如何存储和检索固定布局的数据?

如何存储和检索固定布局的数据?

我今天的问题是关于当我想创建固定设计时,存储数据的合适方法。假设我在 TikZ 绘图中有一个给定的布局,我想在其中有动态文本。但是用户不必面对 TikZ 代码,他只需定义内容,然后我将其填充到 TikZ 节点中。所以这是我的示例:

\documentclass[tikz]{standalone}

\begin{document}
    \begin{tikzpicture}
    \node(center)[fill=cyan,circle,minimum size=3cm] at (135:10cm) {Topic};
    \foreach \i in {0,...,7}
    {
        \node(bubble)[fill=green,text width=2cm,circle,align=center] at (\i*20:\i*3cm) {\textbf{Heading \i}\\Content};
        \draw (center) -- (bubble);
    }
    \end{tikzpicture}
\end{document}

现在我的节点已经设置好了,但是预先提供数据的合适方法是什么呢?当然,我可以为每个节点定义一个宏,如下所示:

\newcommand{\headingone}{Heading 1}
\newcommand{\contentone}{Content 1}

然后使用这些宏来读取数据。但是,难道没有更简单、更数据驱动的方法吗?由于图表不应动态增长,我不想创建一个包含项目的环境,尽管这对我来说似乎是一种可行的方法。但是,难道没有更聪明的方法来做到这一点吗?

答案1

我不太清楚您想要什么,但您可以创建两个clist并将数据存储在那里。tikzpicture然后您可以在 中检索循环内的数据\foreach

确切的实现取决于您想要存储的数据类型,但对于简单的字符串,它可以像这样工作:

\documentclass[tikz]{standalone}

\ExplSyntaxOn
\clist_new:N \l_mypic_headers_clist 
\clist_new:N \l_mypic_contents_clist 

\NewDocumentCommand { \getHeadersAtIndex } { m } {
    \clist_item:Nn \l_mypic_headers_clist { #1 }
}

\NewDocumentCommand { \getContentsAtIndex } { m } {
    \clist_item:Nn \l_mypic_contents_clist { #1 }
}

\NewDocumentCommand { \getMaxIndex } { } {
    \clist_count:N \l_mypic_headers_clist
}

\NewDocumentCommand { \addToLists } { m m } { 
    \clist_put_right:Nn \l_mypic_headers_clist { { #1 } }
    \clist_put_right:Nn \l_mypic_contents_clist { { #2 } }
}
\ExplSyntaxOff

\addToLists{Header 1}{Contents 1}
\addToLists{Header 2}{Contents 2}
\addToLists{Header 3}{Contents 3}
\addToLists{Header 4}{Contents 4}
\addToLists{Header 5}{Contents 5}
\addToLists{Header 6}{Contents 6}
\addToLists{Header 7}{Contents 7}

\begin{document}
    \begin{tikzpicture}
    \node(center)[fill=cyan,circle,minimum size=3cm] at (135:10cm) {Topic};
    \foreach \i in {1,...,\getMaxIndex} {
        \node(bubble)[fill=green,text width=2cm,circle,align=center] at (\i*20:\i*3cm) 
        {\textbf{\getHeadersAtIndex{\i}} \\ \getContentsAtIndex{\i}};
        \draw (center) -- (bubble);
    }
    \end{tikzpicture}
\end{document}

如果您需要更强大的设置,您可以使用序列而不是逗号列表进行存储。只需将上述代码中的clist每个替换为即可。seq


编辑

您可以在块内添加以下函数ExplSyntax

\NewDocumentCommand { \addMultipleToLists } { m } { 
    \clist_map_inline:nn { #1 } {
        \clist_put_right:Nn \l_mypic_headers_clist { 
            \clist_item:nn { ##1 } { 1 }
        }
        \clist_put_right:Nn \l_mypic_contents_clist { 
            \clist_item:nn { ##1 } { 2 }
        }
    }
}

然后,您可以使用一种可能更方便的方式来输入数据(请注意,在这种情况下,如果文本包含逗号,则需要将其括在额外的括号中,并且显然不能简单地在此处切换到序列,因为您首先向宏提供了逗号列表):

\addMultipleToLists{{Header 1,Contents 1},
                    {Header 2,Contents 2},
                    {Header 3,Contents 3},
                    {Header 4,Contents 4},
                    {Header 5,Contents 5},
                    {Header 6,Contents 6},
                    {Header 7,Contents 7}}

在此处输入图片描述

答案2

此 PGFkeys 支持的解决方案支持以下形式的列表

{{Header 1, Content 1}, {Header 2, Content 2}, {…}, …}

{Header 1, Content 1, Header 2, Content 2, …

后者是默认的list use = all comma,前者可以与一起使用list use = tuples

为了放置绿色节点,我使用chains图书馆的

on chain = <chain name> placed {at = (<calculation>)}

简单来说(<calculation>)就是

(\tikzchaincount*20: \tikzchaincount*3cm)

即与您的相同,但\i替换为\tikzchaincount

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{chains}
\makeatletter
\tikzset{
  /utils/if not empty/.code 2 args={%
    \if\relax\detokenize{#1}\relax\expandafter\pgfutil@gobble
                             \else\expandafter\pgfutil@firstofone\fi
                             {\pgfkeysalso{#2}}}}
\makeatother
\tikzset{
  % defaults
  topic style/.style={shape=circle, minimum size=3cm, fill=cyan},
  list style/.style={fill=green, text width=2cm, circle, align=center},
  topic/.initial=Topic,
  list/.initial={Header 1, Contents 1,
                 Header 2, Contents 2,
                 Header 3, Contents 3,
                 Header 4, Contents 4,
                 Header 5, Contents 5,
                 Header 6, Contents 6},
  % mantaining the lists/settings
  reset list/.style={list=},
  add to list/.style={list/.append={,#1}},
  list use/.is choice,
  list use/all comma/.style={use list/.style={% H1, C1, H2, C2, …
    list parser/.expand twice/.expand once={\pgfkeysvalueof{/tikz/list},}}},
  list use/tuples/.style={use list/.style={% {H1, C1}, {H2, C2}, …
    placer/.list/.expand twice/.expand once=\pgfkeysvalueof{/tikz/list}}},
  list use=all comma,% default: all comma
  % actual placing
  list parser/.style args={#1,#2,#3}{                   % parsing H1, C1, H2, C2, …
    placer={{#1},{#2}},
    /utils/if not empty={#3}{list parser={#3}}},
  tuples parser/.style args={#1,#2}{placer={{#1},{#2}}},% parsing {H1, C1}, {H2, C2}, …
  placer/.code args={#1,#2}{%
    \node [list style, on chain] {\textbf{#1}\\#2} edge (center);}}

\newcommand*\myTikz[1][]{%
\begin{tikzpicture}[#1,
   start chain=headers placed {at=(\tikzchaincount*20:\tikzchaincount*3cm)}]
   \node (center) [topic style] at (135:10cm) {\pgfkeysvalueof{/tikz/topic}};
   \tikzset{use list}
\end{tikzpicture}}

\begin{document}
\myTikz
\myTikz[add to list={Header X, Content X, Header Y, Content Y}]
\myTikz[topic=\TeX, list={TikZ, extends PGF, \LaTeX, extends \TeX}]

\tikzset{
  list use=tuples,
  list={{Header 1, Contents 1},
        {Header 2, Contents 2},
        {Header 3, Contents 3},
        {Header 4, Contents 4},
        {Header 5, Contents 5},
        {Header 6, Contents 6}}}
\myTikz
\myTikz[add to list={{Header X, Content X}, {Header Y, Content Y}}]
\myTikz[topic=\TeX, list={{TikZ, extends PGF}, {\LaTeX, extends \TeX}}]
\end{document}

相关内容