我有一种在行尾放置箭头的风格:
\makeatletter
\tikzset{nomorepostaction/.code={\let\tikz@postactions\pgfutil@empty}}
\makeatother
\tikzset{mystyle/.style={
shorten >=0.5pt,
postaction={
nomorepostaction,
decorate,
decoration={
markings,
mark=at position 1 with {\arrow[semithick]{>}}
}
}
}}
我需要这样做,因为这正是我想要的“半粗”箭头。但如果我缩短一条线,箭头就会画在错误的位置:
\draw [mystyle, shorten >=5pt] (0,0) to (2,0);
在我看来,问题是由“在位置 1”部分引起的,它指的是行尾,但没有实施任何缩短。
所以,我的问题是:我如何定义一种样式来可靠地将装饰放在行尾(或与行尾固定偏移量),这对于因“缩短 <”和“缩短 >”而导致的行缩短或加长具有鲁棒性?
答案1
这是对实际问题的回答(我仍然认为定义一个新的箭头会更优雅)。这使用了 Caramdir 的回答使用 TikZ 标记放置箭头扩展了mark=at position
,使其能够处理算术。再加上长度\pgf@shorten@end@additional
(和\pgf@shorten@start@additional
)中保存的缩短,这似乎可以解决问题(至少对于这个例子来说,我不知道它是否更普遍)。
顺便说一句,shorten >
键不是累积的,因此装饰shorten >=0.5pt
中的mystyle
会被实际使用中的覆盖shorten >=5pt
。我不确定你是否希望箭头被拉回额外的 0.5pt
不管该行已经缩短了多少,我在下面给出了各种替代方案。希望这些内容足以让您找到最适合您实际用途的方案。
\documentclass[border=10]{standalone}
% \url{https://tex.stackexchange.com/q/25830/86}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\makeatletter
% overwrite the number parsing macro from pgflibrarydecorations.markings
\def\pgf@lib@dec@parsenum#1{%
\gdef\pgf@lib@dec@computed@width{0 pt}%
\tsx@pgf@lib@dec@parsenum#1+endmarker+%
\ifdim\pgf@lib@dec@computed@width<0pt\relax%
\pgfmathparse{\pgfdecoratedpathlength\pgf@lib@dec@computed@width}
\edef\pgf@lib@dec@computed@width{\pgfmathresult pt}%
\fi%
}
\def\tsx@pgf@lib@dec@parsenum@endmarker{endmarker}
% this is iterated over all numbers that are summed
\def\tsx@pgf@lib@dec@parsenum#1+{
\def\temp{#1}%
\ifx\temp\tsx@pgf@lib@dec@parsenum@endmarker%
\else%
\tsx@pgf@lib@dec@parsenum@one{#1}%
\expandafter\tsx@pgf@lib@dec@parsenum%
\fi%
}
% calculate the length for each number
\def\tsx@pgf@lib@dec@parsenum@one#1{%
\pgfmathparse{#1}%
\ifpgfmathunitsdeclared%
\pgfmathparse{\pgf@lib@dec@computed@width + \pgfmathresult pt}%
\else%
\pgfmathparse{\pgf@lib@dec@computed@width + \pgfmathresult*\pgfdecoratedpathlength*1pt}%
\fi%
\edef\pgf@lib@dec@computed@width{\pgfmathresult pt}%
}
\tikzset{nomorepostaction/.code={\let\tikz@postactions\pgfutil@empty}}
\tikzset{mystyle 1/.style={
shorten >=0.5pt,
postaction={
nomorepostaction,
decorate,
decoration={
markings,
mark=at position 1 with {\arrow[semithick]{>}}
}
}
},
mystyle 2/.style={
postaction={
nomorepostaction,
decorate,
decoration={
markings,
mark={at position 1 + - \pgf@shorten@end@additional with {\arrow[semithick]{>}}}
}
}
},
mystyle 3/.style={
postaction={
nomorepostaction,
decorate,
decoration={
markings,
mark={at position 1 + - \pgf@shorten@end@additional + -0.5pt with {\arrow[semithick]{>}}}
}
}
},
mystyle 4/.style={
shorten >=0.5pt,
postaction={
nomorepostaction,
decorate,
decoration={
markings,
mark={at position 1 + - \pgf@shorten@end@additional with {\arrow[semithick]{>}}}
}
}
},
}
\makeatother
\begin{document}
\begin{tikzpicture}
\foreach \st in {1,...,4} {
\begin{scope}[yshift=-\st cm]
\draw [mystyle \st,shorten >=5pt] (0,0) to (2,0);
\draw [mystyle \st] (0,-.5) to (2,-.5);
\end{scope}
}
\end{tikzpicture}
\end{document}
结果:
(如果您发现这有用,请在上面的链接中为 Caramdir 的代码投票!我所做的只是剪切和粘贴。)
答案2
这是新的thick arrow
。它只是从中获取的正常箭头定义pgfcorearrows.code.tex
,并添加了线条\pgfsetlinewidth{...}
。
编辑:根据 Andrew Stacey 的建议,以下是相同的箭头,但厚度是一个选项。如果您不指定厚度的单位,则该值将乘以线条厚度以获得箭头的厚度。使用的线条厚度是绘制箭头时生效的线条厚度。
发行
\draw [thick arrow] (0,0) to (2,0);
\draw [thick arrow=2pt] (0,-1) to (2,-1);
\draw [line width=2pt,thick arrow=1,shorten >=5pt] (0,-2) to (2,-2);
\draw [line width=2pt,thick arrow=2,shorten >=5pt] (0,-3) to (2,-3);
将产生
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\makeatletter
\pgfarrowsdeclare{thickarrow}{thickarrow}
{
\pgfutil@tempdima=-0.84pt%
\advance\pgfutil@tempdima by-1.3\pgflinewidth%
\pgfutil@tempdimb=0.21pt%
\advance\pgfutil@tempdimb by.625\pgflinewidth%
\pgfarrowsleftextend{+\pgfutil@tempdima}
\pgfarrowsrightextend{+\pgfutil@tempdimb}
}
{
\pgfmathparse{\pgfgetarrowoptions{thickarrow}}%
\ifpgfmathunitsdeclared%
\pgfmathparse{\pgfmathresult pt}%
\else%
\pgfmathparse{\pgfmathresult*\pgflinewidth}%
\fi%
\let\thickness=\pgfmathresult
\pgfsetlinewidth{\thickness pt}
\pgfutil@tempdima=0.28pt%
\advance\pgfutil@tempdima by.3\pgflinewidth%
\pgfsetlinewidth{0.8\pgflinewidth}
\pgfsetdash{}{+0pt}
\pgfsetroundcap
\pgfsetroundjoin
\pgfpathmoveto{\pgfqpoint{-3\pgfutil@tempdima}{4\pgfutil@tempdima}}
\pgfpathcurveto
{\pgfqpoint{-2.75\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
{\pgfqpoint{0pt}{0.25\pgfutil@tempdima}}
{\pgfqpoint{0.75\pgfutil@tempdima}{0pt}}
\pgfpathcurveto
{\pgfqpoint{0pt}{-0.25\pgfutil@tempdima}}
{\pgfqpoint{-2.75\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
{\pgfqpoint{-3\pgfutil@tempdima}{-4\pgfutil@tempdima}}
\pgfusepathqstroke
}
\makeatother
\tikzset{
set thickarrow thickness/.code={
\pgfsetarrowoptions{thickarrow}{#1}},
thick arrow/.style={set thickarrow thickness=#1,-thickarrow},
thick arrow/.default=0.6pt
}
\begin{document}
\begin{tikzpicture}[transform canvas={scale=3}]
\draw [thick arrow] (0,0) to (2,0);
\draw [thick arrow=2pt] (0,-1) to (2,-1);
\draw [line width=2pt,thick arrow=1,shorten >=5pt] (0,-2) to (2,-2);
\draw [line width=2pt,thick arrow=2,shorten >=5pt] (0,-3) to (2,-3);
\draw [thick arrow=2,shorten >=5pt,line width=2pt] (0,-3) to (2,-3);
\end{tikzpicture}
\end{document}