编辑

编辑

我有这个饼图代码。我希望线条与每个切片相对应,我已经更改了数字并尝试包含 \def\stackalignment{l},但不起作用。

\documentclass{article}

\usepackage{tikz,stackengine}

\def\stackalignment{r}
 \newcommand\pielabelon[3][0pt]{%
\abovebaseline[#3]{#2%
    \makebox[-\dimexpr8pt+#1]{\smash{%
            \stackunder{}{\rule{1pt}{\dimexpr#3+2.5ex}}}}}
   }
  \newcommand\pielabelunder[3][0pt]{%
\belowbaseline[#3]{#2%
    \makebox[-\dimexpr8pt+#1]{\smash{%
            \stackon{\rule{0pt}{1.3ex}}{\rule{1pt} {\dimexpr#3+2.5ex}}}}}
}


     \newcommand{\slice}[4]{
\pgfmathparse{0.5*#1+0.5*#2}
\let\midangle\pgfmathresult

% slice
\draw[thick,fill=black!10] (0,0) -- (#1:1) arc (#1:#2:1) -- cycle;

% outer label
\node[label=\midangle:#4] at (\midangle:1) {};

% inner label
\pgfmathparse{min((#2-#1-10)/110*(-0.3),0)}
\let\temp\pgfmathresult
\pgfmathparse{max(\temp,-0.5) + 0.8}
\let\innerpos\pgfmathresult
\node at (\midangle:\innerpos) {#3};
     }

     \newcounter{a}
      \newcounter{b}

    \begin{document}


\begin{tikzpicture}

        \newcounter{i}
        \newcounter{j}
        \foreach \p/\t in {
            30/Absolute Return Bonds,
            10/\pielabelon[20pt]{Euro Corporate bonds ($>$10 years) (10\%)}{2.5ex},
            4/\pielabelon[15pt]{Eurozone Equities (4\%)}{2.5ex},
            3/\pielabelon[6pt]{Fixed Interest euro govt Bonds ($>$5years) (3\%)}{1ex},
            48/Global equities,
            2/\pielabelunder{Index-Linked euro govts (AS) (2\%)}{2.5ex},
            3/\pielabelunder{Property (3\%)}{0ex}}
        {
            \setcounter{a}{\value{b}}
            \addtocounter{b}{\p}
            \slice{\thea/100*360}
            {\theb/100*360}
            {\ifnum\p>10\relax\p\%\fi}{\t}
        }

        \end{tikzpicture}

      \end{document}

另外,可以将图例分成两行吗?我尝试添加 \ \,但没有成功。

答案1

现有代码的问题在于它相当不灵活。例如,您无法轻松调整它以在某个线段和标记它的文本之间以一定角度绘制一条线,因为这些线根本不是用 TikZ 绘制的。该代码也过于复杂,因为它坚持使用非 TikZ 的东西来创建标签,这使得很难跟踪它们的位置,因为您没有通过节点获得的锚点。

我认为想要的结果类似于以下内容。但是,我对此完全不确定,因为尽管进行了多次编辑,但我仍然不清楚您要做什么。哪个线?还有什么到底是怎么回事?

饼形图

下面的代码将标签作为\slice宏的一部分创建。我意识到您希望与文档中的其他图表保持一致。如果这是一次性的,只需为宏使用不同的名称\slice并在此处使用它。但是,如果这个问题适用于您的许多图表,我会用这个或另一个 Ti 替换代码Z 方法使事情变得灵活,并简化代码以实现透明度和易于定制。最好使用现有的软件包之一,但如果做不到,至少使用可以根据需要轻松扩展或调整的代码。

stackengine令人印象深刻,可能可以在这里使用。但是没有理由在这里使用它,因为 TiZ 可以更直接、更灵活、更透明地满足您的需求。无缘无故地给自己找麻烦是常有的事。如果您被不灵活的代码困住了,通常更有效的方法是减少损失,用更灵活的解决方案替换它。替换它所花的时间永远不会像您担心的那样长;修改它所花的时间总是比您希望的要长。从本质上讲,这就是它一开始就不灵活的原因。

仅仅因为你可以用手机敲钉子并不意味着你不应该去商店买一把像样的锤子。你认为这一路要花很长时间。你希望接下来的五打钉子用手机敲得比前十几打钉子更快。别自欺欺人了:最好现在就拿到锤子,而不是等到以后再拿。

循环中使用了三个变量,而不是两个,但所需的信息仍然比以前少。第一个变量和以前一样是百分比。第二个变量是标签本身的内容。第三个变量是避免文本冲突所需的任何垂直调整:正值表示向上,负值表示向下。

\documentclass[border=10pt,multi,tikz]{standalone}
\newcommand{\slice}[4]{
  \pgfmathsetmacro\midangle{0.5*#1+0.5*#2}
  % slice
  \draw[thick,fill=black!10] (0,0) -- (#1:1) arc (#1:#2:1) -- cycle;
  outer label
  \node  [label={[name=l \j]\midangle:#3}, yshift=#4] at (\midangle:1.15) {};
  inner label
  \pgfmathsetmacro\innerpos{max(min((#2-#1-10)/110*(-0.3),0),-.5) +.8}
  \pgfmathsetmacro\labelanchor{ ( \midangle < 90 ) ? "south west" : ( ( \midangle < 180 ) ? "east" : ( ( \midangle < 270 ) ? "north" : "west" ) ) }
  \draw (\midangle:\innerpos) -- (l \j.\labelanchor);
}
\newcounter{a}
\newcounter{b}
\begin{document}
\begin{tikzpicture}
  \foreach \p/\t/\n [count=\j] in {%
    30/Absolute Return Bonds/0pt,
    10/Euro Corporate bonds ($>$10 years) (10\%)/0pt,
    4/Eurozone Equities (4\%)/0pt,
    3/Fixed Interest euro govt Bonds ($>$5years) (3\%)/-5pt,
    48/Global equities/0pt,
    2/Index-Linked euro govts (AS) (2\%)/-5pt,
    3/Property (3\%)/0pt
  }
  {
    \setcounter{a}{\value{b}}
    \addtocounter{b}{\p}
    \slice{\thea/100*360}
    {\theb/100*360}
    {\t}
    {\n}
  }
\end{tikzpicture}
\end{document}

编辑

如果您希望较大的百分比出现在段中,我会将百分比从标签中完全取出,并有条件地将其添加为 的一部分\slice。但是,在这种情况下,图表需要按比例放大,否则就没有空间放置10%标签。(或者,您可以更改在段中放置标签的截止点 -30%48%在较小的图表中不是问题。)

例如,

\documentclass[border=10pt,multi,tikz]{standalone}
\newcommand{\slice}[4]{
  \pgfmathsetmacro\midangle{0.5*#1+0.5*#2}
  % slice
  \draw[thick,fill=black!10] (0,0) -- (#1:1) arc (#1:#2:1) -- cycle;
  \ifnum\p<10
    \def\plabel{#3 (\p\%)}%
    \def\slabel{}%
  \else
    \def\plabel{#3}%
    \def\slabel{\p\%}%
  \fi
  %outer label
  \node  [label={[name=l \j]\midangle:\plabel}, yshift=#4] at (\midangle:1.15) {};
  %inner label
  \pgfmathsetmacro\innerpos{max(min((#2-#1-10)/110*(-0.3),0),-.5) +.8}
  \pgfmathsetmacro\labelanchor{ ( \midangle < 90 ) ? "south west" : ( ( \midangle < 180 ) ? "east" : ( ( \midangle < 270 ) ? "north" : "west" ) ) }
  \node (slabel \j) at (\midangle:\innerpos) {\slabel};
  \draw (slabel \j) -- (l \j.\labelanchor) ;
}
\newcounter{a}
\newcounter{b}
\begin{document}
\begin{tikzpicture}[scale=2]
  \foreach \p/\t/\n [count=\j] in {%
    30/Absolute Return Bonds/0pt,
    10/Euro Corporate bonds ($>$10 years)/0pt,
    4/Eurozone Equities/0pt,
    3/Fixed Interest euro govt Bonds ($>$5years)/-5pt,
    48/Global equities/0pt,
    2/Index-Linked euro govts (AS)/-5pt,
    3/Property/0pt
  }
  {
    \setcounter{a}{\value{b}}
    \addtocounter{b}{\p}
    \slice{\thea/100*360}
    {\theb/100*360}
    {\t}
    {\n}
  }
\end{tikzpicture}
\end{document}

带分段标签的图表

相关内容