11

I got a image as below from internet,but I am not sure which tool is used to drawing it. Does Tikz has such library to do it? Or how can we draw it in Tikz effectively.

enter image description here

Beatlej
  • 1,723
  • nice diagram but no such library in Tikz so far as I know. but it should doable by Tikz. – lucky1928 Mar 08 '15 at 19:56
  • here is an example with some of your features http://tex.stackexchange.com/questions/108774/how-can-i-make-a-standard-timeline Also you should look at the chronosys documentation at texdoc.net. And here is a nice way to build timeline with images by making it 'multilevel' on a single page http://tex.stackexchange.com/questions/199556/multi-level-timeline – R. Schumacher Mar 08 '15 at 20:28
  • See also the timeline library demonstrated, for example, here and here. (Weird variant of mine is here.) – cfr Mar 09 '15 at 01:12

1 Answers1

22

Improved version

(Older versions can be seen in the edit history of this answer)

enter image description here

This image was produced with the code (explanations at the bottom):

\begin{timeline}
\TimeLine{%
    1/red1/{},%
    2/red2/{},%
    8/yellow1/{30--60 days},%
    1/yellow2/{},%
    12/yellow3/{30--90 days},%
    4/green1/{10--30 days},%
    6/green2/{30--45 days}%
  }
\AddText[text=white]{red1}{Initial \\ meeting}{2}{L}
\AddText{red2}{List \\ property}{2}{m}
\AddText{yellow1}{Listing \\ period}{3}{M}
\AddText{yellow2}{Offer \\ received}{4}{L}
\AddText{yellow2}{Offer \\ signed}{4}{m}
\AddText{yellow3}{File under \\ review}{5}{M}
\AddText[xshift=-3pt]{green1}{Negotiator \\ assigned}{6}{L}
\AddText{green1}{Offer in final \\ review}{6}{m}
\AddText[xshift=3pt]{green2}{Short sale\\ approved}{7}{L}
\AddText{green2}{Under \\ contract}{7}{m}
\AddText[text=white]{green2!80!black}{Vacate \& \\ close}{7}{R}
\end{timeline}

The complete code:

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{calc,positioning,shapes.multipart,decorations.pathreplacing,shapes.arrows}

\definecolor{red1}{RGB}{195,0,0}
\definecolor{red2}{RGB}{246,136,93}
\definecolor{yellow1}{RGB}{247,175,47}
\definecolor{yellow2}{RGB}{255,192,96}
\definecolor{yellow3}{RGB}{255,255,96}
\definecolor{green1}{RGB}{214,249,121}
\definecolor{green2}{RGB}{113,158,65}

% vertical separation between timeline and text boxes
\def\TextShift{15pt}

\tikzset{
  myrect/.style={
    rectangle split, 
    rectangle split horizontal,
    rectangle split parts=#1,
    draw,
    anchor=west,
  },
  mytext/.style={
    arrow box,
    draw=#1!70!black,
    fill=#1,
    align=center,
    line width=1pt,
    font=\sffamily
  },
  mytextb/.style={
    mytext=#1,
    anchor=north,
    arrow box arrows={north:0.5cm}  
  },
  mytexta/.style={
    mytext=#1,
    anchor=south,
    arrow box arrows={south:0.5cm}  
  }
}

\newcommand\AddTextA[4][]{
  \node[mytexta=#2,#1] at #3 {#4};
}
\newcommand\AddTextB[4][]{
  \node[mytextb=#2,#1] at #3 {#4};
}
\newcommand\AddText[5][]{
  \if#5l\relax
    \node[mytextb=#2,yshift=-\TextShift,#1] 
      at (part#4.south west) {\strut#3\strut};
  \fi
  \if#5L\relax
    \node[mytexta=#2,yshift=\TextShift,#1] 
      at (part#4.north west) {\strut#3\strut};
  \fi
  \if#5m\relax
    \node[mytextb=#2,yshift=-\TextShift,#1] 
      at ( $ (part#4.south west)!0.5!(part#4.south east) $ ) {\strut#3\strut};
  \fi
  \if#5M\relax
    \node[mytexta=#2,yshift=\TextShift,#1] 
      at ( $ (part#4.north west)!0.5!(part#4.north east) $ ) {\strut#3\strut};
  \fi
  \if#5r\relax
    \node[mytextb=#2,yshift=-\TextShift,#1] 
      at (part#4.south east) {\strut#3\strut};
  \fi
  \if#5R\relax
    \node[mytexta=#2,yshift=\TextShift,#1] 
      at (part#4.north east) {\strut#3\strut};
  \fi
}

\newcommand\TimeLine[1]{%
\coordinate (part0);  
\foreach \Longitud/\Color/\Texto [count=\ti] in {#1}
{
  \node[
    myrect=\Longitud,
    fill=\Color,
    right=of part\the\numexpr\ti-1\relax
    ] 
      (part\ti)
      {};
  \draw 
    ([yshift=-15pt]part\ti.east) coordinate (upper\ti) -- 
    ([yshift=15pt]part\ti.east) coordinate (lower\ti);
  \node[font=\footnotesize]
    at (part\ti.center) {\Texto};  
  \gdef\lastpart{\ti}
}
\foreach \Nodo in {2,...,\lastpart}
{
  \ifodd\Nodo\relax
  \draw[decoration={brace,mirror},decorate] 
    (lower\Nodo) -- (lower\the\numexpr\Nodo-1\relax);
  \else
  \draw[decoration=brace,decorate] 
    (upper\Nodo) -- (upper\the\numexpr\Nodo-1\relax);
  \fi    
}
}

\newenvironment{timeline}[1][]
  {\begin{tikzpicture}[node distance=0pt and -\pgflinewidth,#1]}
  {\end{tikzpicture}}

\begin{document}

\begin{timeline}
\TimeLine{%
    1/red1/{},%
    2/red2/{},%
    8/yellow1/{30--60 days},%
    1/yellow2/{},%
    12/yellow3/{30--90 days},%
    4/green1/{10--30 days},%
    6/green2/{30--45 days}%
  }
\AddText[text=white]{red1}{Initial \\ meeting}{2}{L}
\AddText{red2}{List \\ property}{2}{m}
\AddText{yellow1}{Listing \\ period}{3}{M}
\AddText{yellow2}{Offer \\ received}{4}{L}
\AddText{yellow2}{Offer \\ signed}{4}{m}
\AddText{yellow3}{File under \\ review}{5}{M}
\AddText[xshift=-3pt]{green1}{Negotiator \\ assigned}{6}{L}
\AddText{green1}{Offer in final \\ review}{6}{m}
\AddText[xshift=3pt]{green2}{Short sale\\ approved}{7}{L}
\AddText{green2}{Under \\ contract}{7}{m}
\AddText[text=white]{green2!60!black}{Vacate \& \\ close}{7}{R}
\end{timeline}

\end{document}

Explanation

  1. I defined an environment timeline and a \TimeLine command to easily produce the timeline; the command takes as mandatory argument a comma separated list in the form

    \TimeLine{<value-1>/<color-1>/<text-1>,...,<value-n>/<color-n>/<text-n>}
    

    For example, by using

    \begin{timeline}
    \TimeLine{%
        1/red1/{},%
        2/red2/{},%
        8/yellow1/{30--60 days},%
        1/yellow2/{},%
        12/yellow3/{30--90 days},%
        4/green1/{10--30 days},%
        6/green2/{30--45 days}%
      }
    \end{timeline}
    

    one gets

    enter image description here

  2. The text boxes are typeset using a node, through an \AddText command with syntax

    \AddText[<options for the node>]{<color>}{<text>}{<position>}{<number>}
    

    where <position> can be l, m, or r (for left, middle, or right, resp.) below the timeline, or L, M, or R (for left, middle, or right, resp.) above the timeline. <number> specifies the number of the part in the timeline which will receive the text. For example, using

    \AddText{red}{text}{l}{5}
    

    will typeset "text" inside a red arrow box to the left of the fifth part of the timeline.

Gonzalo Medina
  • 505,128
  • Nice code. I was playing with it and could not find where the number of blocks in any color is limited to 19. I tried '30/red1/{},%' to test this. – R. Schumacher Mar 09 '15 at 03:31
  • @R.Schumacher Thanks. The problem you mention is most probably a restriction of rectangle split, although there's a way to overcome this (as far as I recall). I'll check this later and let you know. – Gonzalo Medina Mar 09 '15 at 11:56
  • Great answer, can you help explain what's the purpose to add "\relax" at some lines? – Beatlej Mar 09 '15 at 15:31
  • @Beatlej Thanks. Regarding \relax, see for example http://tex.stackexchange.com/q/86385/3954. Short answer: it tells TeX to stop scanning. – Gonzalo Medina Mar 09 '15 at 15:37
  • @R.Schumacher In fact, rectangle split only works as expecte up to 20 parts. I thought that using rectangle split allocate boxes one could overcome this but my tests show me that 20 is the maximum for the number of parts for each rectangle. – Gonzalo Medina Mar 09 '15 at 16:02
  • @GonzaloMedina When I try to add "amplitude=8pt" to brace, it seems big part is fine, but the small parts will display a strange line, it caused by the arrow too big for short distance I guess, but not sure if we can fix it. – Beatlej Mar 09 '15 at 21:54
  • @Beatlej Yes, 8pt is too big a value for a brace spanning short lengths. You could get rid of the code automatically adding the braces and then add them manually with the desired amplitude value for each one, but in my opinion this will make the diagram inconsistent. I'd rather use the same value for all of them (a small value such as 3pt will be OK, I guess). – Gonzalo Medina Mar 09 '15 at 22:03