# Milestone graphic in TikZ

This question led to a new project:
timeline

How could I implement a graphic like this in TikZ?

Several basic requirements:

1. Begin with some arbitrary data input (preferably JSON or CSV) defining the task list, level of effort, and timeline position.
2. Transparency effect used for task bubbles.
3. Description labels placed automatically.

Work in progress borrowed from the Skype Example:

    % Timeline
% Author Jake Hertenstein 2014
% http://jakehertenstein.com/
\documentclass{article}
\usepackage{tikz}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}

\tikzstyle{phase}=[circle,minimum width=20pt]
\tikzstyle{legend}=[]
\begin{document}
\begin{tikzpicture}
\foreach \place/\name in {{(0,0)/a},{(0.5,0)/b},{(1.0,0)/c},{(1.5,0)/d},{(2.0,0)/e}}
%%%%%%%%
\fill[black] (-.1,-.1) rectangle (2.1,0.1);
% Legends
\node[legend] at (0,-2) {Milestones};
\node[legend] at (3,-2) {Involvement};
\node[legend] at (0,2) {Project Milestones};
\end{tikzpicture}
\end{document}

-
Welcome to TeX.SX. Questions about how to draw specific graphics that just post an image of the desired result are really not reasonable questions to ask on the site. Please post a minimal compilable document showing that you've tried to produce the image and then people will be happy to help you with any specific problems you may have. See minimal working example (MWE) for what needs to go into such a document. –  Jubobs Feb 11 at 14:58
What exactly do you want to achieve? Which characteristics of the (quite complex) figure are important to you? Do you want to find an automated way of generating these kinds of graphics? If so, what's your data format? Do the labels need to be placed automatically? –  Jake Feb 11 at 15:10
We're looking to develop a better tool for capturing our software development milestones and this is possibly the best milestone figure I've found yet. We would like to automatically generate the figure based on some input data; possibly CSV or JSON. The bubble size, placement, and color would be good parameters to start with. I'm not sure where to start but I'll try to work on a MWE. –  Jake Hertenstein Feb 11 at 15:16
It's certainly possible to do this, but you will end up asking several more questions here regarding specific difficulties. That's going to happen once you have tried to break the figure down into smaller drawing problems. –  Christoph Feb 11 at 15:22
A few suggestions to read up in the pgfmanual: Part I, section 3 (Petri Net tutorial) for some basics. Part IV, section 46 (shadings) for those nice colours. Finally part VII, section 84 (transparency) to get those overlapping circles to work. –  Turion Feb 11 at 15:35

The latest version of the timeline library can be find in the timeline repository.

This is a start of a solution, which provides the experimental timeline library.

The library introduces three main commands:

1. \timeline for drawing a rectangle with the number of weeks;
2. \phase for drawing bubbles: \phases have to be put in the proper phases environment;
3. \addmilestone for adding milestones to bubbles.

How to use the library?

At first one should declare the number of weeks the timeline spans: the weeks are placed deterministically on the timeline according to their number. The dimensions of the timeline can be customized through the keys timeline width, timeline height and timeline offset (which corresponds to the height of the thin shaded border). For example:

\begin{tikzpicture}[timeline offset=0.2]


For convenience, each week is a node and, as every node, can be accessed for later use; its name is week-<number of the week>; for instance:

\draw (week-1)--++(90:1cm);


will draw a line of 1cm above Week 1.

Then it's the turn of the phases: as stated, they can be inserted through the \phase command within the phases environment. This environment simply puts in the background layer its content so that the timeline will stay in the main layer. Each phase is characterized by a position, a degree and a color; for each property there is a key. The position can be set by between week=<initial> and <end> in <offset> where <intial> is the beginning week, <end> the ending week and <offset> is a number from 0 to 1 which sets the distance from <initial> to <end>. The involvement degree simply sets the radius of the bubble while phase color its color. As well as the weeks, also the phases have an id in the form phase-<number>: it will be useful later on. The <number> is progressive, meaning that it increases each time one adds a phase.

Last, but not least, the milestones. They can be added through the \addmilestone command, which need: a starting position, a direction where the line will go and a text. For the starting position, use the at key, and I suggest to exploit the phase name, i.e. at=phase-1.north (after the dotuse whatever TikZ allows). The direction can be something like 90:1cm and the text sets the label. Some customization of the text can be done through the text options key.

The code of the library:

\usetikzlibrary{backgrounds,calc}

\pgfkeys{/tikz/.cd,
timeline width/.store in=\timelinewidth,
timeline width=20,
timeline height/.store in=\timelineheight,
timeline height=1,
timeline offset/.store in=\timelineoffset,
timeline offset=0.15,
initial week/.store in=\initialweek,
initial week=1,
end week/.store in=\endweek,
end week=2,
time point/.store in=\timepoint,
time point=0.5,
between week/.style args={#1 and #2 in #3}{
initial week=#1,
end week=#2,
time point=#3,
},
involvement degree/.store in=\involvdegree,
involvement degree=2cm,
phase color/.store in=\phasecol,
phase color=red!50!orange,
phase appearance/.style={
circle,
opacity=0.3,
minimum size=\involvdegree,
fill=\phasecol
},
}
\pgfkeys{/tikz/milestone/.cd,
at/.store in=\msstartpoint,
at=phase-1.north,
direction/.store in=\msdirection,
direction=90:2cm,
text/.store in=\mstext,
text={},
text options/.code={\tikzset{#1}},
}

\newcommand{\timeline}[1]{
\draw[fill,opacity=0.8] (0,0) rectangle (\timelinewidth,\timelineheight);
(0,0) rectangle (\timelinewidth,-\timelineoffset);
(0,\timelineheight) rectangle (\timelinewidth,\timelineheight+\timelineoffset);

\foreach \smitem [count=\xi] in {1,...,#1}  {\global\let\maxsmitem\xi}

\pgfmathsetmacro\position{\timelinewidth/(\maxsmitem+1)}
\node at (0,0.5\timelineheight)(week-0){\phantom{Week 0}};

\foreach \x[count=\xi] in {1,...,#1}{
\node[text=white]at +(\xi*\position,0.5\timelineheight) (week-\xi) {Week \x};
}
}

\newcounter{involv}
\setcounter{involv}{0}

\newcommand{\phase}[1]{
\stepcounter{involv}
\node[phase appearance,#1]
(phase-\theinvolv)
at ($(week-\initialweek)!\timepoint!(week-\endweek)$){};
}

\newcommand{\initialphase}[1]{
\node[phase appearance,#1,anchor=west,between week=0 and 1 in 0,]
(phase-\theinvolv)
at ($(week-0)!0!(week-1)$){};
\setcounter{involv}{0}
}

\newenvironment{phases}{\begin{pgfonlayer}{background}}{\end{pgfonlayer}}

\pgfkeys{/tikz/milestone/.cd,#1}
\draw(\msstartpoint)--++(\msdirection)node[/tikz/milestone/text options]{\mstext};
}


A document example:

\documentclass[border=10pt]{standalone}

\usepackage{tikz}
\usetikzlibrary{timeline}

\begin{document}

\begin{tikzpicture}
\timeline{8}% number of weeks

% put here the phases
\begin{phases}
\initialphase{involvement degree=1.75cm,phase color=black}
\phase{between week=1 and 2 in 0.1,involvement degree=2.25cm}
\phase{between week=1 and 2 in 0.5,involvement degree=3cm}
\phase{between week=1 and 2 in 0.9,involvement degree=2.125cm}
\phase{between week=3 and 4 in 0.7,phase color=blue!80!cyan}
\end{phases}

% put here the milestones

\end{tikzpicture}

\end{document}


The result:

-
Wow. Did you just do that on a whim? Amazing –  Leeser Feb 11 at 20:08
@Leeser: glad you like it :) There's still lot of room for improvements, though. –  Claudio Fiandrino Feb 11 at 20:35
+1 For a blazing fast response and solution! –  Jake Hertenstein Feb 12 at 13:36
@JakeHertenstein: :) –  Claudio Fiandrino Feb 12 at 13:43
@ClaudioFiandrino Is the fact that it measures time in weeks hard-coded in a way which would make the library difficult to adapt for more general use? I want to draw a timeline covering thousands of years and it needs to fit on A4... Looks by far the most beautiful timeline I've seen from TeX, though ;). Also, could you please clarify the licence of your github code? –  cfr Jul 12 at 0:36

Some initial ideas here:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
%\usetikzlibrary{calc,intersections}

\begin{document}
\begin{tikzpicture}[week/.style={font=\bfseries, text=white},
initial_contact/.style={fill=black!60,circle,opacity=0.5},
planning/.style={fill=red,circle,opacity=0.5},
content/.style={fill=yellow,circle,opacity=0.5} ]

% Initial phase
\node[initial_contact, minimum size=4em] at (-2, 0) {};

% Planning phase
\node[planning, minimum size=7em] at (0, 0) {};
\node[planning, minimum size=15em] at (3, 0) {};
\node[planning, minimum size=7em] at (5, 0) {};

% Content phase
\node[content, minimum size=7em] at (10, 0) {};

\filldraw[fill=black, draw=white,line width=1ex,opacity=0.75] (-3.5,-0.5) rectangle (54,0.5);
%%%%% Weeks.
\node[week] at (0,0) {WEEK1};
\node[week] at (7,0) {WEEK2};
\node[week] at (14,0) {WEEK3};
\node[week] at (21,0) {WEEK4};
\node[week] at (28,0) {WEEK5};
\node[week] at (35,0) {WEEK6};
\node[week] at (42,0) {WEEK7};
\node[week] at (49,0) {WEEK8};
\end{tikzpicture}
\end{document}

• The weeks are located at 0, 7, 14, etc. So, if week1 (at 0,0) started yesterday (Monday 10) and you have a task on Friday 14, the position of the task would be (4, 0).
• I've made a node for every phase, maybe this could be improved.
• For the loops and the label, I'm going to steal something from @ClaudioFiandrino :P

So, now I read the tasks from a file. The file format is a CSV with phase, taskid, name, position (0 for first week, 7 for the second week, 3.5 for the middle of the first week, etc) and size. The output is the same as before. Right now I put the label in a fixed position. I cannot think of an automatic way of positioning a label without overlapping.

Labels are re-sized according to size.

\documentclass{standalone}
\usepackage{datatool}
\usepackage{tikz}
\usetikzlibrary{positioning}
%\usetikzlibrary{calc,intersections}

\usepackage{filecontents}
initial,initialmeeting,Initial Meeting,-2,4
planning,needsassesment,Needs Assesment,0,7
planning,research,Research,3,15
planning,siteoutline,Site Outline,5,7
content,contentoutline,Content Outline,10,7
\end{filecontents*}

\begin{document}
\begin{tikzpicture}[week/.style={font=\bfseries, text=white},
initial/.style={fill=black!60,circle,opacity=0.5},
planning/.style={fill=red,circle,opacity=0.5},
content/.style={fill=yellow,circle,opacity=0.5} ]

\draw (node cs:name=\taskid, anchor=north) to ++(0,3) node[above, scale=\size/6] {\name};
}

\filldraw[fill=black, draw=white,line width=1ex,opacity=0.75] (-3.5,-0.5) rectangle (54,0.5);

%%%%% Weeks.
\node[week] at (0,0) {WEEK1};
\node[week] at (7,0) {WEEK2};
\node[week] at (14,0) {WEEK3};
\node[week] at (21,0) {WEEK4};
\node[week] at (28,0) {WEEK5};
\node[week] at (35,0) {WEEK6};
\node[week] at (42,0) {WEEK7};
\node[week] at (49,0) {WEEK8};
\end{tikzpicture}
\end{document}


-