Scaling arrows.meta with tranform shape
How about transform canvas
?
\documentclass[]{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\tikzset{myarr/.style={
-{Triangle[width=6pt, length=9pt]},
}}
\begin{document}
\begin{tikzpicture}
\draw[myarr] (0,0) -- (3,0) node[draw, anchor=west]{A};
\end{tikzpicture}
\bigskip
\begin{tikzpicture}[transform canvas={scale=0.5}]
\draw[myarr] (0,0) -- (3,0) node[draw, anchor=west]{A};
\end{tikzpicture}
\end{document}
The arrows have the scale
, scale length
and scale width
option (see page 193 of the TikZ 3.1.4b manual).
I have changed your style so that this factor becomes a parameter of your style.
\tikzset{myarr/.style={
-{Triangle[width=6pt, length=9pt,scale=#1]},
myarr/.default=1
}}
\documentclass[]{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\tikzset{myarr/.style={
-{Triangle[width=6pt, length=9pt,scale=#1]},
myarr/.default=1
}}
\begin{document}
\begin{tikzpicture}
\draw[myarr] (0,0) -- (3,0) node[draw, anchor=west]{A};
\end{tikzpicture}
\bigskip
\begin{tikzpicture}[scale=0.5,transform shape]
\draw[myarr=.5] (0,0) -- (3,0) node[draw, anchor=west]{A};
\end{tikzpicture}
\end{document}
One option is to use \pgflowlevelsynccm
. However, it is to be used with great care.
\documentclass[]{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\tikzset{myarr/.style={
-{Triangle[width=6pt, length=9pt]},
}}
\begin{document}
\begin{tikzpicture}
\draw[myarr] (0,0) -- (3,0) node[draw, anchor=west]{A};
\end{tikzpicture}
\bigskip
\begin{tikzpicture}[scale=0.5, transform shape]
\pgflowlevelsynccm
\draw[myarr] (0,0) -- (3,0) node[draw, anchor=west]{A};
\end{tikzpicture}
\end{document}
A more complex but less dangerous solution is to read out \pgfgettransformentries
and scale the arrow dimensions accordingly. As requested in the comment, it is spelled out here.
\documentclass[]{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\tikzset{myarr/.style={%
/utils/exec=\pgfgettransformentries{\tmpa}{\tmpb}{\tmpc}{\tmpd}{\tmp}{\tmp}%
\pgfmathsetmacro{\mydet}{\tmpa*\tmpd-\tmpb*\tmpc},
-{Triangle[width=6pt, length=9pt,scale={sqrt(abs(\mydet))}]},
}}
\begin{document}
\begin{tikzpicture}
\draw[myarr] (0,0) -- (3,0) node[draw, anchor=west]{A};
\end{tikzpicture}
\bigskip
\begin{tikzpicture}[scale=0.5, transform shape]
\draw[myarr] (0,0) -- (3,0) node[draw, anchor=west]{A};
\end{tikzpicture}
\end{document}
Some comments on the background. The Euclidean transformations in 2 dimensions are given my a transformation matrix (with entries a
, b
, c
and d
, say) and a translation, i.e. a 2d vector. As explained on p. 1142 of the pgfmanual v3.1.4, they can be inferred with \pgfgettransformentries
. The key scale=<factor>
sets a=<factor>
and d=<factor>
, but in general the 2d volume gets scaled by the determinant a*d-b*c
(such that under orthogonal transformations it is invariant) and the scale factor is its square root. (The determinant is just the Jacobian, and has been used e.g. before e.g. in this post and this post. I was urged to mention these earlier posts, which I am happy to do, but where should one stop?) That is, the second proposal does not tilt the arrow, but the first one does that yet is more "dangerous". A third option would be to apply \pgflowlevelsynccm
only to the arrow, yet this will be quite a hack.
Let me also mention that the pgf manual is very clear on that line widths do not get transformed with scale=<factor>
, regardless of whether or not you add transform shape
. And (standard) arrows do scale with the line width. From this it is obvious that transform shape
should not transform the size of arrow heads. If you want to have a fully rescaled picture, you'd need to scale the line widths, too. This can be fed into the arrows as well.