请考虑以下 LaTeX 手稿,其中有一张高大的彩虹阴影矩形的 TikZ 图片。该代码基本上是从 TikZ & PGF 手册 3.0.1a 版第 109 章(“阴影”)第 109.3 小节(“使用阴影”)末尾的示例中复制粘贴的,第 1088 页。
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\pgfdeclareverticalshading{rainbow}{100bp}{color(0bp)=(red); color(25bp)=(red); color(35bp)=(yellow); color(45bp)=(green); color(55bp)=(cyan); color(65bp)=(blue); color(75bp)=(violet); color(100bp)=(violet)}
\begin{tikzpicture}[shading=rainbow]
\shade[shading angle=90] (3,0) rectangle +(1,2);
\end{tikzpicture}
\end{document}
生成的图像(未按比例)
这个矩形的阴影范围从左边的紫色到右边的红色。我不明白为什么会这样。在我看来,它应该从蓝色到黄色。我根据第\pgfshadepath{〈shading name〉}{〈angle〉}
1085-1086 页上的命令描述中给出的阴影算法得出这个观点:
首先,PGF 将设立本地范围。
其次,它使用当前路径来剪切此范围内的所有内容。但是,当前路径在范围之后再次可用,因此可以使用它来描边。
现在,应该
〈shading name〉
是宽度和高度为 100 bp 的阴影,即 100 个大点。PGF 查看当前路径的边界框。计算路径时会自动计算此边界框;但是,有时它可能(相当)太大,尤其是涉及复杂曲线时。在范围内,修改了低级变换矩阵。阴影的中心被平移(移动),使其位于路径边界框的中心。低级坐标系也被缩放,使得阴影“覆盖”路径(细节有点复杂,见下文)。然后,坐标系旋转
〈angle〉
。最后,如果已使用宏
\pgfsetadditionalshadetransform
,则应用额外的转换。所有设置完毕后,插入阴影。
如果路径和阴影始终是矩形,并且不涉及旋转,则很容易缩放阴影,使它们始终覆盖路径。但是,当垂直阴影旋转时,显然必须“放大”它,以便它仍然覆盖路径。当路径本身不是矩形时,情况会变得更糟。
由于这些原因,事情在“现实”中略有不同。阴影被缩放和平移,使得点 (50bp,50bp)(阴影中间)位于路径的中间,并且点 (25bp,25bp) 位于路径的左下角,而 (75bp,75bp) 位于右上角。
重申一下,基本步骤是:
- 根据规格创建一个大小为 100bpx100pb 的阴影正方形
\pgfdeclareverticalshading
。我将这个正方形称为背景 正方形。 - 移动背景方块,使其中心与要着色的形状的边界框的中心重合。
- 缩放移位后的背景方块,使得它的子方块(其左下角位于 (25pb,25pb) 并且右上角位于 (75bp,75bp)(移位前的坐标))与要着色的形状的边界框重合。
- 按指定的 旋转平移和缩放的背景方块
angle
。 - 按照需要着色的形状剪切生成的背景正方形。
具体来说,背景方块的旋转(步骤4)是在它被移动和缩放(步骤3)之后进行的。
让我们将其应用到我们的示例中。在旋转之前,背景方块会进行变换,使得要着色的形状顶部的颜色为紫色,而要着色的形状底部的颜色为红色。现在进行 90 度旋转,由于要着色的形状是一个又高又细的矩形,因此旋转后的背景方块的紫色和红色将落在要着色的形状之外。因此,在剪切之后,只有蓝色到黄色的光谱应该保持可见。
如果旋转是首先要执行的变换,即如果算法的第 2、3 和 4 步按如下方式排列:2->3、3->4、4->2,那么上面获得的图像对我来说是有意义的。
答案1
遮蔽当前路径,但是不丢弃它。
#1
- 阴影(见下文)
#2
- 一个角度描述:
\pgfshadepath
“尝试”用阴影填充当前路径。阴影的原始大小应完全覆盖 (0,0) 和 (100bp,100bp) 之间的区域。阴影将旋转 #2,然后重新缩放,以便完全覆盖路径。然后路径将(本地)用于剪辑并绘制阴影。除了旋转之外,设置的任何变换
\pgfsetadditionalshadetransform
也将应用。完成所有这些后,该路径仍然可以用于正常的描边/剪切操作。
阴影绕其中间旋转。如果不旋转,路径的左下角将位于 (25bp, 25bp),右上角位于 (75bp, 75bp)。
例子:
\pgfdeclareverticalshading{myshading}{100bp}{color(0pt)=(red); color(100bp)=(green)} \pgfpathmoveto{\pgforigin} \pgfpathlineto{\pgfxy(1,0)} \pgfpathlineto{\pgfxy(1,1)} \pgfshadepath{myshading}{0} \pgfusepath{stroke}
---摘自tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
。
答案2
源代码可以最好地回答您的问题
\def\pgfshadepath#1#2{%
\ifdim\pgf@pathminx=16000pt%
\pgfwarning{No path specified that can be filled}%
\else%
\begingroup%
% Calculate center:
\pgf@xb=.5\pgf@pathmaxx%
\advance\pgf@xb by.5\pgf@pathminx%
\pgf@yb=.5\pgf@pathmaxy%
\advance\pgf@yb by.5\pgf@pathminy%
% Calculate scaling:
\pgf@xc=\pgf@pathmaxx%
\advance\pgf@xc by-\pgf@pathminx%
\pgf@yc=\pgf@pathmaxy%
\advance\pgf@yc by-\pgf@pathminy%
\pgf@xc=.01992528\pgf@xc%
\pgf@yc=.01992528\pgf@yc%
\ifdim\pgf@xc<0.0001pt\relax\ifdim\pgf@xc>-0.0001pt\relax\pgf@no@shadetrue\fi\fi%
\ifdim\pgf@yc<0.0001pt\relax\ifdim\pgf@yc>-0.0001pt\relax\pgf@no@shadetrue\fi\fi%
\ifpgf@no@shade\else%
\pgfsys@beginscope%
\pgfsyssoftpath@invokecurrentpath%
\pgfsys@clipnext%
\pgfsys@discardpath%
% Compute new transformation matrix:
\pgfsys@transformcm{1}{0}{0}{1}{\pgf@xb}{\pgf@yb}%
\pgfsys@transformcm%
{\pgf@sys@tonumber{\pgf@xc}}{0}%
{0}{\pgf@sys@tonumber{\pgf@yc}}{0pt}{0pt}%
\pgfmathparse{#2}%
\let\pgfshade@angle=\pgfmathresult%
\pgfmathsin@{\pgfshade@angle}%
\let\pgfshade@sin=\pgfmathresult%
\pgfmathcos@{\pgfshade@angle}%
\let\pgfshade@cos=\pgfmathresult%
\pgf@x=\pgfshade@sin pt%
\pgf@xa=-\pgf@x%
\pgfsys@transformcm{\pgfshade@cos}{\pgfshade@sin}{\pgf@sys@tonumber{\pgf@xa}}{\pgfshade@cos}{0pt}{0pt}%
\ifx\pgf@shade@extra@transform\pgfutil@empty%
\else%
\pgflowlevel{\pgf@shade@extra@transform}%
\fi%
\pgfuseshading{#1}%
\pgfsys@endscope%
\fi%
\endgroup%
\fi%
}
#1
是阴影的名称;rainbow
在你的情况下。#2
是角度;90
就你的情况而言。- (
\pgf@xb
,\pgf@yb
)是路径(BB)的中心。 - (
\pgf@xc
,\pgf@yc
)是路径(BB)的大小;单位 = 50bp。- .01992528 * 50 bp = 1pt
- 变换的顺序是
- 转移
- 规模
- 旋转
现在为了简单起见,假设我们有一个正方形。通过缩放,我们将其转换为一个细长的矩形。
所以问题是,如果我们将这个细长矩形旋转 90 度,它会变成细长矩形,还是宽短矩形。答案是前者。例如,尝试一下
\makeatletter
\tikz{
\path(-3,-3)(3,3);
\pgfsys@transformcm{.5}{0}{0}{2}{0pt}{0pt}
\pgfsys@transformcm{0}{1}{-1}{0}{0pt}{0pt} % comment and uncomment this line
\node[draw]{}; % and see what happens to this *square*
\node{ABC};
}
PGF 与此行为无关。这完全与 PDF 标准有关。也许以下 PDF 规范快照可以帮助您