16

I'm trying to make a poster in the format of comics. Apart for the fact that tikZ does not work in an amazing way with beamerposter, my idea was to create a sort of comics, with interconnected balloons.

Note that I do not want the single-line connected nodes that usually can be easily reproduced with tikZ. Here the connections are with double lines. Fundamentally, I'm able to draw such a shape, but then I really cannot write in the single square. Any help or tips? enter image description here

The code I'm using is very simple

\documentclass[final,hyperref={pdfpagelabels=false}]{beamer}

\usepackage[english]{babel}

\usepackage[orientation=portrait,size=a0,scale=1.4,debug]{beamerposter}

\usepackage{tikz}

\newlength{\columnheight}

\setlength{\columnheight}{105cm}

\begin{document}

\begin{tikzpicture}

 \draw[line width=0.5ex,rounded corners = 1ex, fill=white, font={peppe}] (0,0) --(0,14)--(20,14)--(20,6.9)--(30,6.9)--(30,14)--(50,14)--(50,0)--(30,0)--(30,6.3)--(20,6.3)--(20,0)--(0,0); 

\end{tikzpicture}
\end{document}
cslstr
  • 6,545
Monkey
  • 161
  • 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. – Benedikt Bauer May 21 '14 at 17:29
  • You could draw the Shape in InkScape and export to TikZ. Then put it in the background and use textpos to position your text. – Uwe Ziegenhagen May 21 '14 at 17:30
  • You write that tikZ does not work well with `beamerposter. How does this show? – Benedikt Bauer May 21 '14 at 17:32
  • the comment about tikz and beamerposter was related to some other attempts I was doing, like for mindmaps. They didn't show at all as in a beamer presentation or in an article. I tried in many ways without any luck. Let me also add that actually I'm not an expert at all of TikZ, so it's possible it is a matter of my ignorance, I'm trying to study as much example as possible, but didn't work out for me. At least at the moment – Monkey May 21 '14 at 17:46

2 Answers2

21

Some tricks and ideas to achieve this:

Example

  1. 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?)
  2. 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.
  3. 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:

  1. 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.
  2. 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.
  3. Created a balloon style, which accepts as paramter the width of the balloon.
  4. Text centered by default
  5. 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:

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}
    }
  }
}
JLDiaz
  • 55,732
12

You can always do it by hand:

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}

\node[fill=green!30,minimum width=2cm,minimum height=3cm] (a) {A};
\node[fill=blue!30,minimum width=3cm,minimum height=3cm,right=1cm of a] (b) {B};
\node[fill=orange!30,minimum width=6cm,minimum height=3cm, below=of b.south east, anchor=north east] (c) {C};
\node[fill=red!30,minimum width=2cm,minimum height=3cm, below=of c.south east, anchor=north east] (d) {D};

\draw[thick] (a.-15)|-(a.south west) |-(a.north east)--(a.3)--(a.3-|b.west)|-(b.north east)|-(b.273)--(b.273|-c.north)-|(c.south east)--(c.-32)--(c.-32|-d.north) -|(d.south east)-|(d.north west)--(d.96)--(d.96|-c.south)-|(c.north west)--(c.55)--(c.55|-b.south)-|(a.-15-|b.west)--(a.-15)--cycle;
\end{tikzpicture}

\end{document}

enter image description here

Update:

Following szantaii suggestion next figure shows the previous figure with some decoration.

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{positioning,decorations.pathmorphing,backgrounds}
\begin{document}

\begin{tikzpicture}

\node[minimum width=2cm,minimum height=3cm] (a) {A};
\node[minimum width=3cm,minimum height=3cm,right=1cm of a] (b) {B};
\node[minimum width=6cm,minimum height=3cm, below=of b.south east, anchor=north east] (c) {C};
\node[minimum width=2cm,minimum height=3cm, below=of c.south east, anchor=north east] (d) {D};

\begin{scope}[on background layer]
\draw[rounded corners=1mm, thick, fill=purple!30, decoration={random steps, segment length=3pt, amplitude=0.5pt},decorate] (a.-15)|-(a.south west) |-(a.north east)--(a.3)--(a.3-|b.west)|-(b.north east)|-(b.273)--(b.273|-c.north)-|(c.south east)--(c.-32)--(c.-32|-d.north) -|(d.south east)-|(d.north west)--(d.96)--(d.96|-c.south)-|(c.north west)--(c.55)--(c.55|-b.south)-|(a.-15-|b.west)--(a.-15)--cycle;
\end{scope}
\end{tikzpicture}

\end{document}

enter image description here

Although this solution is not so nice like JLDiaz one, it doesn't need to use a white (or any other color) line to simulate double lines.

Ignasi
  • 136,588
  • 3
    I think a little path decoration would add a comic like look to this fine answer. Add decorations.pathmorphing to the used TikZ libraries, and add decoration={random steps,segment length=3pt,amplitude=0.5pt}, decorate to the \draw command's options. Sample output here. – szantaii May 21 '14 at 18:06
  • @szantaii Solution updated with your suggestion. Thanks! – Ignasi May 21 '14 at 19:21