请问,这可能吗?从这个 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 orange
和feed 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}