3

I'm trying to draw a curved arrow that passes through multiple nodes. This is for a beamer presentation. The idea of the frame is to pose the audience a question, tell them the answer, and then gradually go through a roadmap of the steps involved as follows: Roadmap to answering a question

I have three questions:

  1. How to draw the blue arrow (more aesthetically pleasing)? By this, I mean, smaller arrow head, arrow should be incident onto the 'Answer' node. And the nodes should be "above" the arrow, as in, the arrow should be "sent behind" the nodes.
  2. How to reveal a part of the arrow along with the stops along the roadmap. i.e, (part of arrow+Stop 1+Comment 1) appear on first click (slide 2).
  3. Reveal the 'question' and 'answer' first, then the roadmap. But currently the positioning of the 'answer' is relative to the roadmap and beamer doesn't reveal it until the end. What am I doing wrong here?

I am looking to move forward with minimum code-disruption. Thank you. A MWE is attached.

\documentclass[usenames, dvipsnames]{beamer}
\usepackage{tikz}
\usepackage{amsmath}
\usetikzlibrary{automata,fit, backgrounds,shapes,arrows,calc,positioning}

\begin{document}

% Define block styles
\tikzstyle{block} = [rectangle, draw, fill=blue!20, 
    text width=5em, text centered, rounded corners, minimum height=4em]
\tikzstyle{wideblock} = [rectangle, draw, fill=blue!20, 
    text width=8em, text centered, rounded corners, minimum height=4em]
\tikzstyle{greenblock} = [rectangle, draw, fill=ForestGreen!20, 
    text width=8em, text centered, rounded corners, minimum height=4em]
\tikzstyle{plainblock} = [rectangle, draw, fill=blue!05, 
    text width=8em, text centered, rounded corners, minimum height=4em]
\tikzstyle{line} = [draw, -latex']

\begin{frame}{How we got to the answer}
\resizebox{0.8\linewidth}{!}{%
\begin{tikzpicture}[node distance = 7cm, auto]
\linespread{1}
\node[wideblock,text width=16em](main_ques){Question?};
%first stop along the road-map
\onslide<2->\node[plainblock, yshift=-1cm, right of = main_ques](map1){Stop 1};
\onslide<2->\node[plainblock, right of = map1](map1_comment){Comment 1}; 
\onslide<2->\path[line](map1) -- (map1_comment);
%second stop along the road-map
\onslide<3->\node[plainblock, yshift=-3cm, right of = map1, node distance = 2cm](map2){Stop 2};
\onslide<3->\node[plainblock, right of = map2](map2_comment){Comment 2}; 
\onslide<3->\path[line](map2) -- (map2_comment);
%third stop along the road-map
\onslide<4->\node[plainblock, yshift=-3cm, node distance = 2cm, right of = map2](map3){Stop 3};
\onslide<4->\node[plainblock, right of = map3](map3_comment){Comment 3}; 
\onslide<4->\path[line](map3) -- (map3_comment);
%fourth stop along the road-map
\onslide<5->\node[plainblock,yshift=-1cm, node distance = 2cm, below of = map3](map4){Stop 4};
\onslide<5->\node[plainblock, right of = map4](map4_comment){Comment 4}; 
\onslide<5->\path[line](map4) -- (map4_comment);
%fifth stop along the road-map
\onslide<6->\node[plainblock,yshift=-3cm, node distance = 2cm, left of = map4](map5){This is a really really long sentence};
\onslide<6->\node[plainblock, right of = map5](map5_comment){comment 5}; 
\onslide<6->\path[line](map5) -- (map5_comment);
%Sixth stop along the road-map
\onslide<7->\node[plainblock,yshift=-3cm, node distance = 2cm, left of = map5](map6){Stop 5};
\onslide<7->\node[plainblock, right of = map6, text width = 12em](map6_comment){This is a very long comment that requires a bigger text box}; 
\onslide<7->\path[line](map6) -- (map6_comment);
%This is the answer that should appear on the first slide itself.
\node[greenblock, yshift=-1cm, left of = map6](ans){Answer};
\path[line](main_ques) -- (ans);
\end{tikzpicture}}
\end{frame}
\end{document}
7
  • Note that \tikzstyle is deprecated. – cfr May 3 '17 at 0:42
  • 1
    What do you mean by 'more aesthetic'? Presumably 'more aesthetically pleasing' but, since beauty is very much in the eye of the beholder, you need to say what you would like to be different about it. – cfr May 3 '17 at 0:43
  • 1
    For your third question, you need \onslide<7->{...} rather than just \onslide<7->... which affects everything following it, including your final node. – cfr May 3 '17 at 0:45
  • Thanks @cfr, I edited the question to reflect what I meant by the aesthetic part. And thanks for your answer to the third question. – Roe1 May 3 '17 at 1:12
  • 1
    It is helpful to explain these things. 'I want a nicer arrow' makes me think the code produces an arrow, at least for you, if not for me. 'I want an arrow, but this powerpoint attempt is pretty crude and I hope for a nicer one' is more verbose, but also more explanatory. – cfr May 3 '17 at 1:30
4

The current code doesn't draw an arrow for me at all. I've updated the deprecated syntax (mostly - annotated elsewhere), added a curve with hobby, corrected the overlay specifications so that they are scoped properly and created overlay-specific clippings for the new arrow, which is drawn behind the nodes with a smaller arrow head than that pictured. Adjust to suit.

\documentclass[usenames, dvipsnames]{beamer}
\usepackage{tikz}
\usepackage{amsmath}
\usetikzlibrary{arrows,calc,backgrounds,positioning,hobby,arrows.meta}% arrows is deprecated, too

\begin{document}

% Define block styles
\tikzset{% \tikzstyle is deprecated
  block/.style = {rectangle, draw, fill=blue!20, text width=5em, text centered, rounded corners, minimum height=4em},
  wideblock/.style = {rectangle, draw, fill=blue!20, text width=8em, text centered, rounded corners, minimum height=4em},
  greenblock/.style = {rectangle, draw, fill=ForestGreen!20, text width=8em, text centered, rounded corners, minimum height=4em},
  plainblock/.style = {rectangle, draw, fill=blue!05, text width=8em, text centered, rounded corners, minimum height=4em},
  line/.style = {draw, -latex'},
}

\begin{frame}{How we got to the answer}
  \resizebox{0.8\linewidth}{!}{%
    \begin{tikzpicture}[node distance = 7cm, auto]
      \linespread{1}
      \node[wideblock,text width=16em](main_ques){Question?};
      %first stop along the road-map
      \onslide<2->{\node[plainblock, yshift=-1cm, right of = main_ques](map1){Stop 1};
        \node[plainblock, right of = map1](map1_comment){Comment 1};
        \path[line](map1) -- (map1_comment);}
      %second stop along the road-map
      \onslide<3->{\node[plainblock, yshift=-3cm, right of = map1, node distance = 2cm](map2){Stop 2};
        \node[plainblock, right of = map2](map2_comment){Comment 2};
        \path[line](map2) -- (map2_comment);}
      %third stop along the road-map
      \onslide<4->{\node[plainblock, yshift=-3cm, node distance = 2cm, right of = map2](map3){Stop 3};
        \node[plainblock, right of = map3](map3_comment){Comment 3};
        \path[line](map3) -- (map3_comment);}
      %fourth stop along the road-map
      \onslide<5->{\node[plainblock,yshift=-1cm, node distance = 2cm, below of = map3](map4){Stop 4};
        \node[plainblock, right of = map4](map4_comment){Comment 4};
        \path[line](map4) -- (map4_comment);}
      %fifth stop along the road-map
      \onslide<6->{\node[plainblock,yshift=-3cm, node distance = 2cm, left of = map4](map5){This is a really really long sentence};
        \node[plainblock, right of = map5](map5_comment){comment 5};
        \path[line](map5) -- (map5_comment);}
      %Sixth stop along the road-map
      \onslide<7->{\node[plainblock,yshift=-3cm, node distance = 2cm, left of = map5](map6){Stop 5};
        \node[plainblock, right of = map6, text width = 12em](map6_comment){This is a very long comment that requires a bigger text box};
        \path[line](map6) -- (map6_comment);}
      %This is the answer that should appear on the first slide itself.
      \node[greenblock, yshift=-1cm, left of = map6](ans){Answer};
      \path[line](main_ques) -- (ans);
      \begin{scope}[on background layer]
        \onslide<2->
        \only<2>{\clip (current bounding box.north west) rectangle (map1.south east);}
        \only<3>{\clip (current bounding box.north west) rectangle (map2.south east);}
        \only<4>{\clip (current bounding box.north west) rectangle (map3.south east);}
        \only<5>{\clip (current bounding box.north west) rectangle (map4.south east);}
        \only<6>{\clip (current bounding box.north west) rectangle (map5.south -| current bounding box.east);}
        \only<7>{\clip (current bounding box.north west) rectangle (map6.south -| current bounding box.east);}
        \only<8>{\clip (current bounding box.north west) rectangle (current bounding box.south east);}
        \draw [blue!50!cyan, line width=1.5pt, -{Triangle[width=2.5mm,length=2.5mm]}] (main_ques.east) to [curve through=($(map1)!.5!(map2)$) ($(map3)!.5!(map4)$) ($(map5)!.5!(map6)$)] (ans.east);
      \end{scope}
    \end{tikzpicture}%
  }
\end{frame}
\end{document}

incremental arrow

Note to editors: Please do NOT convert my image to, or replace it with, a GIF. If I wanted it to be animated, I'd have created one myself. Thank you.

2
  • Thanks for the answer @cfr, this is elegant. Could you briefly explain the logic behind your answer? I still don't understand how clip and hobby do what they're doing here. Also, I was wondering if there was way to go from 'Stop 5' to 'ans' directly without the pause in between. – Roe1 May 3 '17 at 4:07
  • 1
    @Roe1 Just remove the last \only<7> and \only<8> lines. Hobby just draws smooth curves through points. Otherwise, it is hard to get a smooth curve without lots of trial-and-error. The clippings are just clipping to the specified rectangular areas. So only the part of the curve inside the specified rectangle is shown. The curve is the same on all slides, but the rectangular region to which it is clipped changes. – cfr May 3 '17 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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