我正在尝试绘制一个包含 6 条独立时间线的图形,我希望显示这些时间线并让它们全部对齐到零点。我将它们全部绘制在 y=0 处,但我想对整个时间线进行 y 偏移,这样在绘制每条线时就不需要计算 y 偏移。
在所附的示例中,我怎样才能将整个第二条时间线的页面 y 轴移动 1 厘米,以不覆盖第一条时间线但保持相同的 x 坐标?
\documentclass[a4paper,11pt]{report}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\node[anchor=east] at (-1,0) {\textless Long Label \textgreater};
\draw (-1,0) -- node[fill=white,rotate=90,inner sep=-1.25pt,outer sep=0,anchor=center]{$\approx$} (0,0);
\draw [-latex] (-1,-10pt) -- (-1,0);
\node at (-1,-3ex) {0};
\foreach \x in {0,1,3,5,9,13,14,15} {
\pgfmathsetmacro\result{\x * 4 + 104}
\coordinate (A\x) at ($(0,0)+(\x*0.85cm,0)$) {};
\draw [-latex] ($(A\x)-(0,10pt)$) -- ($(A\x)$) ;
\node at ($(A\x)+(0,-3ex)$) {\pgfmathprintnumber{\result}};
}
\draw (0,0) -- (19,0);
\draw (19,0) -- node[fill=white,rotate=90,inner sep=-1.25pt,outer sep=0,anchor=center]{$\approx$} (20,0);
\draw [-latex] (20,-10pt) -- (20,0);
\node at (20,-3ex) {264};
% How Do I yshift this down 1 cm to keep alignment
\node[anchor=east] at (-1,0) {\textless L2 \textgreater};
\draw (-1,0) -- node[fill=white,rotate=90,inner sep=-1.25pt,outer sep=0,anchor=center]{$\approx$} (0,0);
\draw [-latex] (-1,-10pt) -- (-1,0);
\node at (-1,-3ex) {0};
\foreach \x in {0,3,4,5,9,13} {
\pgfmathsetmacro\result{\x * 4 + 104}
\coordinate (A\x) at ($(0,0)+(\x*0.85cm,0)$) {};
\draw [-latex] ($(A\x)-(0,10pt)$) -- ($(A\x)$) ;
\node at ($(A\x)+(0,-3ex)$) {\pgfmathprintnumber{\result}};
}
\draw (0,0) -- (19,0);
\draw (19,0) -- node[fill=white,rotate=90,inner sep=-1.25pt,outer sep=0,anchor=center]{$\approx$} (20,0);
\draw [-latex] (20,-10pt) -- (20,0);
\node at (20,-3ex) {264};
\end{tikzpicture}
\end{document}
答案1
快速解决
要移动多条路径,可以将它们放在scope
环境中,并在环境的可选参数中添加yshift
、xshift
或,例如shift
\begin{scope}[yshift=-1cm]
% all the code for one of the lines
\end{scope}
也就是说,通过修改用于绘制这样一条线的代码,您既可以获得更简洁的代码,也可以获得更容易修改的代码。
新代码建议
我会先添加一些解释和内容,如果你愿意的话,可以直接跳到最后的代码。
用数字绘制箭头
在您的代码中,您可以分三步完成此操作。首先计算位置,然后绘制箭头,最后打印数字。您可以做的第一个简化是在“\draw”中添加节点,即
\draw [-latex] ($(A\x)-(0,10pt)$) node[below] {\pgfmathprintnumber{\result}} -- ($(A\x)$);
这仍然比必要的更冗长。通过使用相对坐标,你实际上根本不需要使用库中的语法calc
,你可以说
\draw [latex-] (A\x) -- ++(0,-10pt) node[below] {\pgfmathprintnumber{\result}};
请注意,我朝相反的方向画线,并将箭头添加到路径的起点。
不过,你仍然需要\coordinate
先进行计算。通过使用pin
节点语法,你可以在一行中完成所有操作:
\node [inner sep=0pt, pin={[pin edge={latex-,black},pin distance=10pt]below:\pgfmathprintnumber{\result}}] at (\x*0.85cm,0) {};
首先,代码中的坐标是($(0,0)+(\x*0.85cm,0)$)
,当然与 相同(\x*0.85cm,0)
。inner sep
声明意味着节点的内容周围没有填充。操作pin
将标签添加到 ,node
并从节点到标签绘制一条线。pin edge
是线条的样式,pin distance
不言自明,below
意味着pin
绘制在节点下方。
现在,在下面的代码中,我做了一些不同的事情。我没有明确指定坐标,而是使用语法将节点添加到线上的特定位置
\node[arrownumber={$\result$}] at ($(linestart)!<fraction>!(lineend)$) {};
这arrownumber
是一个执行上述操作的自定义样式pin
,参数({$\result$}
)是图钉文本。linestart
和lineend
是在完整线的开始和结束处添加的节点,并且<fraction>
是在循环中计算的介于 0 和 1 之间的数字\foreach
。
不连续符号
您将线分成三段,在每个断点处添加一个节点。您可以只画一条线,然后在特定位置添加节点,例如
\draw (0,0) node[left]{<long label>} -- ++(21,0)
node[breakline,pos=0.5/21]{$\approx$}
node[breakline,pos=20.5/21]{$\approx$};
在这里,我在同一行左侧添加了标签。breakline
是一种自定义样式,其功能与您所使用的完全相同,即breakline/.style={fill=white,rotate=90,inner sep=-1.25pt,outer sep=0,anchor=center}
。
但是,符号的渲染并不完美,因为线条没有完全击中\approx
。作为替代方案,我使用了自定义方向,借用并改编了https://tex.stackexchange.com/a/22379/586.这让我可以说
\draw[interrupt={0.5/21}{20.5/21}] (0,0) -- ++ (21,0);
其中0.5/21
和20.5/21
是沿线添加断点的相对位置。
其他的建议
借助上述技术,您可以得到一系列命令,其中的坐标y
仅指定一次,位于线的左侧点。因此,在不同的y
坐标处添加更多命令变得很容易,因为您只需复制代码并更改一个数字即可。
在下面的代码中,我更进一步,把所有内容都放在一个宏中,这样你就可以说
\drawmyline[length of line]{<x-values>}{<start position>}{<left label>}
是length of the line
可选的。<x-values>
是循环中使用的以逗号分隔的 x 值列表。<start position>}
是形式为的坐标x,y
,<left label>
是添加到左侧的文本。
代码和输出
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.markings}
\usepackage[T1]{fontenc}
\newcommand\drawmyline[4][21]{%
\draw[interrupt={0.5/21}{20.5/21}] (#3)
node[left]{#4}
-- ++(#1,0)
node[arrownumber={$0$},pos=0](linestart){}
node[arrownumber={$264$},pos=1](lineend){};
\foreach \x in {#2} {
\pgfmathsetmacro\result{int(\x * 4 + 104)}
\pgfmathsetmacro\MarkPos{(1+\x*0.85)/21}
\node[arrownumber={$\result$}] at ($(linestart)!\MarkPos!(lineend)$) {};
}
}
\tikzset{
arrownumber/.style={
inner sep=0pt,
pin={[pin edge={latex-,black},pin distance=10pt,font=\footnotesize]below:#1}},
interrupt/.style 2 args={
postaction={
decorate,
decoration={markings,
mark= at position #1
with
{
\fill[white] (-0.05,0.2) to[out=250,in=70] (-0.05,-0.2) --
(0.05,-0.2) to[out=70,in=250] (0.05,0.2);
\draw (-0.05,0.2) to[out=250,in=70] (-0.05,-0.2)
(0.05,-0.2) to[out=70,in=250] (0.05,0.2);
},
mark= at position #2
with
{
\fill[white] (-0.05,0.2) to[out=250,in=70] (-0.05,-0.2) --
(0.05,-0.2) to[out=70,in=250] (0.05,0.2);
\draw (-0.05,0.2) to[out=250,in=70] (-0.05,-0.2)
(0.05,-0.2) to[out=70,in=250] (0.05,0.2);
}
}
}
}}
\begin{document}
\begin{tikzpicture}
%\drawmyline[length of line]{x-values}{start position}{left label}
\drawmyline{0,1,3,5,9,13,14,15}{0,0}{long label}
\drawmyline{0,3,4,5,9,13}{0,-1}{longer label}
% this is the same code used in the \drawmyline macro
\draw[interrupt={0.5/21}{20.5/21}] (0,-2)
node[left]{<long label>}
-- ++(21,0)
node[arrownumber={$0$},pos=0](linestart){}
node[arrownumber={$264$},pos=1](lineend){};
\foreach \x in {0,1,3,5,9,13,14,15} {
\pgfmathsetmacro\result{int(\x * 4 + 104)}
\pgfmathsetmacro\MarkPos{(1+\x*0.85)/21}
\node[arrownumber={$\result$}] at ($(linestart)!\MarkPos!(lineend)$) {};
}
\end{tikzpicture}
\end{document}