![令人困惑的代码](https://linux22.com/image/321493/%E4%BB%A4%E4%BA%BA%E5%9B%B0%E6%83%91%E7%9A%84%E4%BB%A3%E7%A0%81.png)
我对一些绝地大师代码感到困惑。这个令人印象深刻的日历代码应该很容易掌握。我可以通过反复试验来操作它,但我想进入下一个层次并理解它。显然,LaTeX3 / expl3 代码很长,可能太多了,无法用一个答案来处理,但对以下问题和对齐中使用的 pgf 代码的解释将是一个可以接受的答案。
以下是哪些:
\pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}
\pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}
为什么使用这个代码来代替节点的最小高度和最小宽度:
\pgfkeys{/tikz/day xshift=\cellwidth+2mm+2mm} % Set width of days
\pgfkeys{/tikz/day yshift=\cellheight+2mm+2mm} % Set height of days
为什么会有:
\pgfkeys{/tikz/inner sep = 0pt}
然而,日代码节点包含inner sep=1mm
且添加\pgfkeys{/tikz/outer sep = 0pt}
没有影响。
日历上方的垂直间距由什么定义?如果我有多行日期标签(日期名称有多种语言)怎么办?如何确保月份名称和日历不重叠?
令人困惑的代码
我添加了注释,所以如果它们不正确,你会知道原因。这两个代码块似乎让魔法发生了:
%% Adapted from https://tex.stackexchange.com/a/10199/4771
\makeatletter%
\tikzoption{day headings}{\tikzstyle{day heading}=[#1]}
\tikzstyle{day heading}=[]
\tikzstyle{day letter headings}=[
execute before day scope={ \ifdate{day of month=1}{%
\pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}%
\pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}%tikz@lib@cal@width effectively a multiple of day xshift
\pgftransformyshift{-\pgf@ya}
\foreach \d/\l in {0/Mantig,1/Dienstig,2/Mittwoch,3/Pfingstig,% Translate weekday names (start of week: Monday)
4/Freitig,5/Samstig,6/Sunntig} {
\pgf@xa=\d\pgf@xa%
\pgftransformxshift{\pgf@xa-\cellwidth/2}% Spread weekdays horizontally across calendar
\pgftransformyshift{\pgf@ya}% Drop other weeks vertically so that first week is on first line.
\node[above=-0.5ex,day heading]{\l};%
}
}{}%
}%
]
\makeatother%
或者
\makeatletter
\tikzstyle{month label above centered}=[% Formatting of Month Name Location on Page
execute before day scope={%
\ifdate{day of month=1}{% Alignment of first day
{
\pgfmathsetlength{\pgf@xa}{\tikz@lib@cal@xshift}% Grab total width
\pgf@xb=\tikz@lib@cal@width\pgf@xa% Set @xb to total width
\advance\pgf@xb by-\pgf@xa% Subtract full width from xb?
\pgf@xb=.5\pgf@xb% Get half of xb?
\pgftransformxshift{\pgf@xb}%
\pgftransformxshift{-\cellwidth/2}%
\pgfmathsetlength{\pgf@y}{\tikz@lib@cal@yshift}%
\pgftransformyshift{0.333\pgf@y}
\tikzmonthcode%
}
}{}},
every month/.append style={anchor=base}
]
\makeatother
/tikz/day 代码(稍微更容易理解)
这项合身业务似乎不那么优雅。
\pgfkeys{/tikz/day code =
{
\node (lower right) at (0,0) [above left,font=\Huge] {\tikzdaytext}; % Date label on each day
\node (upper left) at (-\cellwidth,\cellheight) [below right,align=left,text width=\cellwidth-\pgflinewidth,font=\tiny,black] {\showtext}; % Adds week numbers
\node (lower left) at (-\cellwidth,0) {};
\node[draw, % day node
fit=(lower right) (upper left) (lower left),
inner sep=1mm,outer sep=0pt] {};
}
}
如果我将所有日代码节点替换为这个节点:
\node[draw,minimum width=\cellwidth,minimum height=\cellheight,outer sep=0pt,inner sep=0pt] {}; % Day Box
这些框似乎水平移动了一些空间。这是为什么?我怎样才能使节点之间的距离为 0pt,以便日历看起来像:
完整代码
看https://tex.stackexchange.com/a/170474/13552
其他相关链接
答案1
添加日期标签 ( day letter headings
)
为了实现这一点,我们需要
- 日宽 (
day xshift
) - 日照高度 (
day yshift
)
循环对于这个来说是有意义的
\foreach \d/\l in {0/Monday,1/Tuesday,2/Wednesday,3/Thursday,
4/Friday,5/Saturday,6/Sunday} {---Create node---}
该节点可能看起来像这样:
\node[above=-0.5ex,day heading,text width=\cellwidth,align=center]{\l};
(我将其替换above=-0.5ex
为anchor=south
)
存储\d
0 到 6。我们将其用作每天的多个倍数。例如,0 乘以一天的宽度等于零,换句话说,不要移动那一天。下一周的第二天(本例中为星期二)不应与星期一重叠,因此它移动了 1 个长度(一天的宽度)。第三天(星期三)移动了,依此类推2 * "width of day"
。
防止日期标签水平重叠
我们使用 PGF 相对坐标变换 (p. 1046) 调整每个节点的位置。
\pgf@ya
和是什么\pgf@xa
?
这些是临时的 TeX 维度(第 751 页)。它们可用于存储节点放置计算中使用的数字。我们可以使用这些变量来存储实现上述日对齐计算的方程的全局“日宽度”和“日高度”变量。
您可以使用以下语法\pgf@ya
进行设置:(维度是值+单位,例如)\pgf@xa
\pgfmathsetlength{\pgf@ya}{---DIMENSION---}
3ex
幕后:TikZ 日历库(tikzlibrarycalendar.code.tex
)设置了以下维度:
\def\tikz@lib@cal@yshift{3ex}
\def\tikz@lib@cal@xshift{3.5ex}
xshift
将节点延伸到原点的左侧。
键day xshift
和day yshift
分别重新定义这些值。(\tikzoption{day xshift}{\def\tikz@lib@cal@xshift{#1}}
& \tikzoption{day yshift}{\def\tikz@lib@cal@yshift{#1}}
)
改变日子
为了在循环中移动日期标签节点,我们首先需要获取“高度宽度”和“日期宽度”变量并将它们分配给,\pgf@ya
以便\pgf@xa
我们可以对它们进行一些算术运算。
\pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}
\pgfmathsetlength{\pgf@xa}{\tikz@lib@cal@xshift}
下面只是将\d
上面循环中的值乘以“日期宽度”变量,以实现“应用日期标签”部分中解释的所有内容。
\pgf@xa=\d\pgf@xa
下一步是将循环中一周中每一天的节点向右移动。首先,您可能会想到使用以下代码:
\pgftransformxshift{\pgf@xa}
请记住,每一天的宽度都是从一天的原点向左延伸的。这意味着节点将与每一天的原点对齐(右侧不对齐),而不是在一天的中间。
%\pgftransformxshift{originshift - width of the day/2}
\pgftransformxshift{\pgf@xa-\tikz@lib@cal@xshift/2}
除非出于某些原因,TikZ 无法使用 进行算术运算\tikz@lib@cal@xshift
,所以作者决定这样做:
- 初始化长度(
\newlength{\cellwidth}
并设置\setlength{\cellwidth}{\dimexpr\textwidth/7}
) - 分配
\tikz@lib@cal@xshift
给该长度\pgfkeys{/tikz/day xshift=\cellwidth} % Set width of days
- 使用该长度进行计算
就像这样:
\pgftransformxshift{\pgf@xa-\cellwidth/2}
的值\cellwidth
也用于设置text width
每个节点的。
防止日期垂直重叠
相应的垂直移位设置如下:
\pgfkeys{/tikz/day yshift=\cellheight} % Set height of days
\newlength{\cellheight}
\setlength{\cellheight}{26mm}
每个节点将与调用它的日期的原点垂直对齐(每月应调用一次 - 每月的第一天)
一个解决方案就是将标签移动到一天的原点(第 1 天)上方一个“一天的高度”。
\pgftransformyshift{\pgf@ya}
您可能和我一样想知道为什么不能直接使用calc
库并执行anchor=south
如下操作:\node[anchor=south] at (\pgf@xa-\cellwidth/2,0) + (0,1cm) {\l};
。事实是,我还没有尝试过。我只是想在探索这种可能性之前先了解给出的代码。
完成事情
日期标签每个月只能触发一次,因此可以使用 if/then 语句将其与第 1 天挂钩。
\ifdate{day of month=1}{---AFOREMENTIONED STUFF---}
我们希望它在整个日历范围内执行(我认为),因此您需要将所有这些都包装起来:
execute before day scope={---AFOREMENTIONED STUFF---}
然后我们必须使其成为一种可以在命令中调用的样式\calendar
,因此我们将所有内容包装在一种tikz
样式中:
\tikzstyle{day letter headings}=[---AFOREMENTIONED STUFF---]
最后,所有这些都需要用以下内容包装,因为 TikZ 使用符号@
作为其宏。
\makeatletter
\makeatother
排版日历(\calendar[])
要使用日历命令,请使用day letter headings
:
键day code
可以自定义日期的绘制方式,需要使用它来确保对齐。我还在学习这个。
幕后:TikZ 日历库(tikzlibrarycalendar.code.tex
)设置如下:
\tikzoption{day code}{\def\tikzdaycode{#1}}
\calendar[
dates=2016-01-01 to 2016-01-last,
week list,
day headings={font=\footnotesize},
day letter headings,
day code={
\node [anchor=base east,draw,minimum width=\cellwidth,minimum height=\cellheight] (daybox) {}; % Draw the Day Boxes Using anchor=base east (causes the xshift to move left)
\node[name=\pgfcalendarsuggestedname,every day,anchor=north east,font=\huge] at (daybox.north east) {\tikzdaytext}; % Date Number
\node (upper left) at (-\cellwidth,\cellheight) [anchor=north west,align=left,text width=\cellwidth-\pgflinewidth,font=\tiny,black] at (daybox.north west){\showtext}; % Week Day
},
]
日期标题的参数将被传递给样式day heading
,供日期标签节点使用。
其他的东西
every day
日期数字节点中的键是什么?
幕后:TikZ 日历库(tikzlibrarycalendar.code.tex
)设置如下:
\tikzoption{days}{\tikzstyle{every day}+=[#1]}
\tikzstyle{every day}=[anchor=base east]
关键是什么name=\pgfcalendarsuggestedname
?
添加月份标签 ( month label above centered
)
---回答未完成---更多内容即将发布……