我想制作一个矩形,水平方向比垂直方向长,左右两端为黑色,中间为白色。我不想要从黑色到白色(再变回黑色)的线性渐变,而是钟形曲线形式的变化。
我见过这,这看起来很笼统,但我无法将任意函数改为简单的高斯函数。我希望有一种更简单的方法。
以下是我能做到的最好的事情:
% !TEX program = xelatex
\documentclass[tikz]{standalone}
\begin{document}
\begin{pgfpicture}
\pgfdeclarehorizontalshading{myshadingD} {20pt}{color(0pt)=(black); color(40pt)=(white)}
\pgfdeclarehorizontalshading{myshadingA} {20pt}{color(0pt)=(white); color(40pt)=(black)}
\pgftext[at=\pgfpoint{0cm}{0cm}] {\pgfuseshading{myshadingD}}
\pgftext[at=\pgfpoint{2cm}{0cm}] {\pgfuseshading{myshadingA}}
\end{pgfpicture}
\end{document}
这会创建如下内容:
答案1
由于定义\pgfdeclarefunctionshading
需要大量的数学和 PostScript,我只需预先计算几个值。
我正在使用 LibreOffice Calc,因为它是我手头上最简单的工具,我可以使用它的功能来创建必要的
color(<length>)=(<outer>!<share>!<inner>);
在单独的列中声明,我只需要将其复制到我的 TeX 源中。
对于\pgftext{\pgfuseshading{<name>}}
命令 I,将计算0pt
和之间的 41 个值,40pt
这些值将映射到 −π 和 +π。
自从PGF 变换路径上的阴影相反,我们将使用25bp
和75bp
来表示相同的±π范围(总共 51 个值)。
阴影可用的在 PGF/TikZ 中我调用Gaussian
(与 相比gaussian
)\pgftext
。
键gauss outer color
和gauss inner color
可用于改变颜色。
我的文档中的最后一个例子将Gaussian
阴影与默认(严格线性)axis
阴影进行了比较。
也许这可以用更少的点来完成,但仍然足够,但肯定比用 PostScript 编码的工作量要少。
代码
% !TEX program = xelatex
\PassOptionsToPackage{rgb}{xcolor}
\documentclass{article}
\usepackage{tikz}
\pgfdeclarehorizontalshading[black]{gaussian}{20pt}{
color(0pt)=(black!99);color(1pt)=(black!99);color(2pt)=(black!98);color(3pt)=(black!97);color(4pt)=(black!96);
color(5pt)=(black!94);color(6pt)=(black!91);color(7pt)=(black!88);color(8pt)=(black!83);color(9pt)=(black!78);
color(10pt)=(black!71);color(11pt)=(black!63);color(12pt)=(black!55);color(13pt)=(black!45);color(14pt)=(black!36);
color(15pt)=(black!27);color(16pt)=(black!18);color(17pt)=(black!11);color(18pt)=(black!5);color(19pt)=(black!1);
color(20pt)=(black!0);color(21pt)=(black!1);color(22pt)=(black!5);color(23pt)=(black!11);color(24pt)=(black!18);
color(25pt)=(black!27);color(26pt)=(black!36);color(27pt)=(black!45);color(28pt)=(black!55);color(29pt)=(black!63);
color(30pt)=(black!71);color(31pt)=(black!78);color(32pt)=(black!83);color(33pt)=(black!88);color(34pt)=(black!91);
color(35pt)=(black!94);color(36pt)=(black!96);color(37pt)=(black!97);color(38pt)=(black!98);color(39pt)=(black!99);
color(40pt)=(black!99)}
\pgfdeclarehorizontalshading[gauss@border,gauss@center]{Gaussian}{100bp}{
color(0bp)=(gauss@border!100!gauss@center);color(25bp)=(gauss@border!99!gauss@center);color(26bp)=(gauss@border!99!gauss@center);
color(27bp)=(gauss@border!98!gauss@center);color(28bp)=(gauss@border!98!gauss@center);color(29bp)=(gauss@border!97!gauss@center);
color(30bp)=(gauss@border!96!gauss@center);color(31bp)=(gauss@border!94!gauss@center);color(32bp)=(gauss@border!92!gauss@center);
color(33bp)=(gauss@border!90!gauss@center);color(34bp)=(gauss@border!87!gauss@center);color(35bp)=(gauss@border!83!gauss@center);
color(36bp)=(gauss@border!79!gauss@center);color(37bp)=(gauss@border!74!gauss@center);color(38bp)=(gauss@border!68!gauss@center);
color(39bp)=(gauss@border!62!gauss@center);color(40bp)=(gauss@border!55!gauss@center);color(41bp)=(gauss@border!47!gauss@center);
color(42bp)=(gauss@border!40!gauss@center);color(43bp)=(gauss@border!32!gauss@center);color(44bp)=(gauss@border!25!gauss@center);
color(45bp)=(gauss@border!18!gauss@center);color(46bp)=(gauss@border!12!gauss@center);color(47bp)=(gauss@border!7!gauss@center);
color(48bp)=(gauss@border!3!gauss@center);color(49bp)=(gauss@border!1!gauss@center);color(50bp)=(gauss@border!0!gauss@center);
color(51bp)=(gauss@border!1!gauss@center);color(52bp)=(gauss@border!3!gauss@center);color(53bp)=(gauss@border!7!gauss@center);
color(54bp)=(gauss@border!12!gauss@center);color(55bp)=(gauss@border!18!gauss@center);color(56bp)=(gauss@border!25!gauss@center);
color(57bp)=(gauss@border!32!gauss@center);color(58bp)=(gauss@border!40!gauss@center);color(59bp)=(gauss@border!47!gauss@center);
color(60bp)=(gauss@border!55!gauss@center);color(61bp)=(gauss@border!62!gauss@center);color(62bp)=(gauss@border!68!gauss@center);
color(63bp)=(gauss@border!74!gauss@center);color(64bp)=(gauss@border!79!gauss@center);color(65bp)=(gauss@border!83!gauss@center);
color(66bp)=(gauss@border!87!gauss@center);color(67bp)=(gauss@border!90!gauss@center);color(68bp)=(gauss@border!92!gauss@center);
color(69bp)=(gauss@border!94!gauss@center);color(70bp)=(gauss@border!96!gauss@center);color(71bp)=(gauss@border!97!gauss@center);
color(72bp)=(gauss@border!98!gauss@center);color(73bp)=(gauss@border!98!gauss@center);color(74bp)=(gauss@border!99!gauss@center);
color(75bp)=(gauss@border!99!gauss@center);color(100bp)=(gauss@border!100!gauss@center)}
\makeatletter
\tikzset{
gauss outer color/.code=\colorlet{gauss@border}{#1}\def\tikz@shading{Gaussian}\tikz@addmode{\tikz@mode@shadetrue},
gauss inner color/.code=\colorlet{gauss@center}{#1}\def\tikz@shading{Gaussian}\tikz@addmode{\tikz@mode@shadetrue}}
\makeatother
\colorlet{gauss@border}{black}
\colorlet{gauss@center}{white}
\begin{document}
Let $a$ and $b$ be the first and the last length of the shading which should be mapped to the range $z = (-\pi, \pi)$ then is
\begin{equation}
z = \pi \left(2 \frac{i-a}{b-a}-1\right).
\end{equation}
The share of the color in range $c = (0, 100)$ is then
\begin{equation}
c(i) = 100 \left(1- \frac{\phi(z)}{\phi(0)}\right).
\end{equation}
\texttt{gaussian}: $a = 0\,\mathrm{pt}$, $b = 40\,\mathrm{pt}$ \quad
\texttt{Gaussian}: $a = 25\,\mathrm{bp}$, $b = 75\,\mathrm{bp}$
\begin{tikzpicture}[x=20pt,y=20pt]
\pgftext[at=\pgfpoint{0pt}{0pt}]{\pgfuseshading{gaussian}}
\draw[overlay,very thick,red] plot[domain=-1:1, samples=100]
(\x,{exp(-(\x*\x*pi*pi)/2)/sqrt(2*pi)});
\end{tikzpicture}
\tikz\shade[shading=Gaussian] (0,0) rectangle (3,1);
\begin{tikzpicture}
\shade[gauss outer color=green, gauss inner color=magenta]
(0, 0) coordinate (bl) rectangle ++(2.5, 1) coordinate (tr);
\fill[magenta] ([shift=(up:1)] bl) rectangle ++(1.25, -.25)
++ (down:.5) rectangle ++(1.25, -.25);
\shade[left color=green, right color=magenta]
(bl) rectangle ++ (1.25, .25) coordinate (m);
\shade[left color=magenta, right color=green]
(tr) rectangle ++ (-1.25, -.25);
\end{tikzpicture}
\end{document}
输出
答案2
伪造的阴影
- 使用填充的
rectangle
s:fake shading
或 - 通过使用阴影
rectangle
s:real fake shading
。
出了点问题path picture
这就是为什么其中real fake shading
有一个空白,否则第一个阴影矩形就不会被阴影。\shade;
除了该\shade;
命令之外,我还使用 PGF 宏来希望能加快编译速度。
我们可以将函数设置为对某些东西进行着色,其中对fakeshading/function=<func>
介于和之间的值进行求值<func>
,并将 设置为介于和之间的值。\x
0
1
0
100
请注意,使用 一步fake shading
仍然.01
可以看到 的边缘。real fake shading
.05
代码
% !TEX program = xelatex
\PassOptionsToPackage{rgb}{xcolor}
\documentclass[tikz]{standalone}
\pgfqkeys{/tikz/fakeshading}{
colorA/.initial=black,
colorB/.initial=white,
function/.initial={%
(100-100*phi(6.28318530717959*\x-3.14159265358979)/0.398942280401433)},
step/.initial=.01}
\makeatletter
\def\fake@shading@function{max(0,min(100,\pgfkeysvalueof{/tikz/fakeshading/function}))}
\tikzset{
declare function={phi(\z)=exp(-\z*\z/2)/sqrt(2*pi);},
fake shading/.default=,real fake shading/.default=,
fake shading/.style={ path picture={%
\tikzset{every fake shading/.try,/tikz/fakeshading/.cd,#1}\fake@shading@setup
\pgfmathmultiply@{.5}{\fake@shading@step}% half step length
\let\fake@shading@halfstep\pgfmathresult
\foreach \x[expand list,evaluate={\y=\fake@shading@function;}]
in {0,\pgfkeysvalueof{/tikz/fakeshading/step},...,1.001} {
% \fill[color=fake@shading@A!\y!fake@shading@B] (\x-\fake@shading@halfstep,0)
% rectangle ++(\pgfkeysvalueof{/tikz/fakeshading/step},1);
\pgfpathrectangle{\pgfpointxy{\x-\fake@shading@halfstep}{0}}%
{\pgfpointxy{\pgfkeysvalueof{/tikz/fakeshading/step}}{1}}
\pgfsetfillcolor{fake@shading@A!\y!fake@shading@B}\pgfusepath{fill}}}},
real fake shading/.style={path picture={%
\tikzset{every real fake shading/.try,/tikz/fakeshading/.cd,#1}\fake@shading@setup
\pgfmathmultiply@{\fake@shading@step}{2}\let\fake@shading@doublestep\pgfmathresult
\def\x{0}\pgfmathsetmacro\fake@shading@lasty{\fake@shading@function}%
\shade;% the first shade doesn't want to
\foreach \x[expand list,evaluate={\y=\fake@shading@function;},
remember=\y as \lasty (initially \fake@shading@lasty)%
] in {\fake@shading@step,\fake@shading@doublestep,...,1.001} {
\pgfutil@colorlet{tikz@axis@top}{fake@shading@A!\lasty!fake@shading@B}%
\pgfutil@colorlet{tikz@axis@bottom}{fake@shading@A!\y!fake@shading@B}%
\pgfutil@colorlet{tikz@axis@middle}{tikz@axis@top!50!tikz@axis@bottom}%
\pgfpathrectangle{\pgfpointxy{\x}{0}}{\pgfpointxy{-\fake@shading@step}{1}}
\pgfshadepath{axis}{90}\pgfusepath{}}}}}
\def\fake@shading@setup{%
\pgftransformreset
\colorlet{fake@shading@A}{\pgfkeysvalueof{/tikz/fakeshading/colorA}}%
\colorlet{fake@shading@B}{\pgfkeysvalueof{/tikz/fakeshading/colorB}}%
\pgfextract@process\tikz@temp{% setting up coordinate system
\pgfpointdiff{\pgfpointanchor{path picture bounding box}{south west}}
{\pgfpointanchor{path picture bounding box}{north east}}}%
\pgfsetxvec{\tikz@temp\pgf@y0pt }\pgfsetyvec{\tikz@temp\pgf@x0pt }%
\pgftransformshift{\pgfpointanchor{path picture bounding box}{south west}}%
\pgfmathsetmacro\fake@shading@step{\pgfkeysvalueof{/tikz/fakeshading/step}}}
\makeatother
\tikzset{every real fake shading/.append style={fakeshading/step=.05}}
\begin{document}
\begin{tikzpicture}
\path[fake shading] (0,1) rectangle (5,2);
\path[real fake shading] (0,0) rectangle (5,1);
\end{tikzpicture}
\begin{tikzpicture}[fakeshading/function=100*((2*\x-1)^2)]% x² between (-1 and 1)
\path[fake shading] (0,1) rectangle (5,2);
\path[real fake shading] (0,0) rectangle (5,1);
\end{tikzpicture}
\begin{tikzpicture}[fakeshading/function=50*(sin(2*\x*360)+1)]% (sin x between 0 and 4pi)
\path[fake shading] (0,1) rectangle (5,2);
\path[real fake shading] (0,0) rectangle (5,1);
\end{tikzpicture}
\tikz\shade[real fake shading] (0,0) rectangle (3,1);
\begin{tikzpicture}
\shade[real fake shading={colorA=green, colorB=magenta}]
(0, 0) coordinate (bl) rectangle ++(2.5, 1) coordinate (tr);
\fill[magenta] ([shift=(up:1)] bl) rectangle ++(1.25, -.25)
++ (down:.5) rectangle ++(1.25, -.25);
\shade[left color=green, right color=magenta]
(bl) rectangle ++ (1.25, .25) coordinate (m);
\shade[left color=magenta, right color=green]
(tr) rectangle ++ (-1.25, -.25);
\end{tikzpicture}
\end{document}
输出
fake shading
转换后看起来不太好,并且有一些瑕疵。
没有real fake shading
同样的问题: