\documentclass{standalone}
\usepackage{xcolor}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\fill[cyan!80!white] (2,0) -- (2,4) arc (360:180:2cm and 0.5cm) -- (-2,0) arc (180:360:2cm and 0.5cm);
\fill[cyan] (0,4) circle (2cm and 0.5cm);
\draw[white,line width=2pt] (-2,4) -- (-2,0) arc (180:360:2cm and 0.5cm) -- (2,4) ++ (-2,0) circle (2cm and 0.5cm);
\end{tikzpicture}
\end{document}
\documentclass{standalone}
\usepackage{xcolor}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
\draw[white,line width=2pt](0,0) circle (3);
\end{tikzpicture}
\end{document}
两段代码分别画了一个圆柱体和一个球形,圆柱体的两个面分别用cyan 和cyan!80!white,球体设置渐变从cyan到cyan!80!white,可以明显看出两图颜色差别很大,想了解原因是什么,以及如何实现 cyan 的正确渐变
慕子的回答:
https://github.com/pgf-tikz/pgf/issues/993
加\PassOptionsToPackage{cmyk}{xcolor}
或\PassOptionsToPackage{rgb}{xcolor}
就能看出来了
感觉是 pgf shading 的 bug
相关代码在 https://github.com/pgf-tikz/pgf/blob/afa8dcc67472b70a11bd5f01b3f494243bba9b8a/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex#L345-L365
目前是,默认 rgb,除非指定了 color mode 是 cmyk 或 gray。
但默认情况下,xcolor 使用的 color mode 是 natural。在默认模式下,base colors 的色域,是不同的。而 pdf 要求每个 pattern,包括这里的 shading pattern,只使用单一色域的颜色,所以无法避免色域转换。
大部分 base color,在不同色域下的定义,「看起来」的颜色是相同的,所以转色域后,看起来颜色差异很小。cyan 刚好是例外。
pgf 做得更好的成本有点大,最好还是 henri 说的,让 xcolor 改默认行为。The main issue here is that xcolor mixes color models without warning.
https://github.com/pgf-tikz/pgf/issues/993#issuecomment-782731021
\begin{tikzpicture}
\tikzset{inner color=red,outer color=black}
\pgftext{\pgfuseshading{radial}}
\draw[green,line width=1.2pt](0,0) circle (25bp);
\draw[green,line width=1.2pt](0,0) circle (50bp);
\fill[shading=radial] (5,0) circle (50bp);
\end{tikzpicture}
得到
左侧半径为 50bp 的大圆是完整的 radial 渐变。右侧圆中的渐变,就是左侧圆中,半径为 25bp 的那一部分。左侧圆环中的颜色都没有出现在右侧圆中,被裁掉了。
如果想让完整的 radial 渐变出现在右侧圆中,需要重定义 radial 渐变,或者自己另外定义一种渐变。例如重定义 radial 渐变:
\makeatletter
\pgfdeclareradialshading[tikz@radial@inner,tikz@radial@outer]{radial}{\pgfpointorigin}{%
color(0bp)=(tikz@radial@inner);
color(25bp)=(tikz@radial@outer)}
\makeatother
这样重定义 radial 渐变的半径为 25bp, 再次绘制前面的圆,得到
其中的详细原因参考 TikZ & PGF Manual 的 114.3 Using Shadings 的命令 \pgfshadepath
。
——————————————————————————————————————————————
抱歉,以上回答显然是答非所问了,请参考网友 @u33 的回答。
——————————————————————————————————————————————————————————————
转述一下 #993 的要点:
1.在\fill[fill=cyan] (0,0) circle (3);
中,颜色 cyan
是 xcolor 宏包预定义的颜色,这个颜色来自 cmyk 模式。
2.在\fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
中,PGF 跟随 xcolor 认定的颜色模式,例子中是 rgb 模式。
cmyk 模式下的颜色 cyan
与 rgb 模式下的 cyan
是不一样的,出现色差。
解决的办法在 #993 中已经给出,即给 xcolor 宏包加上 cmyk
或者 rgb
选项,这是全局设定。
如果想局部设定,可以:
1.重定义颜色 cyan
为 rgb 模式下的颜色。首先获取 rgb 模式下的 cyan
的颜色数据:
\pgfshadecolortorgb{cyan}{\mycol}
\mycolred,\mycolgreen,\mycolblue
就是 0,1,1
,然后
\definecolor{cyan}{rgb}{0,1,1}
然后再填充图形。例如:
\begingroup
\definecolor{cyan}{rgb}{0,1,1}
\begin{tikzpicture}
\fill[fill=cyan] (-7,0) circle (3);
\fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
\end{tikzpicture}
\endgroup
得到
2.如果你觉得 cmyk 模式下的颜色 cyan
比较养眼,可以局部的修改 radial 渐变所认定的颜色模式,即修改 \pgf@setup@shading@model
的定义,如下:
\begingroup
\makeatletter
\def\pgf@setup@shading@model{%
\pgfshadingmodelrgbtrue
\pgfshadingmodelcmykfalse
\pgfshadingmodelgrayfalse
\XC@sdef\pgf@mod@test{\XC@tgt@mod{cmyk}}%修改在这里
\def\pgf@shading@device{/DeviceRGB}%
\def\pgf@shading@ps@device{setrgbcolor}%
\def\pgf@shading@functional@range{0 1 0 1 0 1}%
\def\pgf@shading@model{rgb}%
\ifx\pgf@mod@test\XC@mod@cmyk
\def\pgf@shading@device{/DeviceCMYK}%
\def\pgf@shading@ps@device{setcmykcolor}%
\def\pgf@shading@functional@range{0 1 0 1 0 1 0 1}%
\def\pgf@shading@model{cmyk}%
\pgfshadingmodelrgbfalse
\pgfshadingmodelcmyktrue
\fi
\ifx\pgf@mod@test\XC@mod@gray
\def\pgf@shading@device{/DeviceGray}%
\def\pgf@shading@ps@device{setgray}%
\def\pgf@shading@functional@range{0 1}%
\def\pgf@shading@model{gray}%
\pgfshadingmodelrgbfalse
\pgfshadingmodelgraytrue
\fi
\edef\pgf@sys@driver@dvisvgm{pgfsys-dvisvgm.def}%
\ifx\pgfsysdriver\pgf@sys@driver@dvisvgm
\def\pgf@shading@model{rgb}%
\fi
\edef\pgf@sys@driver@texforht{pgfsys-tex4ht.def}%
\ifx\pgfsysdriver\pgf@sys@driver@texforht
\def\pgf@shading@model{rgb}%
\fi
}
\makeatother
\begin{tikzpicture}
\fill[fill=cyan] (-7,0) circle (3);
\fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
\end{tikzpicture}
\endgroup
%重画,做比较
\begin{tikzpicture}
\fill[fill=cyan] (-7,0) circle (3);
\fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
\end{tikzpicture}
得到
非常感谢,从您的讨论中我发现了我的错误。
重新编辑了一下回答,我希望我改正了错误。