我尝试做出这种形状但遇到了几个问题。
首先将徽标放在椭圆内,我使用了
\pgftransformcm{1}{0}{0}{1}{\centerpoint}
也许有更好的解决方案。我需要\pgftransformcm{-1}{0}{0}{1}{\centerpoint}
在最后使用,因为文本是反转的,但是随着所有转换,我失去了基线并且文本放错了位置。这是主要问题我尝试使用
\inheritsavedanchors
但没有成功为了获得良好的结果,我认为保持高度和宽度之间的比例很重要,但如何做到这一点?
也许计算不正确,但我更愿意在重新进行所有计算之前先了解我需要做什么。可以使用高度/宽度比率来获得更好的结果。
这是长代码,当我固定尺寸时结果很好。
\documentclass{article}
\usepackage{tikz,fullpage}
\usetikzlibrary{shapes}
\begin{document}
\thispagestyle{empty}
\makeatletter
\newdimen\batmanx
\newdimen\batmany
\tikzset{ shape example/.style={
color=black!30,
draw,
fill=yellow!30,
line width=.5cm,
inner xsep=2.5cm,
inner ysep=0.5cm}
}
\pgfdeclareshape{batman}
{
\savedanchor\centerpoint{%
\pgf@x=.5\wd\pgfnodeparttextbox%
\pgf@y=.5\ht\pgfnodeparttextbox%
\advance\pgf@y by-.5\dp\pgfnodeparttextbox%
}
\savedanchor\radius{%
%
% Caculate ``height radius''
%
\pgf@y=.5\ht\pgfnodeparttextbox%
\advance\pgf@y by .5\dp\pgfnodeparttextbox%
\pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
\advance\pgf@y by\pgf@yb%
%
% Caculate ``width radius''
%
\pgf@x=.5\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
\advance\pgf@x by\pgf@xb%
%
% Adjust
%
\pgf@x=1.4142136\pgf@x%
\pgf@y=1.4142136\pgf@y%
%
% Adjust height, if necessary
%
\pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/minimum height}}%
\ifdim\pgf@y<.5\pgf@yc%
\pgf@y=.5\pgf@yc%
\fi%
%
% Adjust width, if necessary
%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
\ifdim\pgf@x<.5\pgf@xc%
\pgf@x=.5\pgf@xc%
\fi%
%
% Add outer sep
%
\pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
\advance\pgf@x by\pgf@xb%
\advance\pgf@y by\pgf@yb%
}
% Anchors
\anchor{center}{\centerpoint}
\anchor{mid}{\centerpoint\pgfmathsetlength\pgf@y{.5ex}}
\anchor{base}{\centerpoint\pgf@y=0pt}
\anchor{north}
{
\pgf@process{\radius}
\pgf@ya=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@y by\pgf@ya
}
\anchor{south}
{
\pgf@process{\radius}
\pgf@ya=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@y by-\pgf@ya
}
\anchor{west}
{
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by-\pgf@xa
}
\anchor{mid west}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by-\pgf@xa%
\pgfmathsetlength\pgf@y{.5ex}
}
\anchor{base west}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by-\pgf@xa%
\pgf@y=0pt
}
\anchor{north west}
{
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@x by-0.707107\pgf@xa
\advance\pgf@y by0.707107\pgf@ya
}
\anchor{south west}
{
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@x by-0.707107\pgf@xa
\advance\pgf@y by-0.707107\pgf@ya
}
\anchor{east}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by\pgf@xa
}
\anchor{mid east}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by\pgf@xa%
\pgfmathsetlength\pgf@y{.5ex}
}
\anchor{base east}
{%
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@process{\centerpoint}
\advance\pgf@x by\pgf@xa%
\pgf@y=0pt
}
\anchor{north east}
{
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@x by0.707107\pgf@xa
\advance\pgf@y by0.707107\pgf@ya
}
\anchor{south east}
{
\pgf@process{\radius}
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\centerpoint}
\advance\pgf@x by0.707107\pgf@xa
\advance\pgf@y by-0.707107\pgf@ya
}
\anchorborder{
\edef\pgf@marshal{%
\noexpand\pgfpointborderellipse
{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
{\noexpand\radius}%
}%
\pgf@marshal%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\centerpoint%
\advance\pgf@x by\pgf@xa%
\advance\pgf@y by\pgf@ya%
}
%
% Background path
%
\backgroundpath
{
\pgf@process{\radius}%
\pgfutil@tempdima=\pgf@x%
\pgfutil@tempdimb=\pgf@y%
\pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
\advance\pgfutil@tempdima by-\pgf@xb%
\advance\pgfutil@tempdimb by-\pgf@yb%
\batmanx=\pgfutil@tempdima%
\batmany=\pgfutil@tempdimb%
\pgfpathellipse{\centerpoint}
{\pgfqpoint{\pgfutil@tempdima}{0pt}}
{\pgfqpoint{0pt}{\pgfutil@tempdimb}}%
\pgfsetfillopacity{.5}
\pgfsetfillcolor{yellow}
\pgfusepath{fill,stroke}
\pgfsetlinewidth{0.05\pgfutil@tempdima}%
\pgfutil@tempdima=0.90\pgfutil@tempdima%
\pgfutil@tempdimb=0.90\pgfutil@tempdimb%
\pgfpathellipse{\centerpoint}{\pgfqpoint{\pgfutil@tempdima}{0pt}}
{\pgfqpoint{0pt}{\pgfutil@tempdimb}}%
\pgfusepath{stroke}
\pgfsetlinewidth{0.4 pt}
\pgftransformcm{1}{0}{0}{1}{\centerpoint}
\pgfpathmoveto{\pgfpoint{0 cm}{0.66\batmany}}
\pgfpathlineto{\pgfqpoint{0.07\batmanx}{0.66\batmany}}
\pgfpathlineto{\pgfqpoint{0.14\batmanx}{0.793\batmany}}
\pgfpathcurveto{\pgfqpoint{0.17\batmanx}{0.317\batmany}}
{\pgfqpoint{0.186\batmanx}{0.24\batmany}}
{\pgfqpoint{0.28\batmanx}{0.24\batmany}}
\pgfpathcurveto{\pgfqpoint{0.42\batmanx}{0.24\batmany}}
{\pgfqpoint{0.42\batmanx}{0.537\batmany}}
{\pgfqpoint{0.28\batmanx}{0.756\batmany}}
\pgfpatharcto{0.84\batmanx}{0.80\batmany}{0}{0}{0}
{\pgfqpoint{0.457\batmanx}{-0.683\batmany}}
\pgfpathcurveto{\pgfqpoint{0.56\batmanx}{-0.488\batmany}}
{\pgfqpoint{0.56\batmanx}{0 cm}}
{\pgfqpoint{0.314\batmanx}{-0.44\batmany}}
\pgfpathcurveto{\pgfqpoint{0.214\batmanx}{-0.24\batmany}}
{\pgfqpoint{0.14\batmanx}{-0.24\batmany}}
{\pgfqpoint{0 cm}{-0.78\batmany}}
\pgftransformcm{-1}{0}{0}{1}{\pgfpointorigin}
\pgfpathcurveto{\pgfpoint{0.14\batmanx}{-0.24\batmany}}
{\pgfpoint{0.214\batmanx}{-0.24\batmany}}
{\pgfpoint{0.314\batmanx}{-0.44\batmany}}
\pgfpathcurveto{\pgfpoint{0.56\batmanx}{0 cm}}
{\pgfpoint{0.56\batmanx}{-0.488\batmany}}
{\pgfpoint{0.457\batmanx}{-0.683\batmany}}
\pgfpatharcto{0.84\batmanx}{0.80\batmany}{0}{0}{1}
{\pgfpoint{0.28\batmanx}{0.756\batmany}}
\pgfpathcurveto{\pgfpoint{0.42\batmanx}{0.537\batmany}}
{\pgfpoint{0.42\batmanx}{0.24\batmany}}
{\pgfpoint{0.28\batmanx}{0.24\batmany}}%
\pgfpathcurveto{\pgfqpoint{0.186\batmanx}{0.24\batmany}}
{\pgfqpoint{0.17\batmanx}{0.317\batmany}}
{\pgfqpoint{0.14\batmanx}{0.793\batmany}}
\pgfpathlineto{\pgfqpoint{0.07\batmanx}{0.66\batmany}}%
\pgfpathmoveto{\pgfpoint{0 cm}{0.66\batmany}}
\pgfsetfillopacity{1}%
\pgfsetfillcolor{black}%
\pgfusepath{fill,stroke}
\pgftransformcm{-1}{0}{0}{1}{\centerpoint}%
\pgfsetlinewidth{0.4pt}%
}
}
\Huge
\begin{tikzpicture}
\node[name=s,shape=batman,minimum height=8.2cm,minimum width=14cm] {\color{red}Batman\vrule width 1pt height 2cm};
\foreach \anchor/\placement in
{north west/above left, north/above, north east/above right,
west/left, center/above, east/right,
mid west/right, mid/above, mid east/left,
base west/left, base/below, base east/right,
south west/below left, south/below, south east/below right,
text/left, 10/right, 130/above}
\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)}
node[\placement] {\color{red}\scriptsize\texttt{(s.\anchor)}};
\end{tikzpicture}
\end{document}
使用下面的代码,结果是正确的
\begin{tikzpicture}
\node[draw,shape=batman,minimum height=4.1cm,minimum width=7cm,text=white] (A) {\Large Bat me up};
\node[draw,shape=batman,minimum height=8.2cm,minimum width=14cm,text=white] (B) at ([yshift=-12cm]A) {\Huge Bat me down };
\draw [red,ultra thick,double,->](A) --(B);
\end{tikzpicture}
与
\begin{tikzpicture}
\node[draw,shape=batman,text=white] (A) {\Large Bat me up};
\node[draw,shape=batman,text=white] (B) at ([yshift=-3cm]A) {\Huge Bat me down };
\draw [red,ultra thick,double,->](A) --(B);
\end{tikzpicture}
这非常糟糕(比例文本等)
答案1
您需要包含您的变换,pgf
并进行自己的变换来放置其节点,因此您需要尊重这一点。当您在另一个变换之上进行变换时,就会出现问题。
您可以通过在第一个组之前放置一个组\pgftransformcm
并在背景路径的底部放置一个结束组来避免这种情况。
%
% Background path
%
\backgroundpath
{
% commented out...
% interesting drawing...
% commented out...
\bgroup
\pgftransformcm{1}{0}{0}{1}{\centerpoint}
\pgfpathmoveto{\pgfpoint{0 cm}{0.66\batmany}}
\pgfpathlineto{\pgfqpoint{0.07\batmanx}{0.66\batmany}}
\pgfpathlineto{\pgfqpoint{0.14\batmanx}{0.793\batmany}}
\pgfpathcurveto{\pgfqpoint{0.17\batmanx}{0.317\batmany}}
{\pgfqpoint{0.186\batmanx}{0.24\batmany}}
{\pgfqpoint{0.28\batmanx}{0.24\batmany}}
...
...
...
\pgfpathmoveto{\pgfpoint{0 cm}{0.66\batmany}}
\pgfsetfillopacity{1}%
\pgfsetfillcolor{black}%
\pgfusepath{fill,stroke}
\egroup
\pgfsetlinewidth{0.4pt}%
}
然后您的文本将显示在text
锚点处。
为了保持一定的纵横比,您应该计算高度和宽度。检查用户给出的数值,然后根据任何规定的方法从其中之一计算比率。这可以通过简单的 if 和检查来完成,相当于以下内容,可以扩展以满足您的需求:
% Calculate height, this example puts a minimum height of the
% shape dependent on the text contained.
\pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/batman/minimum height}}%
\pgf@y=2\ht\pgfnodeparttextbox%
\ifdim\pgf@y<\pgf@ya%
\pgf@y=\pgf@ya%
\fi%
% do more computational work...
...
% You could do checks of aspect ratio, which I would recommend:
\pgf@ya=.25\pgf@x
\pgf@xa=4\pgf@y%
\ifdim\pgf@yc<\pgf@ya%
\pgf@y=\pgf@ya%
\fi%
\ifdim\pgf@xc<\pgf@xa%
\pgf@x=\pgf@xa%
\fi%
此外,我同意percusse
,你应该试着规避 transformcm,因为你严格来说不需要它。
您可以使用:
\pgftransformshift{\centerpoint}
为您的第一次transformcm
和:
\pgftransformxscale{-1}
这是您的第二个transformcm
。
代码由 Altermundus 添加。
我应用了 zeroth(我的主机)给出的注释和代码。首先,我使用 TeX 组来限制某些变换的动作,然后我删除transformcm
并使用了更简单的宏\pgftransformshift{\centerpoint}
。zeroth\pgftransformxscale{-1}
给了我保持高度和宽度之间良好比例的想法,最后 Jake 的一个很好的回答给了我使用继承形状的最后一个关键。
\documentclass[landscape]{scrartcl}
\usepackage{tikz,fullpage}
\usetikzlibrary{shapes}
\begin{document}
\thispagestyle{empty}
\makeatletter
\newdimen\batmanx
\newdimen\batmany
\tikzset{ shape example/.style={
color=black!30,
draw,
fill=yellow!30,
line width=.5cm,
inner xsep=2.5cm,
inner ysep=0.5cm}
}
\pgfdeclareshape{batman}
{
\inheritsavedanchors[from=ellipse]
\inheritanchorborder[from=ellipse]
%
\savedanchor\centerpoint{%
\pgf@x=.5\wd\pgfnodeparttextbox%
\pgf@y=.5\ht\pgfnodeparttextbox%
\advance\pgf@y by-.5\dp\pgfnodeparttextbox%
}
\savedanchor\radius{%
\pgf@x=.5\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
\advance\pgf@x by\pgf@xb%
\pgf@x=1.4142136\pgf@x%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
\ifdim\pgf@x<.5\pgf@xc%
\pgf@x=.5\pgf@xc%
\fi%
% good ratio
\pgf@y=0.586\pgf@x
\pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/minimum height}}%
\ifdim\pgf@y<.5\pgf@yc%
\pgf@y=.5\pgf@yc%
\fi%
\pgf@x=1.707\pgf@y
\pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
\advance\pgf@x by\pgf@xb%
\advance\pgf@y by\pgf@yb%
}
% Anchors
\inheritanchor[from=ellipse]{center}
\inheritanchor[from=ellipse]{mid}
\inheritanchor[from=ellipse]{base}
\inheritanchor[from=ellipse]{north}
\inheritanchor[from=ellipse]{south}
\inheritanchor[from=ellipse]{west}
\inheritanchor[from=ellipse]{mid west}
\inheritanchor[from=ellipse]{base west}
\inheritanchor[from=ellipse]{north west}
\inheritanchor[from=ellipse]{south west}
\inheritanchor[from=ellipse]{east}
\inheritanchor[from=ellipse]{mid east}
\inheritanchor[from=ellipse]{base east}
\inheritanchor[from=ellipse]{north east}
\inheritanchor[from=ellipse]{south east}
% Background path
\backgroundpath
{
\pgf@process{\radius}%
\pgfutil@tempdima=\pgf@x%
\pgfutil@tempdimb=\pgf@y%
\pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
\advance\pgfutil@tempdima by-\pgf@xb%
\advance\pgfutil@tempdimb by-\pgf@yb%
\batmanx=\pgfutil@tempdima%
\batmany=\pgfutil@tempdimb%
\pgfpathellipse{\centerpoint}
{\pgfqpoint{\pgfutil@tempdima}{0pt}}
{\pgfqpoint{0pt}{\pgfutil@tempdimb}}%
\pgfsetfillopacity{.5}
\pgfsetfillcolor{yellow}
\pgfusepath{fill,stroke}
\pgfsetlinewidth{0.05\pgfutil@tempdima}%
\pgfutil@tempdima=0.90\pgfutil@tempdima%
\pgfutil@tempdimb=0.90\pgfutil@tempdimb%
\pgfpathellipse{\centerpoint}{\pgfqpoint{\pgfutil@tempdima}{0pt}}
{\pgfqpoint{0pt}{\pgfutil@tempdimb}}%
\pgfusepath{stroke}
\pgfsetlinewidth{0.4 pt}
\bgroup
\pgftransformshift{\centerpoint}
\pgfpathmoveto{\pgfpoint{0 cm}{0.66\batmany}}
\pgfpathlineto{\pgfqpoint{0.07\batmanx}{0.66\batmany}}
\pgfpathlineto{\pgfqpoint{0.14\batmanx}{0.793\batmany}}
\pgfpathcurveto{\pgfqpoint{0.17\batmanx}{0.317\batmany}}
{\pgfqpoint{0.186\batmanx}{0.24\batmany}}
{\pgfqpoint{0.28\batmanx}{0.24\batmany}}
\pgfpathcurveto{\pgfqpoint{0.42\batmanx}{0.24\batmany}}
{\pgfqpoint{0.42\batmanx}{0.537\batmany}}
{\pgfqpoint{0.28\batmanx}{0.756\batmany}}
\pgfpatharcto{0.84\batmanx}{0.80\batmany}{0}{0}{0}
{\pgfqpoint{0.457\batmanx}{-0.683\batmany}}
\pgfpathcurveto{\pgfqpoint{0.56\batmanx}{-0.488\batmany}}
{\pgfqpoint{0.56\batmanx}{0 cm}}
{\pgfqpoint{0.314\batmanx}{-0.44\batmany}}
\pgfpathcurveto{\pgfqpoint{0.214\batmanx}{-0.24\batmany}}
{\pgfqpoint{0.14\batmanx}{-0.24\batmany}}
{\pgfqpoint{0 cm}{-0.78\batmany}}
\pgftransformxscale{-1}
\pgfpathcurveto{\pgfpoint{0.14\batmanx}{-0.24\batmany}}
{\pgfpoint{0.214\batmanx}{-0.24\batmany}}
{\pgfpoint{0.314\batmanx}{-0.44\batmany}}
\pgfpathcurveto{\pgfpoint{0.56\batmanx}{0 cm}}
{\pgfpoint{0.56\batmanx}{-0.488\batmany}}
{\pgfpoint{0.457\batmanx}{-0.683\batmany}}
\pgfpatharcto{0.84\batmanx}{0.80\batmany}{0}{0}{1}
{\pgfpoint{0.28\batmanx}{0.756\batmany}}
\pgfpathcurveto{\pgfpoint{0.42\batmanx}{0.537\batmany}}
{\pgfpoint{0.42\batmanx}{0.24\batmany}}
{\pgfpoint{0.28\batmanx}{0.24\batmany}}%
\pgfpathcurveto{\pgfqpoint{0.186\batmanx}{0.24\batmany}}
{\pgfqpoint{0.17\batmanx}{0.317\batmany}}
{\pgfqpoint{0.14\batmanx}{0.793\batmany}}
\pgfpathlineto{\pgfqpoint{0.07\batmanx}{0.66\batmany}}%
\pgfpathlineto{\pgfpoint{0 cm}{0.66\batmany}}
\pgfsetfillopacity{1}%
\pgfsetfillcolor{black}%
\pgfusepath{fill,stroke}
\egroup
\pgfsetlinewidth{0.4pt}%
}
}
{\Huge
\begin{center}
\begin{tikzpicture}
\node[name=s,shape=batman,minimum height=8cm] {\color{red}Batman\vrule width 1pt height 2cm};
\foreach \anchor/\placement in
{north west/above left, north/above, north east/above right,
west/left, center/above, east/right,
mid west/right, mid/above, mid east/left,
base west/left, base/below, base east/right,
south west/below left, south/below, south east/below right,
text/left, 10/right, 130/above}
\draw[shift=(s.\anchor),color=red] plot[mark=x] coordinates{(0,0)}
node[\placement] {\color{red}\scriptsize\texttt{(s.\anchor)}};
\end{tikzpicture}
\end{center}
}
\newpage
\begin{tikzpicture}
\node[draw,shape=batman,
text=yellow] (A) {\Large Bat me up};
\node[draw,shape=batman,
minimum width=14cm,
text=yellow] (B) at ([yshift=-8cm]A) {\Huge Bat me down };
\draw [red,ultra thick,double,->](A) --(B);
\end{tikzpicture}
\end{document}
在下一张图片中我用的是minimum height=8cm
对于最后一个,对于第一个节点我没有使用任何内容,对于第二个节点我没有使用任何内容minimum width=14cm
。
待办事项:也许验证一些计算来绘制形状。