Crea una línea de tiempo curva en Tex

Crea una línea de tiempo curva en Tex

Estoy intentando crear una línea de tiempo que incluya 24 puntos de tiempo colocados en una flecha curva de la siguiente manera:

ingrese la descripción de la imagen aquí

Tengo una versión de una flecha recta (de @Gonzalo Medina), pero es más larga que el ancho de la página, por lo que quiero tener una línea de tiempo curva como la anterior. Me gustaría pedir su ayuda. Muchas gracias.

\documentclass[a4]{article}
\usepackage[margin=0cm]{geometry}
\usepackage{ragged2e}
\usepackage{tikz} 
\usetikzlibrary{chains,shapes.arrows,fit,calc}

\definecolor{arrowcolor}{RGB}{50,130,230}
\definecolor{circlecolor}{RGB}{79,129,189}
\colorlet{textcolor}{white}
\colorlet{bordercolor}{white}

\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\newcounter{task}

\newlength\taskwidth
\newlength\taskvsep

\setlength\taskwidth{2.5cm}
\setlength\taskvsep{17pt}

\def\taskpos{}
\def\taskanchor{}

\newcommand\task[1]{%
  {\parbox[t]{\taskwidth}{\scriptsize\Centering#1}}}

\tikzset{
inner/.style={
  on chain,
  circle,
  inner sep=1pt,
  fill=circlecolor,
  line width=0.5pt,
  draw=bordercolor,
},
on grid
}

\newcommand\Time[2][]{%
\node[inner xsep=0pt] (c1) {\phantom{A}};
\stepcounter{task}
\ifodd\thetask\relax
  \renewcommand\taskpos{\taskvsep}\renewcommand\taskanchor{south}
\else
  \renewcommand\taskpos{-\taskvsep}\renewcommand\taskanchor{north}
\fi
\node[inner,font=\footnotesize\sffamily\color{textcolor}]    
  (c\the\numexpr\value{task}+1\relax) {#1};
\node[anchor=\taskanchor,yshift=\taskpos] 
  at (c\the\numexpr\value{task}+1\relax) {\task{#2}};
}

\newcommand\drawarrow{a
\ifnum\thetask=0\relax
  \node[on chain] (c1) {};
\fi
\node[on chain] (f) {};
\begin{pgfonlayer}{background}
\node[
  inner sep=10pt,
  single arrow,
  single arrow head extend=0.5cm,
  draw=none,
  fill=arrowcolor,
  fit= (c1) (f)
] (arrow) {};
\fill[white] 
  (arrow.before tail) -- (c1|-arrow.east) -- (arrow.after tail) -- cycle;
\end{pgfonlayer}
}

\newenvironment{timeline}[1][node distance=.5\taskwidth]
  {\par\noindent\begin{tikzpicture}[start chain,#1]}
  {\drawarrow\end{tikzpicture}\par}

\begin{document}

\begin{timeline}
\Time[1958]{Task 1}
\Time[1959]{Task 2}
\Time[1960]{Task 3}
\Time[1961]{Task 4}
\Time[1962]{Task 5}
\Time[1963]{Task 6}
\Time[1964]{Task 7}
\Time[1965]{Task 8}
\Time[1966]{Task 9}
\Time[1967]{Task 10}
\Time[1968]{Task 11}
\Time[1969]{Task 12}
\Time[1970]{Task 13}
\Time[1971]{Task 14}
\Time[1972]{Task 15}
\Time[1973]{Task 16}
\Time[1974]{Task 17}
\Time[1975]{Task 18}
\Time[1976]{Task 19}
\Time[1977]{Task 20}
\Time[1978]{Task 21}
\Time[1979]{Task 22}
\Time[1980]{Task 23}
\Time[1981]{Task 24}
\end{timeline}

\end{document}

Árbitro.:¿Cómo puedo hacer una línea de tiempo estándar?[agregado por la comunidad]

Respuesta1

Para empezar...

  • Para una flecha en varias líneas, sugiero usar la arrows.metabiblioteca.

     % p.221
     %\usetikzlibrary {arrows.meta}
     \tikz \draw [line width=1ex,
     {Triangle Cap[reversed]-{Latex[length=0pt +2]}}]
     (0,0) -- (1,0);
    
  • Para la etiqueta tarea1, tarea2... uso \node alsocon label distancein\tikzset

EDITAR: Con una forma más redondeada, uso a circle(con a clip) y agrego 2 argumentos en el bar arrown.° 1 para el inicio y el n.° 2 para el final.

  • Agrego una longitud \arrowvseppara la distancia entre las flechas.

El código

\documentclass[a4paper]{article}
% https://tex.stackexchange.com/questions/715875/create-a-curved-timeline-in-tex
\usepackage[showframe,margin=1cm]{geometry}
\usepackage{tikz} 
\usetikzlibrary{arrows.meta}
\usetikzlibrary {positioning}
\usetikzlibrary {chains}
%  color
\definecolor{arrowcolor}{RGB}{50,130,230}
\definecolor{circlecolor}{RGB}{79,129,189}
\colorlet{textcolor}{white}
\colorlet{bordercolor}{white}
%  length
\newlength\taskwidth
\newlength\taskvsep
\newlength\arrowvsep%<-- added
\setlength\taskwidth{2.cm}
\setlength\taskvsep{1.5ex}
\setlength\arrowvsep{3.cm}
%
\begin{document}
%in th doc p.601
\begin{tikzpicture}[start chain,node distance=5mm]
    % The chain is called just "chain"
    \draw[help lines] (0,-1) grid (2,1);
    \node [on chain] {A};
    \node [on chain] {B};
    \node [on chain] {C};
\end{tikzpicture}

\vspace{1cm}
\begin{tikzpicture}[start chain,node distance=5mm]
    % The chain is called just "chain"
    \draw[help lines] (0,-1) grid (2,1);
    \node [on chain,circle,draw] {A};
    \node [on chain,circle,draw] {B};
    \node [on chain,circle,draw] {C};
\end{tikzpicture}

\vspace{1cm}
%\usetikzlibrary {positioning}
\begin{tikzpicture}[start chain,node distance=1cm,on grid]
    % The chain is called just "chain"
    \draw[help lines] (0,-1) grid (2,1);
    \node [on chain,circle,draw] {A};
    \node [on chain,circle,draw] {B};
    \node [on chain,circle,draw] {C};
\end{tikzpicture}

\vspace{1cm}
\begin{tikzpicture}[start chain=1 going right,
    start chain=2 going left,
    node distance=5mm,
    every node/.style=draw]
    \draw[help lines] (0,-2) grid (3,1);
    \node [on chain=1] {A};
    \node [on chain=1] {B};
    \node [on chain=1] (C){C};
    \node [on chain=2] at ([shift={(0.5cm,-1cm)}]C) {0};
    \node [on chain=2] {1};
    \node [on chain=2] {2};
    \end{tikzpicture}

\vspace{1cm}
        % p.221
        %\usetikzlibrary {arrows.meta}
        \tikz \draw [line width=1cm,
        {Triangle Cap[reversed]-{Latex[length=0pt +2]}}]
        (0,0) -- (5,0);


 \begin{tikzpicture}
    \draw [line width=1cm,
        {Triangle Cap[reversed]-}]
        (0,0) -- (5,0);
        \begin{scope}
            \clip (5,-3) rectangle (6.5,1.5);
            \draw[line width=1cm] (5,-1) circle[radius=1cm]; 
        \end{scope}
    \draw [line width=1cm,
        -{Latex[length=0pt +2]}]
        (5,-2) -- (0,-2);
 \end{tikzpicture}


\tikzset{
    node distance=1.5cm,
    on grid,
    bar height/.initial=1.2cm,
    bar arrow/.style args={#1/#2}%
        {%
            #1-#2,
            arrowcolor,
            line width=\pgfkeysvalueof{/tikz/bar height},
            %rounded corners=5mm
        },
    inner/.style=
        {
            %on chain,
            circle,
            inner sep=1pt,
            minimum width=1cm,
            fill=circlecolor,
            line width=0.5pt,
            draw=bordercolor,
            font=\footnotesize\sffamily\color{textcolor},
        },
    label distance=\taskvsep
}

\vspace{1cm}
\noindent\centering
\fbox{%<--- comment on the final document
    \begin{tikzpicture}
    [%
        trim left=-1.5cm,% begin of the arrow at -1.5
        start chain=1 going right,
        start chain=2 going left,
    ]
    \draw[help lines] (0,0) grid (15,-4);%<-- comment in the final doc
    % \draw[bar arrow] (-1.5,0) -- (15,0) -- ++(0,-\arrowvsep)--(-1.5,-\arrowvsep);
    \draw[bar arrow={Triangle Cap[reversed]/{}}] (-1.5,0) -- (14,0);
    \begin{scope}
        \clip (14,-3.7) rectangle (16.2,1.5);
        \draw[bar arrow={{}/{}}] (14,-0.5\arrowvsep) circle[radius=0.5\arrowvsep]; 
    \end{scope}
    \draw[bar arrow={{}/{{Latex[arrowcolor, length=0pt +2]}}}] (14,-\arrowvsep) -- (-0.5\arrowvsep,-\arrowvsep);
    
    \foreach \i/\d in{
        1/1958,
        2/1958,
        3/1960,
        4/1961,
        5/1962,
        6/1963,
        7/1964,
        8/1965,
        9/1966,
        10/1967}
        {
            \node[inner,on chain=1] (N_\i)  {\d};
            \node also [label=\ifodd\i above\else below\fi:task\i] (N_\i);
        }
    \node [on chain=2] at ([shift={(1cm,-\arrowvsep)}]N_10) {};
    \foreach \i in{11,...,19}
        {
            \node[inner,on chain=2] (N_\i) {Date\i};
            \node also [label=\ifodd\i below\else above\fi:task\i] (N_\i);
        }
    \end{tikzpicture}%
}
\end{document}

ingrese la descripción de la imagen aquí

Respuesta2

Me gustó este tipo de gráfico y vi que se prestaba a las soluciones que tengo para imprimir etiquetas masivas, el camino se dibuja en partes comenzando desde la cola hacia la cabeza, cuando la number of sectionsfila alcanza un valor específico, la curva respectiva es se dibuja y se dibujan los tramos en sentido contrario, luego de completar el doble del valor del número de tramos, se dibuja la otra curva y se pone a cero el contador, haciendo así que el camino crezca automáticamente, finalmente se detiene el cabezal que era necesario acondicionar. los dibujos al ingreso de datos de texto, que en lugar de dibujar el cuerpo dibuja la cabeza cuando esta el texto endy en ese caso hay 2 opciones si va o regresa, si regresa debe colocar reverse, para que dibuje el voy en dirección contraria, aprendí mucho haciendo esto, tomando cosas de aquí y de allá, por eso lo comparto y por el fin de semana en casa.

Hago este tipo de organización de código porque los datos se pueden ordenar en filas, y en el caso de generar etiquetas puedo obtenerlas rápidamente usando una hoja de datos como Excel, por ejemplo, exportando su respectivo formato de código tikz en un cuadro final.

Algunos de los textos los hice completar con un chatbot con ciertos temas, espero que no sean incómodos.

RESULTADO: ingrese la descripción de la imagen aquí

MWE:

\documentclass[tikz,border=1cm]{standalone}
\usepackage{ifthen}
\usepackage{helvet}
\definecolor{arrowcolor}{RGB}{50,130,230}

\begin{document}
    \def\NTsize{\sf\bfseries\normalsize}
    \def\CTsize{\sf\bfseries\normalsize}
    
    \def\BODY#1#2#3#4#5#6#7#8#9{
        \begin{scope}[shift={(#1)},rotate=0,transform shape]
            \ifthenelse{\equal{#2}{end}}{%Draw The end Arrow Head
                \ifthenelse{\equal{#3}{reverse}}{
                    \filldraw[#6]%Reversed Arrow
                        (-1pt,#5*0.5+#7/2)
                            -- ++(#4*0.5+1pt,0)
                            -- ++ (0,3mm) 
                            -- (#4,#5*0.5)
                            -- (#4*0.5,#5*0.5-#7/2-3mm)
                            -- ++(0,3mm)
                            -- ++(-#4*0.5-1pt,0);
                    }{
                    \filldraw[#6]%Normal Arrow
                        (#4+1pt,#5*0.5+#7/2)
                            -- ++(-#4*0.5-1pt,0)
                            -- ++ (0,3mm)
                            -- (0,#5*0.5)
                            -- (#4*0.5,#5*0.5-#7/2-3mm)
                            -- ++(0,3mm)
                            -- ++(#4*0.5+1pt,0);
                }
            }{% Draw the normal body
                \filldraw[#6] (0,#5*0.5+#7/2) rectangle ++(#4,-#7);
                \draw[white](#4*0.5,#5*0.5) node[circle,draw,fill=#6!70!black, minimum size=#7-3mm,font=\NTsize](temp){#2};
                \draw(temp)+(#8:#9) node[text width=#4-3mm, align=center,font=\CTsize](t2){#3};
                \draw[#6!40!white, preaction={draw,#6, line width=2pt}](temp)--(t2);
            }               
        \end{scope} 
    }

    \def\TAIL#1#2#3#4#5{
        \begin{scope}[shift={(#1)}]
            \filldraw[#4] (#2+1pt,#3*0.5+#5/2)-- ++(-#2*0.5-1pt,0) -- (#2*0.75,#3*0.5) -- (#2*0.5,#3*0.5-#5/2) -- ++ (1pt+#2*0.5,0);
        \end{scope} 
    }
    
    \def\CURVE#1#2#3#4#5#6{
        \begin{scope}[shift={(#1)},#4,transform shape]
            \filldraw[#5](-1pt,#3*0.5-#6/2) -- ++(1pt,0) arc (90:-90:#3*0.5-#6/2) -- ++(-1pt,0)-- ++(0,-#6) -- ++(1pt,0) arc (-90:90:#3/2+#6/2)--++(-1pt,0);
        \end{scope} 
    }
    
    \def\SNAKETEXT#1(#2)[#3][#4][#5]#6#7{%\SNAKETEXT{Contents}(Position)[x_dim][y_dim][colour]{tasks_per_line}{arrow size}
        \begin{scope}[shift={(#2)}]
            \edef\Shiftx{0}
            \edef\Shifty{0}
            \pgfmathparse{int(#6*2)}
            \xdef\tpl{\pgfmathresult}
            \foreach \cod/\direc/\dist/\desc [count=\ctr from 0] in {#1}{
                \ifnum\ctr=0
                    \TAIL{\Shiftx*#3,-\Shifty*#4-#4}{#3}{#4}{#5}{#7}
                \fi
                \ifnum\ctr<#6
                    \pgfmathparse{int(\Shiftx+1)}
                    \xdef\Shiftx{\pgfmathresult}
                    \BODY{\Shiftx*#3,-\Shifty*#4-#4}{\cod}{\desc}{#3}{#4}{#5}{#7}{\direc}{\dist}
                \fi
                \ifnum\ctr=#6
                    \pgfmathparse{int(\Shiftx+1)}
                    \xdef\Shiftx{\pgfmathresult}
                    \CURVE{\Shiftx*#3,-\Shifty*#4-#4}{#3}{#4}{}{#5}{#7}
                    \pgfmathparse{int(\Shiftx-1)}
                    \xdef\Shiftx{\pgfmathresult}
                    \pgfmathparse{int(\Shifty+1)}
                    \xdef\Shifty{\pgfmathresult}
                    \BODY{\Shiftx*#3,-\Shifty*#4-#4}{\cod}{\desc}{#3}{#4}{#5}{#7}{\direc}{\dist}
                \fi
                \ifnum\ctr>#6
                    \ifnum\ctr<\tpl
                        \pgfmathparse{int(\Shiftx-1)}
                        \xdef\Shiftx{\pgfmathresult} 
                        \BODY{\Shiftx*#3,-\Shifty*#4-#4}{\cod}{\desc}{#3}{#4}{#5}{#7}{\direc}{\dist}
                    \fi
                \fi
                \ifnum\ctr=\tpl
                    \pgfmathparse{int(\Shiftx-1)}
                    \xdef\Shiftx{\pgfmathresult}
                    \CURVE{\Shiftx*#3+#3,-\Shifty*#4-#4}{#3}{#4}{xscale=-1}{#5}{#7}
                    \pgfmathparse{int(\Shifty+1)}
                    \xdef\Shifty{\pgfmathresult}
                    \pgfmathparse{int(\Shiftx+1)}
                    \xdef\Shiftx{\pgfmathresult}
                    \BODY{\Shiftx*#3,-\Shifty*#4-#4}{\cod}{\desc}{#3}{#4}{#5}{#7}{\direc}{\dist}
                    \xdef\ctr{0}
                \fi
            }
        \end{scope} 
    }
    
    \begin{tikzpicture}
        \SNAKETEXT{
            task1/90/20mm/Detail of task 1,
            task2/-90/20mm/Detail of task 2,
            task3/90/20mm/Detail of task 3,
            task4/-90/20mm/Detail of task 4,
            task5/90/23mm/Some manual text input for more details,
            task6/-90/23mm/Become a Professional Procrastinator,
            task7/90/20mm/Organize Your Clutter,
            task8/-90/20mm/Master the Art of Napping,
            task9/90/20mm/Attend a Productivity Seminar,
            task10/-90/23mm/Create a To-Do List for Doing Nothing,
            task11/-90/20mm/Practice Active Inactivity,
            task12/90/20mm/Become an Expert at Waiting,
            task13/-90/20mm/Write a Book on Doing Nothing,
            task14/90/20mm/Achieving Zen in Pajamas,
            task15/-90/20mm/Watch 10 Hours of Cat Videos,
            task16/90/23mm/Reorganized My Sock Drawer Instead of Studying,
            task17/-90/30mm/Dedicate hours each day to scrolling through social media feeds.,
            task18/90/25mm/Spend hours contemplating the meaning of life,
            task19/-90/20mm/Some task like doing nothing,
            end/end/end/end%
        }(0,0)[25mm][50mm][arrowcolor]{10}{20mm}
    
        %Changing the font sizes
        \def\NTsize{\sf\bfseries\scriptsize}
        \def\CTsize{\sf\bfseries\scriptsize}
        \SNAKETEXT{
            JAN-30/-90/15mm/Polar Bear Plunge Day,
            FEB-29/90/15mm/International Lost Sock Memorial Day,
            MAR-13/-90/15mm/Global Labyrinth Day,
            APR-30/90/15mm/National Awkward Silence Appreciation Day,
            MAY-15/-90/15mm/World Emoji Day,
            JUN-07/-90/15mm/National Talk Like a Pirate Day,
            JUL-15/90/15mm/Global Prohibition Day,
            AUG-12/-90/15mm/National Overthinking Awareness Weeky,
            SEP-06/90/15mm/World Couch Potato Championship,
            OCT-17/-90/15mm/National Socks-with-Sandals Day,
            NOV-28/-90/15mm/ Global Pajama Conference,
            DEC-25/90/15mm/World Simultaneous Eye Roll Day ,
            end/end/end/reverse%
        }(0,-13)[25mm][30mm][green!50!black]{5}{15mm}
    
        %Changing the font sizes
        \def\NTsize{\sf\bfseries\tiny}
        \def\CTsize{\sf\bfseries\tiny}
        \SNAKETEXT{
            A/90/5mm/cmt-stg1,
            B/90/5mm/cmt-stg2,
            C/90/5mm/cmt-stg3
            D/90/5mm/cmt-stg4,
            E/90/5mm/cmt-stg5,
            F/90/5mm/cmt-stg6,
            G/90/5mm/cmt-stg7,
            H/90/5mm/cmt-stg8,
            I/90/5mm/cmt-stg9,
            J/90/5mm/cmt-stg10,
            K/90/5mm/cmt-stg11,
            L/90/5mm/cmt-stg12,
            M/90/5mm/cmt-stg13,
            N/90/5mm/cmt-stg14,
            M/90/5mm/cmt-stg15,
            O/90/5mm/cmt-stg16,
            end/end/end/end%
        }(18,-11)[20mm][10mm][cyan!50!green]{2}{5mm}
    
        %Changing the font sizes
        \def\NTsize{\sf\bfseries\tiny}
        \def\CTsize{\sf\bfseries\tiny}
        \SNAKETEXT{
            A/90/5mm/cmt-stg1,
            B/90/5mm/cmt-stg2,
            C/90/5mm/cmt-stg3
            D/90/5mm/cmt-stg4,
            E/90/5mm/cmt-stg5,
            F/90/5mm/cmt-stg6,
            G/90/5mm/cmt-stg7,
            H/90/5mm/cmt-stg8,
            I/90/5mm/cmt-stg9,
            J/90/5mm/cmt-stg10,
            K/90/5mm/cmt-stg11,
            L/90/5mm/cmt-stg12,
            M/90/5mm/cmt-stg13,
            N/90/5mm/cmt-stg14,
            M/90/5mm/cmt-stg15,
            O/90/5mm/cmt-stg16,
            P/90/5mm/cmt-stg17,
            Q/90/5mm/cmt-stg18,
            end/end/end/reverse%
        }(24,-11)[20mm][10mm][red!50!blue]{2}{5mm}
    \end{tikzpicture}
\end{document}

información relacionada