tikz 日历单元格的动态“扩展”?

tikz 日历单元格的动态“扩展”?

请问,这可能吗?从这个 latex 源开始,我想让日历的单元格垂直“展开”——请参见下图。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calendar}

\begin{document}

\def\testmsgShort{Short message}
\def\testmsgLong{Long message for testing purposes}

\begin{tikzpicture}[
    every node/.style={
            text width=3cm
  }]
\calendar [
    day list downward,
    name=cal,
    dates=2011-01-01 to 2011-01-11
  ]
  if (weekend) [black!25];
  \node [anchor=base west] at (cal-2011-01-03.base east)
          {\textcolor{orange}{\textbf{\testmsgShort}}};
  \node [anchor=base west] at (cal-2011-01-09.base east)
          {\textcolor{orange}{\textbf{\testmsgLong}}};
\end{tikzpicture}

\end{document}

带(长)文本标签的日历

如您所见,长文本节点与日期无关(至少在视觉上)。更自然的方式是将日历视为具有“日期”和“标签”列的表格形式。好吧,我明白,在这样的设置下几乎不可能,因为日历已经绘制出来,“打印出来”,因此新节点无法扩展其“单元格”。

所以,我的问题是——使用 tikz/calendar 可以实现这种“单元格扩展”吗?如果可以——怎么做?我应该寻找其他方法吗?请问哪一种?


更新

谢谢你,杰克!

实际上我希望能够“收集”事件,如下所示:

\tikzstyle{red events}=[
    execute after day scope=
    {
        \redevent{2011-01-04}{This is a long event text.}
        \redevent{2011-01-07}{Short event!}
    }
]

\tikzstyle{blue events}=[
    execute after day scope=
    {
        \blueevent{2011-01-04}{This is another long event text.}
        \blueevent{2011-01-08}{Short another}
    }
]

% ...
\calendar [
    % ...
    red events,
    blue events
    % ...

我不确定这是否是“收集事件”的最佳方式。我说“收集事件”的意思是,有些事件可能永远不变(比如生日),有些事件可能是可移动的;我相信将它们分开并可以编辑-注释-取消注释等会很方便。

但这不适用于您的代码(我有重叠事件),我无法想象(到目前为止我的 tikz 想象力很差,抱歉)如何实现它。

一种方法可能是定义“初始偏移”并将其累积起来——但定义全年偏移的变量不是太昂贵了吗?

还有其他方法吗?

附言:非常感谢你的努力,杰克;无论如何,你的答案将是最好的,但无论如何,我想寻求更好的解决方案(如果可能的话)。)

答案1

好的,这是另一种尝试:将事件收集到改变新event样式的宏中:

\documentclass{minimal}

\usepackage{tikz}
\usetikzlibrary{calendar}

\begin{document}

\newcommand\event[2]{
    \ifdate{equals=#1} {
% In the following, the event nodes are defined
% The \rule in the node text is necessary to match the "text depth=0.5ex" of the date nodes
    \pgftransformxshift{\columnspace}
        \node [anchor= north west,text height=1.5ex,
            name=txt\pgfcalendarsuggestedname,
            text width=3.5cm,event]
        {#2\rule[-0.5ex]{0ex}{0ex}}; 
% Calculate the vertical offset of the southern anchors of the date and event nodes
            \pgfextracty{\extray}{\pgfpointdiff
        {\pgfpointanchor{txt\pgfcalendarsuggestedname}{south} }
        {\pgfpointanchor{\pgfcalendarsuggestedname}{south} }
        }
 Shift by offset
    \pgftransformshift{\pgfpointanchor{txt\pgfcalendarsuggestedname}{south west} }
    \pgftransformxshift{-\columnspace}
    }{}
}

\newcommand\redevents{
    \tikzstyle{event}=[red]
    \event{2011-01-04}{This is a very long event text running over three lines.}
    \event{2011-01-07}{Short event!}
    \event{2011-01-08}{Third of the longish events\ldots}
}
\newcommand\blueevents{
    \tikzstyle{event}=[blue]
        \event{2011-01-04}{This is another long event text.}
        \event{2011-01-08}{Short another}
        \event{2011-01-10}{Single blue event}
}

\begin{tikzpicture}

\def\dayyshift{2ex} % Set space between days
\def\columnspace{4pt} % Set extra space between day and event column

\newdimen{\extray} % Define new dimen for calculating vertical offset

\calendar [
    name=cal,
    dates=2011-01-01 to 2011-01-14,
    every day/.style={
    anchor=north east,
    text depth=0.5ex,
    text height=1.5ex,
    text width=.3cm,
    align=right},
    execute after day scope=
    {
    \extray=0pt
    \pgftransformshift{\pgfpointanchor{\pgfcalendarsuggestedname}{north east}}
%
    \redevents
    \blueevents
%
% Draw separator only if day of month is not 1
    \ifdate {day of month=1} {}{\draw [gray] (\pgfcalendarsuggestedname.north west) ++(90:3pt) -- +(0:4cm);}
% Shift coordinate system to next date
    \pgftransformshift{\pgfpointanchor{\pgfcalendarsuggestedname}{base east}}
    \pgftransformyshift{-\extray}
    \pgftransformyshift{-\dayyshift}
    }
]
if (weekend) [gray!75];
\end{tikzpicture}
\end{document}

收集不同事件的日历

答案2

这是一种不同的方法,只需放置两个节点,一个用于可能很长的文本,一个用于实际的日期,它总是相对于文本节点的左侧放置。

您可以使用feed orangefeed blue键添加文本,并以 格式提供事件列表<date> / <text>

代码

\documentclass[tikz,convert]{standalone}
\usetikzlibrary{calendar}
\makeatletter
\tikzset{
  side orange/.initial=, side blue/.initial=,
  day list downward with side text/.style={
    execute before day scope=%
      \ifdate{equals=\pgfcalendarbeginiso}{\pgfcoordinate{cal@previous}{\pgfpointorigin}}{
        \pgftransformshift{\pgfpointanchor{cal@previous}{south west}}
        \ifdate{day of month=1}{
          \pgftransformyshift{-(\tikz@lib@cal@month@yshift)}
          \pgfcoordinate{cal@previous}{\pgfpointorigin}}{}},
    every day/.style = {node contents=\tikzdaytext, name=\pgfcalendarsuggestedname},
    day code={%
      \node[anchor=north west, outer sep=+0pt, alias=cal@previous,
        name=\pgfcalendarsuggestedname-text, append after command={
          node[anchor=base east, at=(\tikzlastnode.base west), every day]},
        every day text];},
    every day text/.style={
      align=left, text width=3cm, outer sep=+0pt, minimum height=\tikz@lib@cal@yshift,
      font=\vphantom{A},
      node contents=%
        \pgfkeysgetvalue{/tikz/side orange}\tikz@tempa
        \pgfutil@ifxempty\tikz@tempa{}{\color{orange}\tikz@tempa}%
        \pgfkeysgetvalue{/tikz/side blue}\tikz@tempb
        \pgfutil@ifxempty\tikz@tempb{}{%
          \pgfutil@ifxempty\tikz@tempa{}{\par}\color{blue}\tikz@tempb}},
    feed orange/.style args={##1/##2}{if={(equals=##1)[side orange/.append={##2}]}},
    feed blue/.style args={##1/##2}{if={(equals=##1)[side blue/.append={##2}]}}}}
\makeatother
\begin{document}
\tikz\calendar[day list downward with side text, dates=2011-01-01 to 2011-01-11]
  [feed orange/.list = {2011-01-04 / This is a long event text.,
                        2011-01-07 / Short event!}]
  [feed blue/.list   = {2011-01-04 / This is another long event text.,
                        2011-01-08 / Short another?}];
\end{document}

输出

在此处输入图片描述

相关内容