# State of the art (what I have and want)

I have

\documentclass[tikz,border=1cm]{standalone}

\tikzstyle{mybar} = [rounded corners=1mm,fill=blue!40!white, draw=black]
\tikzstyle{mytext} = [rectangle, below=1mm, anchor=south, align=center, font=\sffamily, scale=1]

\newlength{\zerox} \setlength{\zerox}{0cm}
\newlength{\zeroy} \setlength{\zeroy}{0cm}

\newlength{\arrowheight} \setlength{\arrowheight}{0.8cm}
\newlength{\arrowlength} \setlength{\arrowlength}{21cm}
\newlength{\arrowhead} \setlength{\arrowhead}{1.5cm}

\newcommand{\dtl}[2]{{((#1-6)+(#2-0.5)/12)*2cm}}
\newcommand{\level}[1]{{(#1-1)*11mm+\zeroy+0.5*\arrowheight+4mm}}

\begin{document}

\begin{tikzpicture}

\filldraw[mybar] (\dtl{14}{4},\level{1}) rectangle (\dtl{16}{1},\level{1.2});
\node[mytext] at (\dtl{15}{2},\level{1.2}){The Text};

\end{tikzpicture}

\end{document}


which should result in

This is what I want. As seen, I want to have "The Text" in the middle of the bar.

The reason the code seems so complicated, is because of the way it is embedded in my real work. For example \dtl (meaning "date length") calculates the coordinates for given year and month. The bar goes from middle of April 2014 to middle of January 16. Another example is level - which is also because of the greater context of the code.

My question is thus not about getting the final result, but making the code easier to use (not the code of the node itself):

# What I want to change

I would like the two lines of tikzpicture in one node-command and the position of the text automatically calculated from the bar's left and right edges. Somehing like

\node[start={14}{4}, end={16}{1}, newbar={1.2}] {The Text};


Here I only provide provide the left start and right end and the level. I do not need to provide the lower and upper positions anymore (as it is required in the upper MWE in filldraw via the coordinates).

I thought that one way to go about this might be to let the text to be the node and draw the bar with append after command and provide the start ({14}{4}), the end ({16}{1}), and the level ({1}) via parameters. I started with the code, but I don't know how to go about to use \start, \end and \level to set the rectangle, the node etc.

My idea is to have a command like

\tikzset{
start/.style args = {2}{\gdef\start{\dtl{#1}{#2}}},
end/.style args = {2}{\gdef\end{\dtl{#1}{#2}}},
newbar/.style = {
append after command = {
... \start ... \end ... \level{#1}
}
}
}


However this (of course) does not work yet. The three ... indicate code that yet needs to be written. Can you help me with that?

# Details

I would like to have a node as shown but as you can see, the idea is to have three styles to get the result wished for.

## Parameters I'd like to control

• start
• end
• level (the vertical position of the bar and text in space = distance from the coordinate (0,0))

## Positioning

... is supposed to take place by the left end of the bar = horizontal "start", the right end of the bar = horizontal "end", and the vertical position of the bar with the text = called "level". The distances between the text and the bar and the height of the bar should be set globally for all the text-bars (there are many). The text should be horizontally centered in respect to the bar by default, but optionally swayed left or right a bit.

## Context

I thought http://rainnic.altervista.org/content/two-ideas-infographic-cv-using-latex-and-tikz is pretty neat - not just for CVs, so I want to recreate (but with better code) something like

• Mmh your code doesn't compile. In fact, I get 15 errors. But basically, you want to draw a bar with text above it? What parameters do you want to control? Sorry, I couldn't quite understand from your question. And do you want this as a \node or a \newcommand? Jan 7, 2016 at 21:27
• (1) Your MWE unfortunately gives an error, (2) it is very complicated (I must confess, I was lost in it) for the result showed in picture (I make a test, where above image is obtain in one short line: \node[N=32mm/2mm/The Text]; , (3) from your description I'm not able to figured out, what you like to achieve. Can you provide some hand drawn sketch of desired result? Or make simple description of your goal. Jan 7, 2016 at 21:28
• Why can't you make the text part just using label=above:The Text and set label distance or whatever you prefer?
– cfr
Jan 7, 2016 at 21:42
• @Alenanno: Better? I'd prefer a \node. Jan 7, 2016 at 22:01
• @Zarko: Better? I want what I've shown. Jan 7, 2016 at 22:09

## 1 Answer

Edit: After many iteration finally you show, what you like to achieve.

Simple solution: The simplest way to achieve desired picture (considering only bars with text) you can obtain width:

\documentclass[tikz,border=1cm]{standalone}
\usetikzlibrary{quotes}

\tikzset{BAR/.style = {%
every edge quotes/.style = {% " Bar Node"
font=\scriptsize\sffamily,
align=center,
inner sep=0.5mm,
auto},
BL/.style = {% " Bar Line"
draw=blue!50!gray!40!white,
line width=1.2mm,
line cap=round}}
}% end of tikzset

\begin{document}
\begin{tikzpicture}[BAR]
\draw[BL] (2,2) edge["The long\\two line Text"] ++ (3.3,0);
\draw[BL] (0,1) edge["The Text"] ++ (4.4,0);
\draw[BL] (0,0) edge[swap,"The Text"] ++ (4.4,0);
\draw[BL] (5,0) edge[swap,"Text longer than bar"] ++ (1.1,0);
\end{tikzpicture}
\end{document}


In this example start and end of bar line is determined with absolute coordinate beginning of bar line and its end width relative coordinate -- its shift to right. Text above/below bars is written in quotes, and can be in more lines. Line broken should be done manually. For working of above MWE the TikZ library quotes is needed.

For text below bar line, you need to add to edge parameter swap.

Not so simple solution: Based on the first sketch in the question. There presented bar is the simplest determine width the node, which fit coordinates defines its start and end. Using nodes enable use shadings for its fill (what in the first solution is not possible).

Text here is set as label to this node, for its positioning is introduced parameters (above, below are appropriates ones)

\documentclass[tikz,border=1cm]{standalone}
\usetikzlibrary{fit,shadings}

% start position of bar (determined with absolute coordinate}
\newcommand\startbar[1]{\path (#1) coordinate (startb);}
% end position of bar (determined by relative}
\newcommand\stopbar[1]{\path  (startb) ++ (#1,0) coordinate (stopb);}

\tikzset{BAR/.style = {%
bar/.style args = {##1/##2}{%
label=##1:##2,
%    draw, very thin,
minimum height=1.6mm,
rounded corners=\pgfkeysvalueof{/pgf/minimum height}/2,
inner sep=0pt,
%    fill= blue!50!gray!40!white
top color=blue!60, bottom color=blue!60, middle color=blue!10,
fit=(startb) (stopb),
node contents={}},
every label/.append style = {%
font=\scriptsize\sffamily,
label distance=1pt, % set to desired distance
align=center,       % multi line text
inner sep= 0pt},    % eliminate inner sep influence
}
}% end of tikzset

\begin{document}
\begin{tikzpicture}[BAR]
\startbar{2,2}\stopbar{3.3}\node[bar=above/The long\\long two line Text];
\startbar{1,1}\stopbar{4.4}\node[bar=above/The Text];
\startbar{0,0}\stopbar{4.4}\node[bar=below/The Text];
\startbar{5,0}\stopbar{1.1}\node[bar=below/Text longer than bar];
\end{tikzpicture}
\end{document}


Imitation of second image in question: For exercise and to show, how bars can be included in second image presented in question. As base is selected the second example:

\documentclass[tikz,border=1cm]{standalone}
\usetikzlibrary{fit,shadings,shapes.symbols}

\newcommand\startbar[1]{\path (#1) coordinate (startb);}
\newcommand\stopbar[1]{\path  (startb) ++ (#1,0) coordinate (stopb);}

\tikzset{BAR/.style = {%
%
base/.style = {%
inner sep=0pt,
top color=blue!60, bottom color=blue!60, middle color=blue!10,
fit=(startb) (stopb),
node contents={}
},
%
bar/.style args = {##1/##2}{base,%
label=##1:##2,
minimum height=1.6mm,
rounded corners=\pgfkeysvalueof{/pgf/minimum height}/2},
%
timeline/.style = {base,%
shape=signal, signal to=east,
minimum height=5mm},
%
year/.style = {%
shape=circle,
draw, fill=gray!10,
inner sep=1pt,
font=\scriptsize\sffamily},
%
every label/.append style = {%
font=\scriptsize\sffamily,
label distance=1pt, % set to desired distance
align=center,       % multi line text
inner sep= 0pt},    % eliminate inner sep influence
}
}% end of tikzset

\begin{document}
\begin{tikzpicture}[BAR]
\startbar{2,2}\stopbar{3.3}\node[bar=above/The long\\long two line Text];
\startbar{1,1}\stopbar{4.4}\node[bar=above/The Text];
\startbar{0,0}\stopbar{4.4}\node[bar=below/The Text];
\startbar{0,0.5}\stopbar{7}\node[timeline];
\foreach \y [count=\i] in {2009,2010,...,2015}
\node[year] at (\i-0.5,0.5) {\y};
\startbar{5,0}\stopbar{1.1}\node[bar=below/Text longer than bar];
\end{tikzpicture}
\end{document}


• Getting closer... Position is supposed to take place by the left end of the bar = horizontal "start", the right end of the bar = horizontal "end", and the vertical position of the bar with the text = called "level". The distances between the text and the bar and the height of the bar should be set globally for all the text-bars (there are many). The text should be horizontally centered in respect to the bar by default, but optionally swayed left or right a bit. Jan 8, 2016 at 0:15
• @Make42, please play with examples. change coordinates an see what will happen. Temporary the distance of tect from bar is set glabaly (with default values. Also the definition of bars can be set globaly (moved outside from tikzpicture. I will show you, how to do this. Jan 8, 2016 at 0:18
• I'll get into it tomorrow (hopefully). It's getting really late here. Jan 8, 2016 at 0:21
• Ok, here is also early in the morning ... meanwhile I will add third solution. Jan 8, 2016 at 0:27