我定义了一个新形状,用预定义的填充和颜色绘制一朵花:
\makeatletter
\pgfdeclareshape{flower}{
\savedanchor{\center}{%
\pgfpointorigin}
\anchor{center}{\center}
\backgroundpath{%
\begingroup
\tikz@mode
\iftikz@mode@draw
\foreach \a in {60,120,...,360} {
\pgftransformrotate{\a}
\pgfpathellipse{\pgfpointxy{0}{0.7}}{\pgfpointxy{0.25}{0}}{\pgfpointxy{0}{0.5}}
}
\pgfpathcircle{\pgfpoint{0}{0}}{0.4cm}
\let\my@color\tikz@strokecolor!60!\tikz@fillcolor
\foreach \a in {30,60,...,360} {%
\pgftransformrotate{\a+7}%
\pgfpathmoveto{\pgfpointxy{0}{0.1}}
\def\y{0.6+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
}
\fi
\iftikz@mode@fill
\begin{scope}
\foreach \a in {60,120,...,360} {
\pgftransformrotate{\a}
\pgfpathellipse{\pgfpointxy{0}{0.7}}{\pgfpointxy{0.25}{0}}{\pgfpointxy{0}{0.5}}
}
\pgfusepath{clip}
\pgfpathcircle{\pgfpointxy{0}{0}}{1.2cm}
\pgfutil@colorlet{tikz@radial@outer}{\tikz@fillcolor!70}
\pgfutil@colorlet{tikz@radial@inner}{\tikz@fillcolor!60!\tikz@strokecolor}
\pgfshadepath{radial}{0}
\pgfusepath{}
\end{scope}
% \tikz@mode@clipfalse
\let\my@strokecolor\tikz@strokecolor
\let\my@fillcolor\tikz@fillcolor
\pgfsetfillcolor{\my@strokecolor}
\pgfpathcircle{\pgfpointxy{0}{0}}{0.4cm}
\pgfusepath{fill}
\foreach \a in {30,60,...,360} {%
\pgftransformrotate{\a+7}%
\pgfpathmoveto{\pgfpointxy{0}{0.1}}
\def\y{0.5+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
}
\let\my@color\my@fillcolor
\pgfutil@colorlet{\my@color}{\my@strokecolor!60!\my@fillcolor}
\pgfsetstrokecolor{\my@color}
\pgfsetfillcolor{\my@color}
\pgfusepath{stroke,fill}
\fi
\endgroup
}
}
\makeatother
使用时可产生饱满且色彩鲜艳的花朵:
\node[flower, fill=pink, draw=purple] {};
不过,我仍有几个问题和疑问,我自己无法找到答案。
1) 如果我不使用 \begin{scope} 和 \end{scope},我不知道如何停止我在填充部分所做的剪辑。有没有办法避免使用范围?或者把它们放在那里完全没问题?
2)在绘制雄蕊时,可以使用随机函数稍微改变雄蕊的高度
\def\y{0.6+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
但每次都会重新计算 \y 的值,我不知道如何在这里修复它。
3)如果我没有指定描边和填充的颜色
fill=pink, draw=purple
我遇到了编译错误。如果我使用
\node[flower, fill, color=red] {};
那么,我该如何使用默认颜色?
4) 我想定义一个新的装饰,用随机大小的花朵装饰一条路径,而且我希望这些花朵与上图上的花朵完全相同。这是我的装饰的代码:
\pgfdeclaredecoration{flowers}{initial}{
\state{initial}[width=1cm]
{
\pgfmathparse{round(rnd*90)}
\pgftransformrotate{\pgfmathresult}
\pgfmathparse{0.2+rand*0.1}
\pgftransformscale{\pgfmathresult}
\pgfsetlinewidth{\pgfmathresult*\pgflinewidth}
\pgfsetcolor{pink}
\pgfsetfillcolor{pink}
\pgfsetstrokecolor{purple}
\pgfnode{flower}{center}{}{}{\pgfusepath{stroke,fill}}
}
\state{final}
{
\pgfpathmoveto{\pgfpointdecoratedpathlast}
}
}
我的第一个问题是,我通过调用
\draw[decorate, decoration={flowers}] (-4,-3) -- (4,-3);
而不是漂亮的填充/着色。我应该修改花的定义中的哪些部分?
那么,我更愿意使用在花朵之间随机移动的方式,该怎么做呢?
答案1
这可能还有点远,因为有几个地方我不确定你想要什么。
如果我不使用 \begin{scope} 和 \end{scope},我不知道如何停止我在填充部分所做的剪辑。有没有办法避免使用范围?或者把它们放在那里完全没问题?
您必须以
clip
某种方式限制范围,这是实现此目的的正确方法。您可以使用较低级别的命令\pgfscope
,\endpgfscope
以与命令的使用保持一致\pgf...
。在绘制雄蕊时,可以使用随机函数稍微改变它们的高度
\def\y{0.6+0.05*rand} \pgfpathlineto{\pgfpointxy{0}{\y}} \pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
但每次都会重新计算 \y 的值,我不知道如何在这里修复它。
我看到过此代码的几种用法,我猜您希望它们都相互一致。有两个问题:一个是上面的代码,另一个是全局重用。上面的代码
\y
会计算两次,每次都会使用不同的随机数。因此,您\def\y{...}
不想让\y
结果该计算的。为此,使用。第二个问题通过在适当的位置\pgfmathsetmacro\y{...}
重置 的随机种子来解决。这是使用 完成的。\pgfmath
\pgfmathsetseed
如果我没有指定描边和填充的颜色
fill=pink, draw=purple
我遇到了编译错误。如果我使用
\node[flower, fill, color=red] {};
那么,我该如何使用默认颜色?
TikZ 仅在或选项指定了明确颜色时才设置
\tikz@strokecolor
和。一般颜色保存为(请注意,这是一个颜色名称,而不是宏),因此您需要使用它。我建议在代码顶部放置一个“获取正确的颜色”位,然后使用您自己的名称。正如我在评论中所说,我并不完全清楚哪种颜色对应于花朵各部分的哪种操作(填充、描边、淡入淡出),所以我的代码(如下)可能会出错。\tikz@fillcolor
draw
fill
tikz@color
我想定义一个新的装饰,用随机大小的花朵装饰一条路径,而且我希望这些花朵与上图上的完全相同。这是我的装饰的代码:
我的第一个问题是,我通过调用得到的是“普通”花朵,而不是漂亮的填充/着色。我应该在花朵的定义中修改什么?
那么,我更愿意使用在花朵之间随机移动的方式,该怎么做呢?
简单的花朵来自于这样一个事实:您使用低级命令 (
\pgfsetstrokecolor
) 定义装饰中的颜色,但从 TikZ 级别命令 () 中提取颜色\tikz@strokecolor
。据我所知,没有办法提取当前的笔触颜色,所以我们必须使用 TikZ 方法设置它们。stroke
和fill
动作也是如此。正如您在代码中使用的那样,您必须使用指定和\tikz@mode@...
的 TikZ 方法。draw
fill
每次
width
都会重新评估,因此您可以将其设置为新的dimen
,然后在每次运行时调整此尺寸。
这是我根据您代码的改编,实现了上述所有内容。正如我所说,我认为在几个地方我并没有完全理解您所寻找的内容,但希望它足够接近,以便您知道下一步该怎么做。
\documentclass{article}
%\url{http://tex.stackexchange.com/q/110047/86}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\makeatletter
\def\pgfmathgetseed#1{%
\let#1=\pgfmath@rnd@z}
\pgfdeclareshape{flower}{
\savedanchor{\center}{%
\pgfpointorigin}
\anchor{center}{\center}
\backgroundpath{%
\begingroup
\ifx\tikz@strokecolor\pgfutil@empty
\def\my@strokecolor{tikz@color}
\else
\let\my@strokecolor\tikz@strokecolor
\fi
\ifx\tikz@fillcolor\pgfutil@empty
\def\my@fillcolor{tikz@color}
\else
\let\my@fillcolor\tikz@fillcolor
\fi
\pgfmathgetseed{\flower@seed}
\tikz@mode
\iftikz@mode@draw
\foreach \a in {60,120,...,360} {
\pgftransformrotate{\a}
\pgfpathellipse{\pgfpointxy{0}{0.7}}{\pgfpointxy{0.25}{0}}{\pgfpointxy{0}{0.5}}
}
\pgfpathcircle{\pgfpoint{0}{0}}{0.4cm}
\pgfmathsetseed{\flower@seed}
\foreach \a in {30,60,...,360} {%
\pgftransformrotate{\a+7}%
\pgfpathmoveto{\pgfpointxy{0}{0.1}}
\pgfmathsetmacro\y{0.6+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
}
\pgfsetstrokecolor{\my@strokecolor}
\pgfusepath{stroke}
\fi
\iftikz@mode@fill
\pgfscope
\foreach \a in {60,120,...,360} {
\pgftransformrotate{\a}
\pgfpathellipse{\pgfpointxy{0}{0.7}}{\pgfpointxy{0.25}{0}}{\pgfpointxy{0}{0.5}}
}
\pgfusepath{clip}
\pgfpathcircle{\pgfpointxy{0}{0}}{1.2cm}
\pgfutil@colorlet{tikz@radial@outer}{\my@fillcolor!70}
\pgfutil@colorlet{tikz@radial@inner}{\my@fillcolor!60!\my@strokecolor}
\pgfshadepath{radial}{0}
\pgfusepath{discard}
\endpgfscope
% \tikz@mode@clipfalse
\pgfsetfillcolor{\my@strokecolor}
\pgfpathcircle{\pgfpointxy{0}{0}}{0.4cm}
\pgfusepath{fill}
\pgfmathsetseed{\flower@seed}
\foreach \a in {30,60,...,360} {%
\pgftransformrotate{\a+7}%
\pgfpathmoveto{\pgfpointxy{0}{0.1}}
\pgfmathsetmacro\y{0.6+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
}
\let\my@color\my@fillcolor
\pgfutil@colorlet{\my@color}{\my@strokecolor!60!\my@fillcolor}
\pgfsetstrokecolor{\my@color}
\pgfsetfillcolor{\my@color}
\pgfusepath{stroke,fill}
\fi
\endgroup
}
}
\newdimen\flower@sep
\flower@sep=1cm\relax
\pgfdeclaredecoration{flowers}{initial}{
\state{initial}[width=\flower@sep]
{
\pgfmathparse{round(rnd*90)}
\pgftransformrotate{\pgfmathresult}
\pgfmathparse{0.2+rand*0.1}
\pgftransformscale{\pgfmathresult}
\pgfsetlinewidth{\pgfmathresult*\pgflinewidth}
\def\tikz@strokecolor{purple}
\def\tikz@fillcolor{pink}
\tikz@mode@drawtrue
\tikz@mode@filltrue
\pgfnode{flower}{center}{}{}{}
\pgfmathsetlength\flower@sep{1cm + rand*0.5cm}
\global\flower@sep=\flower@sep
}
\state{final}
{
\pgfpathmoveto{\pgfpointdecoratedpathlast}
}
}
\makeatother
\begin{document}
\tikz \node[flower, fill=pink, draw=purple] {};
\tikz \node[flower, fill, color=red] {};
\tikz \draw[decorate, decoration={flowers}] (-4,-3) -- (4,-3);
\end{document}
更新我仔细检查了一下代码,删除了一些重复部分,并整理了一些内容。代码中的注释。
\documentclass{article}
%\url{http://tex.stackexchange.com/q/110047/86}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\makeatletter
\tikzset{
flower shade colour/.store in=\my@shadecolour,
flower shade color/.store in=\my@shadecolour,
flower shade colour=white
}
\pgfdeclareshape{flower}{
\savedanchor{\center}{%
\pgfpointorigin}
\anchor{center}{\center}
%
% We use \beforebackgroundpath since we're handling the stroke and
% fills ourselves.
%
\beforebackgroundpath{%
\begingroup
%
% Do our very best to set the colours.
%
% Was a stroke colour set explicitly (via draw=<colour>)?
\ifx\tikz@strokecolor\pgfutil@empty
% No, so test if a general colour was set.
\@ifundefinedcolor{tikz@color}{%
% No, so take the current colour.
\def\my@strokecolor{.}%
}{%
% General colour was set so use that
\def\my@strokecolor{tikz@color}%
}%
\else
% Stroke colour was set, so use that
\let\my@strokecolor\tikz@strokecolor
\fi
%
% Now the same for the fill colour.
% Was a fill colour set explicitly?
\ifx\tikz@fillcolor\pgfutil@empty
% No, so was a general colour set?
\@ifundefinedcolor{tikz@color}{%
% No, so reuse the stroke colour.
\let\my@fillcolor\my@strokecolor
}{%
% General colour was set, use that.
\def\my@fillcolor{tikz@color}%
}%
\else
% Specific fill colour was set, so use that.
\let\my@fillcolor\tikz@fillcolor
\fi
%
% Test for the mode
%
\tikz@mode
%
% Draw the petals.
%
\foreach \a in {60,120,...,360} {
\pgftransformrotate{\a}
\pgfpathellipse{\pgfpointxy{0}{0.7}}{\pgfpointxy{0.25}{0}}{\pgfpointxy{0}{0.5}}
}
%
% If fill is requested, shade them using the fill colour and the
% (extra) shade colour.
%
\iftikz@mode@fill
\pgfutil@colorlet{tikz@radial@outer}{\my@fillcolor}
\pgfutil@colorlet{tikz@radial@inner}{\my@shadecolour}
\pgfshadepath{radial}{0}
\pgfusepath{discard}
\else
\iftikz@mode@draw
%
% If fill mode was not requested but draw mode was, stroke the path.
%
\pgfusepath{stroke}
\fi
\fi
%
% Now the centre of the flower; filled if requested, if not filled
% then drawn if requested.
%
\pgfpathcircle{\pgfpointxy{0}{0}}{0.4cm}
\iftikz@mode@fill
\pgfsetfillcolor{\my@strokecolor}
\pgfusepath{fill}
\else
\iftikz@mode@draw
\pgfsetstrokecolor{\my@strokecolor}
\pgfusepath{stroke}
\fi
\fi
%
% Lastly the stamen.
% If fill was requested then we also stroke the paths (to get the
% stalk part - biology was never my strong point).
% Note that we push the circles out by their radius so that if
% drawn then it still looks right.
%
\foreach \a in {30,60,...,360} {%
\pgftransformrotate{\a+7}%
\pgfpathmoveto{\pgfpointxy{0}{0.1}}
\pgfmathsetmacro\y{0.6+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y + 0.05}}{0.05cm}
}
\let\my@color\my@fillcolor
\pgfutil@colorlet{\my@color}{\my@strokecolor!60!\my@fillcolor}
\pgfsetstrokecolor{\my@color}
\iftikz@mode@fill
\pgfsetfillcolor{\my@color}
\pgfusepath{stroke,fill}
\else
\iftikz@mode@draw
\pgfusepath{stroke}
\fi
\fi
\endgroup
}
}
%
% This holds our state widths for the decoration so that we
% can vary them each time.
%
\newdimen\flower@sep
\flower@sep=1cm\relax
\pgfdeclaredecoration{flowers}{initial}{
\state{initial}[width=\flower@sep]
{
\pgfmathparse{round(rnd*90)}
\pgftransformrotate{\pgfmathresult}
\pgfmathparse{0.2+rand*0.1}
\pgftransformscale{\pgfmathresult}
\pgfsetlinewidth{\pgfmathresult*\pgflinewidth}
%
% These should be customisable, I guess.
%
\def\tikz@strokecolor{purple}
\def\tikz@fillcolor{pink}
\tikz@mode@drawtrue
\tikz@mode@filltrue
\pgfnode{flower}{center}{}{}{}
%
% Reset the width
%
\pgfmathsetlength\flower@sep{1cm + rand*0.5cm}
\global\flower@sep=\flower@sep
}
\state{final}
{
\pgfpathmoveto{\pgfpointdecoratedpathlast}
}
}
\makeatother
\begin{document}
\tikz \node[flower, fill=pink, draw=purple] {};
\tikz \node[flower, fill, color=red] {};
\tikz \node[flower, draw=red] {};
\tikz \draw[decorate, decoration={flowers}] (-4,-3) -- (4,-3);
\end{document}