Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'd like to put 3 beamer blocks on one frame and connect them in a circular order.

I tried something with TikZ but it doesn't work.

The main problem is that the points n1.south and n2.south in the following code are really under the end of the blocks.

\documentclass[aspectratio=169]{beamer}
\usepackage{tikz}
\usetheme{Frankfurt}

\tikzset{
  every overlay node/.style={
    %draw=black,fill=white,rounded corners,
    anchor=north west,
  },
}
% Usage:
% \tikzoverlay at (-1cm,-5cm) {content};
% or
% \tikzoverlay[text width=5cm] at (-1cm,-5cm) {content};
\def\tikzoverlay{%
   \tikz[baseline,overlay]\node[every overlay node]
}%

\begin{document}

\begin{frame}
\tikzoverlay (n1) at (8cm,2cm) {
  \begin{minipage}{0.4\textwidth}
    \begin{block}{title1}
      {Text1}
    \end{block}
  \end{minipage}
};

\tikzoverlay (n2) at (0cm,2cm) {
  \begin{minipage}{0.4\textwidth}
    \begin{block}{title2}
      Text2
    \end{block}
  \end{minipage}
};

\tikzoverlay (n3) at (5cm,0cm) {
  \begin{minipage}{0.4\textwidth}
    \begin{block}{Title3}
      Text3
    \end{block}
  \end{minipage}
};

\begin{tikzpicture}[overlay]
  \path [line width=0.3cm,->] (n1.south) edge (n3.south);
  \path [line width=0.3cm,->] (n3.north) edge (n2.south);
  \path [line width=0.3cm,->] (n2.east) edge (n1.west);

\end{tikzpicture}


\end{frame}
\end{document}
share|improve this question
2  
It's not exactly what you want, but PowerPoint's “Smart Art” for TikZ? could be useful. –  Ignasi Feb 1 '13 at 9:08
    
+1 because that package might be useful in future, but what I want now is to have blocks with the exact look of the standard beamer blocks. –  Robbo Feb 1 '13 at 9:43

2 Answers 2

up vote 6 down vote accepted

I fixed your code at some points:

  1. The most important, you have to give also the remember picture option to your overlays. Without it, the name of each node does not refer to the proper coordinates, since they are nodes in a different tikz picture.
  2. baseline option is not really required in this case.
  3. inner sep set to zero for the block nodes
  4. % added at the end of some lines to prevent vertical space (which still happens, I don't know why, and can be made visible by uncommenting the first line of the every overlay node style.

The resulting code is:

\documentclass[aspectratio=169]{beamer}
\usepackage{tikz}
\usetheme{Frankfurt}

\tikzset{
  every overlay node/.style={
    %draw=black,fill=white,rounded corners,
    anchor=north west, inner sep=0pt,
  },
}
% Usage:
% \tikzoverlay at (-1cm,-5cm) {content};
% or
% \tikzoverlay[text width=5cm] at (-1cm,-5cm) {content};
\def\tikzoverlay{%
   \tikz[remember picture, overlay]\node[every overlay node]
}%

\begin{document}

\begin{frame}
\tikzoverlay (n1) at (8cm,2cm) {%
  \begin{minipage}{0.4\textwidth}%
    \begin{block}{title1}%
      {Text1}
    \end{block}
  \end{minipage}
};

\tikzoverlay (n2) at (0cm,2cm) {%
  \begin{minipage}{0.4\textwidth}%
    \begin{block}{title2}%
      Text2
    \end{block}
  \end{minipage}
};

\tikzoverlay (n3) at (5cm,0cm) {%
  \begin{minipage}{0.4\textwidth}%
    \begin{block}{Title3}%
      Text3
    \end{block}
  \end{minipage}
};

\begin{tikzpicture}[remember picture, overlay]
  \path [line width=0.3cm,->] (n1.south) edge (n3.south);
  \path [line width=0.3cm,->] (n3.north) edge (n2.south);
  \path [line width=0.3cm,->] (n2.east) edge (n1.west);
\end{tikzpicture}
\end{frame}
\end{document}

Which produces (after compiling twice):

result

Which is ugly, IMHO, but I guess it is what you was asking for.

Edit:

When I wrote the above code, I didn't pay attention to the values of the coordinates where each node was drawn. I assumed that the result with node2 at different level than node1 was intentional. But the OP comment made me realize that indeed both nodes use the same y-coordinate, so, why they are not aligned?

The reason is that they are not drawn in the same tikzpicture, so they don't share the space of coordinates. Each tikzpicture (or \tikz command) starts its own coordinate system. So the new question is "why then it almost worked?".

The reason for this is that each figure has the option overlay, which means that independently of what the picture actually draws, the space reserved by tex for that picture is zero. It is a dimensionless point. That point is then the origin of the figure.

So if we had three figures without space inbetween, since each is seen by tex as a dimensionless point, the three will be drawn "at the same point", and thus their coordinate systems will match. But if the figures are separated by words, then each one will have its own origin.

It happens that in your case the figures are separated by blank spaces and even by `\par, because there are empty lines in the source code, and end-of-lines between figures.

The solution is then to remove all this unwanted space, by removing blank lines between figures and commenting-out the carriage returns at the end of each figure (which would otherwise produce a space):

\documentclass[aspectratio=169]{beamer}
\usepackage{tikz}
\usetheme{Frankfurt}

\tikzset{
  every overlay node/.style={
    %draw=black,fill=white,rounded corners,
    anchor=north west, inner sep=0pt,
  },
}
% Usage:
% \tikzoverlay at (-1cm,-5cm) {content};
% or
% \tikzoverlay[text width=5cm] at (-1cm,-5cm) {content};
\def\tikzoverlay{%
   \tikz[remember picture, overlay]\node[every overlay node]
}%

\begin{document}

\begin{frame}
\tikzoverlay (n1) at (8cm,2cm) {%
  \begin{minipage}{0.4\textwidth}%
    \begin{block}{title1}%
      {Text1}
    \end{block}
  \end{minipage}
};%
\tikzoverlay (n2) at (0cm,2cm) {%
  \begin{minipage}{0.4\textwidth}%
    \begin{block}{title2}%
      Text2
    \end{block}
  \end{minipage}
};%
\tikzoverlay (n3) at (5cm,0cm) {%
  \begin{minipage}{0.4\textwidth}%
    \begin{block}{Title3}%
      Text3
    \end{block}
  \end{minipage}
};%
%
\begin{tikzpicture}[remember picture, overlay]
  \path [line width=0.3cm,->] (n1.south) edge (n3.south);
  \path [line width=0.3cm,->] (n3.north) edge (n2.south);
  \path [line width=0.3cm,->] (n2.east)  edge (n1.west);
\end{tikzpicture}
\end{frame}
\end{document}

Result:

result

share|improve this answer
1  
It's probably due to the content placement mechanism of beamer. First parses the content and fixes and then adjusts the placement within the canvas. It also happens if you use regular blocks in columns environment. –  percusse Feb 1 '13 at 10:58
    
Thanks! But...why the two upper blocks are still misaligned?? I thought it was a problem bound to my main problem... –  Robbo Feb 1 '13 at 11:13
    
@Robbo I fixed the alignment issue, and, more importantly, explained why it happened. –  JLDiaz Feb 1 '13 at 11:30

JLDiaz explained you how to fix your code, but the result could be improved. The solution I suggest perhaps is not perfect because is something that requires a bit of care, but provides a better result IMHO.

It is based on the package textpos to position the blocks, on Changing default width of blocks in beamer to customize the block width and on the \tikzmark macro to identify blocks.

Actually, what is interesting in your solution, is the mechanism in which you identified blocks putting them inside a TikZ node for later connect them using the node's anchors. This solution, however, uses textpos thus: how to identify the whole block? That's the reason why \tikzmark is needed. Notice that using textpos helps in not having such problems of vertical misalignment.

The \tikzmark is built in such a way that the node could be extended in its width and in its height (that's the part that requires a bit of care): notice that the height of the block ultimately depends on your content, so my suggestion is 1) first write the content 2) fix its height later.

The point of the mark identified is exactly in the center of the block title and the node identifies an area larger than the block:

enter image description here

As you can see from the picture, half of the node built via \tikzmark is empty: this is done to ensure that connecting parallel blocks the arrow could be realized by means of something like

\path[line width=0.2cm](n2.east)edge[bend left](n1.west);

As a consequence, the upper part remains empty and you should be aware of this behaviour in case you draw connections starting/ending on the top of the block. This problem has been fixed in a particular way with a special anchor.

The code showing all stuff:

\documentclass[aspectratio=169]{beamer}
\usepackage{lmodern}
\usepackage{tikz}
\usepackage[overlay]{textpos}
\usetheme{Frankfurt}

\newcommand{\tikzmark}[2][minimum width=6cm,minimum height=1.5cm]{
 \tikz[remember picture,overlay]
 \node[anchor=west,
       inner sep=0pt,
       outer sep=6pt,
       xshift=-0.5em,
       yshift=-3ex,
       #1](#2){};
}

\newcommand{\shownode}[1]{
  \tikz[remember picture,overlay]\draw[red](#1.south east)rectangle(#1.north west);
}

\newcommand{\showanchor}[1]{
  \tikz[remember picture,overlay]\draw[red,thick,mark=x] plot coordinates{(#1)};
}

% original code from Stefan Kottwitz
% http://tex.stackexchange.com/a/12551/13304
\newenvironment<>{varblock}[2][.9\textwidth]{%
  \setlength{\textwidth}{#1}
  \begin{actionenv}#3%
    \def\insertblocktitle{#2}%
    \par%    
    \usebeamertemplate{block begin}%
    }
  {\par%
    \usebeamertemplate{block end}%
  \end{actionenv}}

\newenvironment{myblock}[1]{\begin{textblock*}{500pt}(#1)}{\end{textblock*}}

% special way to reach the top of the block
\def\newabove(#1){
([yshift=1.5ex]#1.center)
}

\begin{document}
\begin{frame}
\begin{myblock}{0.55\textwidth, -0.2\textheight}
    \tikzmark{n1}
    \shownode{n1}    
    %remove the previous line: just used to see where the invisible node is placed
    \begin{varblock}[6cm]{title1}
    text1
    \end{varblock}
    \showanchor{n1}
    %remove also this: just used to see where n1 is positioned
\end{myblock}

\begin{myblock}{0em, -0.2\textheight}
    \tikzmark{n2}
    \shownode{n2}
    \begin{varblock}[6cm]{title2}
    text2
    \end{varblock}
    \showanchor{n2}
\end{myblock} 

\begin{myblock}{0.3\textwidth, 0.2\textheight}
    \tikzmark[minimum width=5cm,minimum height=2.25cm]{n3} % customization of width and height
    \shownode{n3}
    \begin{varblock}[5cm]{title3}
    text3\\
    text
    \end{varblock}
    \showanchor{n3}
\end{myblock}

\begin{tikzpicture}[remember picture,overlay,-stealth]
\path[line width=0.2cm](n2.east)edge[bend left](n1.west);
\path[line width=0.2cm](n1.south)edge[bend left](n3.east);
\path[line width=0.2cm](n3.west)edge[bend left](n2.south);
% in case you need to connect some block from ``north''
%\path[line width=0.2cm](n3.north)edge[bend left](n1.south west); % is wrong
\path[line width=0.2cm]\newabove(n3) edge[bend left](n1.south west);
\end{tikzpicture}
\end{frame}
\end{document}

Removing all stuff to make visible nodes and anchors and the special path showing how to reach the top of the block, you end up with:

enter image description here

which I guess is what you wanted.

How to deal with the height problem of blocks

Since this could be a cons of the procedure, let's have an example.

At first one should care about the content of the blocks without considering height or other stuff. For instance:

\documentclass[aspectratio=169]{beamer}
\usepackage{lmodern}
\usepackage{tikz}
\usetheme{Frankfurt}
\usepackage[overlay]{textpos}

\newcommand{\tikzmark}[2][minimum width=6cm,minimum height=1.5cm]{
 \tikz[remember picture,overlay]
 \node[anchor=west,
       inner sep=0pt,
       outer sep=6pt,
       xshift=-0.5em,
       yshift=-3ex,
       #1](#2){};
}

\newcommand{\shownode}[1]{
  \tikz[remember picture,overlay]\draw[red](#1.south east)rectangle(#1.north west);
}

\newcommand{\showanchor}[1]{
  \tikz[remember picture,overlay]\draw[red,thick,mark=x] plot coordinates{(#1)};
}

% original code from Stefan Kottwitz
% http://tex.stackexchange.com/a/12551/13304
\newenvironment<>{varblock}[2][.9\textwidth]{%
  \setlength{\textwidth}{#1}
  \begin{actionenv}#3%
    \def\insertblocktitle{#2}%
    \par%    
    \usebeamertemplate{block begin}%
    }
  {\par%
    \usebeamertemplate{block end}%
  \end{actionenv}}

\newenvironment{myblock}[1]{\begin{textblock*}{500pt}(#1)}{\end{textblock*}}

% special way to reach the top of the block
\def\newabove(#1){
([yshift=1.5ex]#1.center)
}

\begin{document}
\begin{frame}

\begin{myblock}{0cm,-2.5cm}
    \tikzmark{n1}
    \begin{varblock}[6cm]{title1}
    Hello! :) This is the text of my block. Here I want to say
    that the height of the blocks is not so problematic.
    \end{varblock}
\end{myblock}

\begin{myblock}{8cm,-2.5cm}
    \tikzmark{n2}
    \begin{varblock}[6cm]{title2}
    This is my very long block with even an equation:
    \[\Delta_n=
     \begin{cases}
       1 \quad q_n>0\\
       0 \quad q_n=0
     \end{cases}
    \]
    \end{varblock}
\end{myblock}


% I can leave all blank lines I want




\begin{myblock}{8cm,2cm}
    \tikzmark{n3}
    \begin{varblock}[6cm]{title3}
    Short text
    \end{varblock}
\end{myblock}



\begin{myblock}{0cm,2cm}
    \tikzmark{n4}
    \begin{varblock}[6cm]{title4}
    Short text
    \end{varblock}
\end{myblock}

\begin{tikzpicture}[remember picture,overlay,-stealth,line width=0.2cm]
\draw (n1.east)--(n2.west);
\draw (n2.south)--\newabove(n3);
\draw (n3.west)--(n4.east);
\draw \newabove(n4)--(n1.south);
\end{tikzpicture}
\end{frame}
\end{document}

Notice that I intentionally left some blank lines. After two compilation runs we get:

enter image description here

Oh.. there's a problem with blocks 1 and 2. Why? Because the height is wrong; using our \shownode and \showanchor it is possible to understand the reason:

enter image description here

Notice now that the default value is 1.5cm for the height. Thus something like 0.75cm for a block with the title and one line in the body.

In the block 1 we have 4 lines+the title, so roughly speaking, we have three times the standard height: 0.75cm x 3=2.25cm. This however is just the block so to have the whole node we should multiply by two again. Totally: 4.5cm.

Look now at the second block: it is just a bit higher that block 1. I guess that's 1cm higher, so let's put 5.5cm.

So we have to update:

\begin{myblock}{0cm,-2.5cm}
    \tikzmark[minimum width=6cm, minimum height=4.5cm]{n1}
    \shownode{n1}
    \begin{varblock}[6cm]{title1}
    Hello! :) This is the text of my block. Here I want to say
    that the height of the blocks is not so problematic.
    \end{varblock}
    \showanchor{n1}
\end{myblock}

\begin{myblock}{8cm,-2.5cm}
    \tikzmark[minimum width=6cm, minimum height=5.5cm]{n2}
    \shownode{n2}
    \begin{varblock}[6cm]{title2}
    This is my very long block with even an equation:
    \[\Delta_n=
     \begin{cases}
       1 \quad q_n>0\\
       0 \quad q_n=0
     \end{cases}
    \]
    \end{varblock}
    \showanchor{n2}
\end{myblock}

This provides:

enter image description here

More or less we're done. But I'm still unsatisfied with block 2: it's not very precise. I guess we need 0.25cm more. So:

\begin{myblock}{8cm,-2.5cm}
    \tikzmark[minimum width=6cm, minimum height=5.75cm]{n2}
    \shownode{n2}
    \begin{varblock}[6cm]{title2}
    This is my very long block with even an equation:
    \[\Delta_n=
     \begin{cases}
       1 \quad q_n>0\\
       0 \quad q_n=0
     \end{cases}
    \]
    \end{varblock}
    \showanchor{n2}
\end{myblock}

This gives:

enter image description here

Oh.. bad. Too much! Ok, let's shorten it a bit to 5.7cm. This will be for sure right. In conclusion:

enter image description here

share|improve this answer
    
Why do you think using textpos for placing blocks is better than using TkiZ? With TkiZ I have no to worry about the height of the blocks. I am not able to see the advantages of textpos solution. –  Robbo Feb 2 '13 at 10:36
    
Simply because you don't have to care about vertical misalignments due to spaces or end of lines. I guess that you probably took your \tikzoverlay from Christian's answer and there it is said that textpos is weaker, but as you noticed, put lot of overlayed TikZ pictures requires to pay attention in writing the code. –  Claudio Fiandrino Feb 2 '13 at 10:53
    
I highlighted the problems of blocks' height, but actually that's something very easy to be solved: it's like when you decide the width of a minipage. If you want to use this approach, just write the content of your blocks with the standard \tikzmark. When you connect things you will notice that some connections are longer or shorter; so you can come back to the problematic block by changing the optional argument of the \tikzmark with a different width and height and you're done. I don't think this procedure is problematic. –  Claudio Fiandrino Feb 2 '13 at 10:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.