Some tricks and ideas to achieve this:

- The shape of the node is a "superellipse" instead of a rectangle, which looks more "comic-like" (see question How do I make a superellipse node shape in tikz?)
- Connections between balloons are not double lines, but very thick black lines with a very thick (but less) white line on top. It does the trick if the background is also white.
- The final callout is also tricky. An auxiliar rectangular little white node is used to "erase" the bottom of the last balloon, and also serves as named coordinates to draw the curvy callout.
Code:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}
\newcommand*{\superellipse}[3][draw]{% #1 = styles
% #2 = node
% #3 = superness
\coordinate (ne) at ($(#2.center)!#3!(#2.north east)$);
\coordinate (nw) at ($(#2.center)!#3!(#2.north west)$);
\coordinate (sw) at ($(#2.center)!#3!(#2.south west)$);
\coordinate (se) at ($(#2.center)!#3!(#2.south east)$);
\pgfmathparse{-9.6*#3*#3 + 14.4*#3 - 4.8} % <--------- Magic numbers!
\xdef\tension{\pgfmathresult}
\path[#1]
plot[smooth cycle, tension=\tension] coordinates{
(#2.east) (ne) (#2.north) (nw) (#2.west) (sw) (#2.south) (se)};
% \node {\tension};
}
\tikzset{
connection/.style = {line width=2mm, white, shorten >=-3pt, shorten <=-3pt,
preaction={draw, black, line width=3mm, shorten >=0pt, shorten <=0pt},
}
}
\begin{document}
\begin{tikzpicture}
\node[text width=7em, inner sep=1.5em]
(balloon1) {Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor};
\node[text width=12em, inner sep=1.5em, right=of balloon1.north east]
(balloon2) {incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,};
\node[text width=11em, inner sep=1.5em, below=of balloon2]
(balloon3) {quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat};
\foreach \n in {1,2,3}
\superellipse[draw, very thick]{balloon\n}{0.85};
\draw[connection] ($(balloon1.north east)+(-2ex,-2ex)$) to [out=30, in=180] (balloon2.west);
\draw[connection] (balloon2.south) -- (balloon3.north);
\node[fill=white, minimum width=3mm, minimum height=1mm, inner sep=0] at (balloon3.south) (callout) {};
\draw[very thick] (callout.west) to[bend left] +(-5mm,-1cm) to[bend right] (callout.east);
\end{tikzpicture}
\end{document}
Update.
Some improvements:
- Instead of my
\superellipse macro, I use now the code in the answer by Jake to the question How do I make a superellipse node shape in tikz?. This has the advantage of computing very precisely the anchors in the balloon shape, which simplifies the later connections.
- Instead of putting all Jake's code (it is long!) in the main file, I separated it to a
tikz-superellipse.sty file (code included below). This defines a new node shape called superellipse.
- Created a
balloon style, which accepts as paramter the width of the balloon.
- Text centered by default
- Nice comic font used (downloaded from bancomicsans page, it is the one called "Mighty Zeo", the caps version). Requires
xelatex to compile with this font.
This is the new code:
\documentclass{standalone}
\usepackage{tikz}
\usepackage{fontspec}
\usepackage{tikz-superellipse}
\setmainfont{MIGHZC__.TTF}
\usetikzlibrary{calc,positioning}
\tikzset{
connection/.style = {line width=2mm, white, shorten >=-6pt, shorten <=-6pt,
preaction={draw, black, line width=3mm, shorten >=-3pt, shorten <=-3pt}
},
balloon/.style = {text width=#1, inner sep=.5em, align=center, superellipse,
superellipse parameter=3.5, very thick},
balloon/.default = {11em}
}
\begin{document}
\begin{tikzpicture}
\node[balloon=7em]
(balloon1) {Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor};
\node[balloon, right=of balloon1.north east]
(balloon2) {incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,};
\node[balloon=12em, below=of balloon2]
(balloon3) {quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat};
\draw[connection] (balloon1.north east) to [out=20, in=180] (balloon2.west);
\draw[connection] (balloon2.south) -- (balloon3.north);
\node[fill=white, minimum width=3mm, minimum height=1mm, inner sep=0] at (balloon3.south) (callout) {};
\draw[very thick] (callout.north west) to[bend left] +(-5mm,-1cm) to[bend right] (callout.north east);
\end{tikzpicture}
\end{document}
This is the result:

This is the tikz-superellipse.sty file:
\let\pgfmath@function@exp\relax % undefine old exp function
\pgfmathdeclarefunction{exp}{1}{%
\begingroup
\pgfmath@xc=#1pt\relax
\pgfmath@yc=#1pt\relax
\ifdim\pgfmath@xc<-9pt
\pgfmath@x=1sp\relax
\else
\ifdim\pgfmath@xc<0pt
\pgfmath@xc=-\pgfmath@xc
\fi
\pgfmath@x=1pt\relax
\pgfmath@xa=1pt\relax
\pgfmath@xb=\pgfmath@x
\pgfmathloop%
\divide\pgfmath@xa by\pgfmathcounter
\pgfmath@xa=\pgfmath@tonumber\pgfmath@xc\pgfmath@xa%
\advance\pgfmath@x by\pgfmath@xa
\ifdim\pgfmath@x=\pgfmath@xb
\else
\pgfmath@xb=\pgfmath@x
\repeatpgfmathloop%
\ifdim\pgfmath@yc<0pt
\pgfmathreciprocal@{\pgfmath@tonumber\pgfmath@x}%
\pgfmath@x=\pgfmathresult pt\relax
\fi
\fi
\pgfmath@returnone\pgfmath@x%
\endgroup
}
\let\pgfmath@function@pow\relax % undefine old exp function
\pgfmathdeclarefunction{pow}{2}{%
\begingroup%
\pgfmath@xa=#1pt%
\pgfmath@xb=#2pt%
\ifdim\pgfmath@xa=0pt
\pgfmath@x=0pt\relax
\else
\afterassignment\pgfmath@x%
\expandafter\c@pgfmath@counta\the\pgfmath@xb\relax%
\ifnum\c@pgfmath@counta<0\relax%
\c@pgfmath@counta=-\c@pgfmath@counta%
\pgfmathreciprocal@{#1}%
\pgfmath@xa=\pgfmathresult pt\relax%
\fi
\ifdim\pgfmath@x=0pt\relax%
\pgfmath@x=1pt\relax%
\pgfmathloop%
\ifnum\c@pgfmath@counta>0\relax%
\ifodd\c@pgfmath@counta%
\pgfmath@x=\pgfmath@tonumber{\pgfmath@x}\pgfmath@xa%
\fi
\ifnum\c@pgfmath@counta>1\relax%
\pgfmath@xa=\pgfmath@tonumber{\pgfmath@xa}\pgfmath@xa%
\fi%
\divide\c@pgfmath@counta by2\relax%
\repeatpgfmathloop%
\else%
\pgfmathln@{#1}%
\pgfmath@x=\pgfmathresult pt\relax%
\pgfmath@x=\pgfmath@tonumber{\pgfmath@xb}\pgfmath@x%
\pgfmathexp@{\pgfmath@tonumber{\pgfmath@x}}%
\pgfmath@x=\pgfmathresult pt\relax%
\fi%
\fi
\pgfmath@returnone\pgf@x%
\endgroup%
}
\pgfkeys{
/pgf/superellipse parameter/.store in=\pgf@superellipse@param,
/pgf/superellipse parameter/.default=2,
/pgf/superellipse parameter
}
\newcommand{\pointonsuperellipse}[3]{ % cornerpoint, parameter, directionpoint
\pgf@process{#1}
\edef\size@x{\the\pgf@x}%
\edef\size@y{\the\pgf@y}%
\pgfintersectionofpaths
{
\pgfpathmoveto{\centerpoint}
\pgfpathlineto{
\pgfpointborderrectangle{#3}{#1}
}
\pgfpathclose
}
{
\pgfplothandlercurveto
\pgfplotfunction{\x}{-180,-170,...,170}{
\pgfpoint{
abs(1 * cos(\x))^(2/#2)*( (cos(\x)>0)*2-1 ) * \size@x
}{
abs(1 * sin(\x))^(2/#2)*( (sin(\x)>0)*2-1 ) * \size@y
}
}
\pgfpathclose
}
\pgfpointintersectionsolution{1}
}
\makeatletter
\pgfdeclareshape{superellipse}
%
% Draws a circle around the text
%
{
\savedmacro\superellipseparameter{\edef\superellipseparameter{\pgf@superellipse@param}}
\savedanchor\centerpoint{%
\pgf@x=.5\wd\pgfnodeparttextbox%
\pgf@y=.5\ht\pgfnodeparttextbox%
\advance\pgf@y by-.5\dp\pgfnodeparttextbox%
}
\savedanchor\radius{%
%
% Caculate ``height radius''
%
\pgf@y=.5\ht\pgfnodeparttextbox%
\advance\pgf@y by.5\dp\pgfnodeparttextbox%
\pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
\advance\pgf@y by\pgf@yb%
%
% Caculate ``width radius''
%
\pgf@x=.5\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
\advance\pgf@x by\pgf@xb%
%
% Adjust
%
\pgf@x=1.4142136\pgf@x%
\pgf@y=1.4142136\pgf@y%
%
% Adjust hieght, if necessary
%
\pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/minimum height}}%
\ifdim\pgf@y<.5\pgf@yc%
\pgf@y=.5\pgf@yc%
\fi%
%
% Adjust width, if necessary
%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
\ifdim\pgf@x<.5\pgf@xc%
\pgf@x=.5\pgf@xc%
\fi%
%
% Add outer sep
%
\pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
\advance\pgf@x by\pgf@xb%
\advance\pgf@y by\pgf@yb%
}
\savedmacro\test{\def\test{2}}
%
% Anchors
%
\anchor{center}{\centerpoint}
\anchor{mid}{\centerpoint\pgfmathsetlength\pgf@y{.5ex}}
\anchor{base}{\centerpoint\pgf@y=0pt}
\anchor{north}
{
\pgf@process{\radius}
\pgf@ya=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@y by\pgf@ya
}
\anchor{south}
{
\pgf@process{\radius}
\pgf@ya=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@y by-\pgf@ya
}
\anchor{west}
{
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by-\pgf@xa
}
\anchor{mid west}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by-\pgf@xa%
\pgfmathsetlength\pgf@y{.5ex}
}
\anchor{base west}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by-\pgf@xa%
\pgf@y=0pt
}
\anchor{north west}
{
\pgf@process{\radius}
\def\angle{135}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\pgfpoint{
abs(cos(\angle))^(2/\superellipseparameter)*( (cos(\angle)>0)*2-1 ) * \pgf@xa
}{
abs(sin(\angle))^(2/\superellipseparameter)*( (sin(\angle)>0)*2-1 ) * \pgf@ya
}}
\pgf@xb=\pgf@x%
\pgf@yb=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@x by \pgf@xb
\advance\pgf@y by \pgf@yb
}
\anchor{south west}
{
\pgf@process{\radius}
\def\angle{-135}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\pgfpoint{
abs(cos(\angle))^(2/\superellipseparameter)*( (cos(\angle)>0)*2-1 ) * \pgf@xa
}{
abs(sin(\angle))^(2/\superellipseparameter)*( (sin(\angle)>0)*2-1 ) * \pgf@ya
}}
\pgf@xb=\pgf@x%
\pgf@yb=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@x by \pgf@xb
\advance\pgf@y by \pgf@yb
}
\anchor{east}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by\pgf@xa
}
\anchor{mid east}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by\pgf@xa%
\pgfmathsetlength\pgf@y{.5ex}
}
\anchor{base east}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by\pgf@xa%
\pgf@y=0pt
}
\anchor{north east}
{
\pgf@process{\radius}
\def\angle{45}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\pgfpoint{
abs(cos(\angle))^(2/\superellipseparameter)*( (cos(\angle)>0)*2-1 ) * \pgf@xa
}{
abs(sin(\angle))^(2/\superellipseparameter)*( (sin(\angle)>0)*2-1 ) * \pgf@ya
}}
\pgf@xb=\pgf@x%
\pgf@yb=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@x by \pgf@xb
\advance\pgf@y by \pgf@yb
}
\anchor{south east}
{
\pgf@process{\radius}
\def\angle{-45}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\pgfpoint{
abs(cos(\angle))^(2/\superellipseparameter)*( (cos(\angle)>0)*2-1 ) * \pgf@xa
}{
abs(sin(\angle))^(2/\superellipseparameter)*( (sin(\angle)>0)*2-1 ) * \pgf@ya
}}
\pgf@xb=\pgf@x%
\pgf@yb=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@x by \pgf@xb
\advance\pgf@y by \pgf@yb
}
\anchorborder{
\edef\externalx{\the\pgf@x}%
\edef\externaly{\the\pgf@y}%
\pgf@process{\radius}%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pointonsuperellipse{\pgfpoint{\pgf@xa}{\pgf@ya}}{\superellipseparameter}{\pgfpoint{\externalx}{\externaly}}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\centerpoint%
\advance\pgf@x by\pgf@xa%
\advance\pgf@y by\pgf@ya%
}
\backgroundpath
{
\pgf@process{\radius}%
\pgfutil@tempdima=\pgf@x%
\pgfutil@tempdimb=\pgf@y%
\pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
\advance\pgfutil@tempdima by-\pgf@xb%
\advance\pgfutil@tempdimb by-\pgf@yb%
{
\pgftransformshift{\centerpoint}
\pgfplothandlercurveto
\pgfplotfunction{\x}{-180,-170,...,170}{
\pgfpoint{
abs(1 * cos(\x))^(2/\pgf@superellipse@param)*( (cos(\x)>0)*2-1 ) * \pgfutil@tempdima
}{
abs(1 * sin(\x))^(2/\pgf@superellipse@param)*( (sin(\x)>0)*2-1 ) * \pgfutil@tempdimb
}
}
\pgfpathclose
\pgfgetpath\test
\pgfusepath{stroke}
}
}
}
textposto position your text. – Uwe Ziegenhagen May 21 '14 at 17:30tikZdoes not work well with `beamerposter. How does this show? – Benedikt Bauer May 21 '14 at 17:32