Исправление стрелок и галочек в Tikz

Исправление стрелок и галочек в Tikz

Как исправить стрелки и отметки (годы) внизу, чтобы они выглядели хорошо. Кроме того, как добавить линию от столбцов к номеру года внизу, как показано на прикрепленном изображении.

Вот мой результат.

введите описание изображения здесь

Вот мой код

\documentclass[a4paper,12pt,titlepage,twoside,final,openany]{book}
\usepackage{tikz}
\usetikzlibrary{arrows.meta} % Arrows library
\usepackage[pdftex,a4paper=true,pagebackref=false]{hyperref} % with basic options
\usepackage[left=2cm,right=2cm,top=2cm,bottom=4.5cm]{geometry}% Redefine the page margins 


\begin{document}
    \begin{tikzpicture}[x=\textwidth/47] % Adjusted scale
        % Draw the horizontal line with an arrow at the end, extending beyond 2040
        \draw[thick, -{Triangle[length=3mm, width=2mm]}] (0,0) -- (47,0); % Extend line beyond 2040
        
        % Draw tick marks and label for each year from 1994 to 2040
        \foreach \year in {1994,1995,...,2040} {
            \pgfmathsetmacro{\xpos}{\year-1994}
            \draw (\xpos,0.25) -- (\xpos,-0.25) node[below] {\tiny \year};
        }
        
        
        % Additional gradient bar from 2016 to 2040
        \shade[left color=green, right color=red, middle color=yellow] (22,2.6) rectangle (46,3.0);
        % Add text inside the additional colored bar
        \node[text=black] at (36,2.8) {20neo};
        % Red dashed arrow starting at the end of the "A330-900" gradient bar
        \draw[dashed, ->, >=latex, line width=0.2cm, draw=red] (46.2,2.8) -- (47.2,2.8);
        
        
        % Gradient bar from 2020 to 2040
        \shade[left color=green, right color=red, middle color=yellow] (26,2) rectangle (46,2.4);
        % Add text inside the additional colored bar
        \node[text=black] at (36,2.2) {800};
        % Red dashed arrow starting at the end of the "A330-800" gradient bar
        \draw[dashed, ->, >=latex, line width=0.2cm, draw=red] (46.2,2.2) -- (47.2,2.2);
        
        
        % Gradient bar from 2018 to 2040
        \shade[left color=green, right color=red, middle color=yellow] (24,1.4) rectangle (46,1.8);
        % Add text inside the new colored bar
        \node[text=black] at (35,1.6) {900};
        % Red dashed arrow starting at the end of the "A330-900" gradient bar
        \draw[dashed, ->, >=latex, line width=0.2cm, draw=red] (46.2,1.6) -- (47.2,1.6);
        
        
        % Draw colored bar (red) from 1998 to 2019 for A330-200
        \fill[red] (4,0.8) rectangle (25,1.2);
        % Add text inside the red colored bar
        \node[text=white] at (14.5,1.0) {200};
        % Draw a dashed line at the level and height of the red colored bar from 2019 to 2039
        \draw[dashed, red, line width=0.4cm] (25,1.0) -- (45,1.0); % Line from 2019 to 2039
        
        
        % Draw a blue colored bar from 1994 to 2020 above the horizontal line
        \fill[blue] (0,0.3) rectangle (26,0.7);
        % Add text inside the blue colored bar
        \node[text=white] at (13,0.5) {300};
        % Draw a dashed blue line from 2020 to 2040 at the level and height of the first colored bar
        \draw[dashed, blue, line width=0.4cm] (26,0.5) -- (46,0.5); % Line up to 2040
        
        
    \end{tikzpicture}
    
\end{document}

решение1

Если вы хотите нарисовать более одной диаграммы, я предлагаю подход, который использует несколько ключей, чтобы удалить многие жестко закодированные значения и вычисления.

Функцию yearможно использовать для вычитания значения 2000 из чисел года. Функция PGFMath оценивает величину сокращения спецификации конечного наконечника, чтобы изменить место, где заканчивается затененный прямоугольник.

Оба контура, размещающие планки, являются одним путем, так что их markerможно нарисовать на заднем плане.

Код

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta}
\makeatletter
\pgfmathdeclarefunction{arrowlengthend}{0}{%
  \begingroup\nullfont
    \pgf@arrow@compute@shortening\pgf@end@tip@sequence
    \pgfmath@returnone\pgf@xa\endgroup}
\makeatother
\tikzset{
  outer sep=auto,
  reset row counter/.code=\setcounter{tikzrowcounter}{0},
  increment row/.code=\stepcounter{tikzrowcounter}%
                      \tikzset{shift=(up:\value{tikzrowcounter})},
  edges/.style={every edge/.append style={#1}},
  rect to/.style={to path=rectangle(\tikztotarget)\tikztonodes}}
\newcounter{tikzrowcounter}
\tikzset{
  bar height/.initial=4mm,         % controls the height of the bars
  bar/.style={line width=\pgfkeysvalueof{/tikz/bar height}},
  bar arrow rect/.style={
    draw=none, left color=green, right color=red, middle color=yellow, rect to},
  bar arrow style/.style={
    nodes=black, bar, -{Latex[red, length=+0pt +2, width=+0pt +1.4]}},
  bar dashy/.style={dashed, dash phase=3pt},
  bar marker style/.style={arrows=-{Latex[round]}, thick, purple, line to},
  %
  bar with dash/.style args={#1-#2-#3:#4}{
    edges=bar, nodes=white,
    insert path={
      (year #1, 0) edge[line to]   node{#4} (year #2, 0)
      (year #2, 0) edge[line to, bar dashy] (year #3, 0)
      [bar marker={#1}]}},
  bar with tip/.style args={#1-#2:#3}{
    bar arrow style, nodes=black,
    insert path={
      (year #1,-\pgfkeysvalueof{/tikz/bar height}/2) edge[bar arrow rect] node{#3}
      ([xshift=-arrowlengthend]year #2, \pgfkeysvalueof{/tikz/bar height}/2)
      (year #1,0) edge[line to, tips, path only] (year #2, 0)
      [bar marker={#1}]}},
  bar marker/.style={
    insert path={
      node[purple!50!black, rotate=90, above, scale=.6] at (year #1, 0) {#1}
      [behind path](year #1, -\pgfkeysvalueof{/tikz/bar height}/2) coordinate(@)
                    edge[bar marker style={#1}] (@|-start)}},
  %
  bar diagram/.style={
    y=6mm,             % controls the distance between rows
    declare function={year(\y)=\y-2000;},
    reset row counter}} % if you have more than one diagram
\begin{document}
\begin{tikzpicture}[x=\textwidth/47, bar diagram]
\draw[thick, -{Triangle[length=3mm, width=2mm]}, shorten <=+-1mm, shorten >=+-4mm]
     (year 1994,0) coordinate (start) -- (year 2040,0);
\draw[thin, xstep=1, ystep=0] (year 1994, -1.00mm) grid (year 2040, 1.00mm);
\draw[thin, xstep=5, ystep=0] (year 1994, -2.00mm) grid (year 2040, 2.00mm);
\foreach \y in {1995, 2000, ..., 2040}
  \node[below] at (year \y, -2.5mm) {\y};

\path % one path allows us to easily place the marker in the background
      % see “behind path” in style “marker”
  foreach \c/\t in {blue/1994-2020-2040:300, red/1998-2019-2039:200}{
    [increment row, edges=\c, bar with dash/.expand once=\t]
  }
  foreach \t in {2018-2040:900, 2020-2040:800, 2016-2040:20neo}{
    [increment row, bar with tip/.expand once=\t]
  };
\end{tikzpicture}
\end{document}

Выход

введите описание изображения здесь

решение2

  • чтобы закрепить стрелку, сshorten >=-4pt

  • Для лучшего вида отметьте галочками (годы) ниже, предлагаю указывать каждые 5 лет

  • добавить линию от столбцов до номера года, с\draw

  • Для улучшения читабельности вы можете определить стили в tikzset

  • Вы также можете использовать циклы

  • Я не упростил последние такты...

     \documentclass[border=5mm]{standalone}
     \usepackage{tikz}
     \usetikzlibrary{arrows.meta} % Arrows library
    
     \begin{document}
     \tikzset{
         myarrow/.style = {thick,-{Triangle[length=3mm, width=2mm]},shorten <=-2pt-\pgflinewidth,},
         myshade/.style = {left color=green, right color=red, middle color=yellow},
         mytext/.style = {black},
         myBigarrow/.style = {->, >=latex, shorten >=-4pt,line width=0.2cm, draw=red},
         mymark/.style = {blue},
         }
     \begin{tikzpicture}[x=\textwidth/47] % Adjusted scale
         % Draw the horizontal line with an arrow at the end, extending beyond 2040
         \draw[myarrow] (0,0) -- (47.5,0); %<-- change in 47.5  Extend line beyond 2040
    
         % Draw tick marks and label for each year from 1994 to 2040
         \foreach \year in {1994,1995,...,2040} {
             \pgfmathsetmacro{\xpos}{\year-1994}
             \draw (\xpos,0.15) -- (\xpos,-0.15);
         }
         \foreach \year in {1995,2000,...,2040} {
             \pgfmathsetmacro{\xpos}{\year-1994}
             \draw [thick](\xpos,0.25) -- (\xpos,-0.25) node[below] {\tiny \year};
         }
    
         % Additional gradient bar from 2016 to 2040
         \foreach \x/\y/\lib in {22/2.6/20neo,24/1.4/800,26/2/900}%
             {
                 \shade[myshade] (\x,\y) rectangle (45.4,\y+0.4) node[midway]{\lib};
                 \draw[myBigarrow] (46.2,\y+0.2) -- +(1,0);        
                 \draw [mymark](\x,\y) -- (\x,0);
                 }
    
         % Draw colored bar (red) from 1998 to 2019 for A330-200
         \fill[red] (4,0.8) rectangle (25,1.2);
         % Add text inside the red colored bar
         \node[text=white] at (14.5,1.0) {200};
         % Draw a dashed line at the level and height of the red colored bar from 2019 to 2039
         \draw[dashed, red, line width=0.4cm] (25,1.0) -- (45,1.0); % Line from 2019 to 2039
    
    
         % Draw a blue colored bar from 1994 to 2020 above the horizontal line
         \fill[blue] (0,0.3) rectangle (26,0.7);
         % Add text inside the blue colored bar
         \node[text=white] at (13,0.5) {300};
         % Draw a dashed blue line from 2020 to 2040 at the level and height of the first colored bar
         \draw[dashed, blue, line width=0.4cm] (26,0.5) -- (46,0.5); % Line up to 2040
     \end{tikzpicture}
     \end{document}
    

введите описание изображения здесь

решение3

Вот как это сделать. Некоторые замечания:

  1. Я думаю, вам не следует забывать включать transform shape.

  2. Я сделал некоторый рефакторинг grad, и добавил новый стиль ln, в котором вы можете изменять внешний вид вертикальных линий. Рисуйте их в последнюю очередь, если они должны перезаписывать другие полосы.

  3. Я внес предложение о ротации номеров лет.

  4. Затененные полосы выглядят немного странно: вероятно, есть лучший способ сделать это. Пока что я просто уменьшил размер прямоугольника на 0,4 см, так что он останавливается до начала кончика. Предлагаю также переработать опции, связанные с кончиком.

  5. Для ссылки на левые стороны полос я запоминаю их координаты, например \shade[grad] (22,2.6) coordinate (S1) .., ., и использую их позже.

  6. Наконец, нарисуйте все эти вертикали, как \draw[ln] (S1) -- +(0,-2.6);, которые вы могли бы сократить до \foreachпетли, которая принимает значение pais как (ориентировочно)S1*-2.6

результат

\documentclass[a4paper,12pt,titlepage,twoside,final,openany]{book}
\usepackage{tikz}
\usetikzlibrary{arrows.meta} % Arrows library
\usepackage[pdftex,a4paper=true,pagebackref=false]{hyperref} % with basic options
\usepackage[left=2cm,right=2cm,top=2cm,bottom=4.5cm]{geometry}% Redefine the page margins 


\begin{document}
    % <<< don't forget transform shape ~~~~~~~~~~~~~~~~~~~~~~~~~~
    \begin{tikzpicture}[x=\textwidth/47,transform shape, % Adjusted scale
        % <<< some refactoring ~~~~~~~~~~~~~~~~
        grad/.style={left color=green, right color=red, middle color=yellow},
        % <<< new ~~~~~~~~~~~~
        ln/.style={dashed,line width=3pt,teal},
    ]
        % Draw the horizontal line with an arrow at the end, extending beyond 2040
        \draw[thick, -{Triangle[length=3mm, width=2mm]}] (0,0) -- (47,0); % Extend line beyond 2040
        
        % Draw tick marks and label for each year from 1994 to 2040
        \foreach \year in {1994,1995,...,2040} {
            \pgfmathsetmacro{\xpos}{\year-1994}
            % <<< suggestion ~~~~~~~~~~~~~~~~~~~~~~~~
            \draw (\xpos,0.25) -- (\xpos,-0.25) 
                                    node[anchor=east,rotate=90] {\tiny \year};
        }
        
        
        % Additional gradient bar from 2016 to 2040
        % <<< remember left coordinates ~~~~~~~~~~~~~~~
        \shade[grad] (22,2.6) coordinate (S1) rectangle (45.6,3.0);%<<< suggestion
        % Add text inside the additional colored bar
        \node[text=black] at (36,2.8) {20neo};
        % Red dashed arrow starting at the end of the "A330-900" gradient bar
       \draw[dashed, ->, >=latex, line width=0.2cm, draw=red] (46.2,2.8) -- (47.2,2.8);
        
        
        % Gradient bar from 2020 to 2040
        \shade[grad] (26,2) coordinate (S2) rectangle (46,2.4);
        % Add text inside the additional colored bar
        \node[text=black] at (36,2.2) {800};
        % Red dashed arrow starting at the end of the "A330-800" gradient bar
        \draw[dashed, ->, >=latex, line width=0.2cm, draw=red] (46.2,2.2) -- (47.2,2.2);
        
        
        % Gradient bar from 2018 to 2040
        \shade[grad] (24,1.4) coordinate (S3) rectangle (46,1.8);
        % Add text inside the new colored bar
        \node[text=black] at (35,1.6) {900};
        % Red dashed arrow starting at the end of the "A330-900" gradient bar
        \draw[dashed, ->, >=latex, line width=0.2cm, draw=red] (46.2,1.6) -- (47.2,1.6);
        
        
        % Draw colored bar (red) from 1998 to 2019 for A330-200
        \fill[red] (4,0.8) coordinate (B1) rectangle (25,1.2);
        % Add text inside the red colored bar
        \node[text=white] at (14.5,1.0) {200};
        % Draw a dashed line at the level and height of the red colored bar from 2019 to 2039
        \draw[dashed, red, line width=0.4cm] (25,1.0) -- (45,1.0); % Line from 2019 to 2039
        
        
        % Draw a blue colored bar from 1994 to 2020 above the horizontal line
        \fill[blue] (0,0.3) coordinate (B2) rectangle (26,0.7);
        % Add text inside the blue colored bar
        \node[text=white] at (13,0.5) {300};
        % Draw a dashed blue line from 2020 to 2040 at the level and height of the first colored bar
        \draw[dashed, blue, line width=0.4cm] (26,0.5) -- (46,0.5); % Line up to 2040

        % <<< lines; you could replace it by a foreach on value-pairs ~~~~
        \draw[ln] (S1) -- +(0,-2.6);
        \draw[ln] (S2) -- +(0,-2.0);
        \draw[ln] (S3) -- +(0,-1.4);
        \draw[ln] (B1) -- +(0,-0.8);
        \draw[ln] (B2) -- +(0,-0.3);
        
        
    \end{tikzpicture}
    
\end{document}

Связанный контент