Tikz 日历格式、锚定文本(小写字母、文本对齐和颜色交替)

Tikz 日历格式、锚定文本(小写字母、文本对齐和颜色交替)

我已经解决了日标题的小写字母和交替颜色要求的问题。我的代码现在反映了这些变化,我在本问题的末尾描述了它们,供那些可能感兴趣的人参考。

然而,还有两件事我正在努力完成。

(1) 我希望星期名称在列中左对齐,而不是居中。我觉得我应该可以通过调整锚点来实现这一点,但我不知道是标签、日历还是其他什么东西。

(2)此外,在月份名称的两侧,我希望写出年份,分别与最右边的文本和最左边的文本对齐。(也就是说,最初的 2018 与工作日左侧对齐,第二年数字中的 8 与最后一天的数字对齐,例如,在一月份,29 中的 8 位于 9 上方。(我在示例中使用了 hspace 和 xshift,但由于每个月份名称的长度不同,因此固定空格或移位将不起作用。)

\documentclass{article}
\usepackage[margin = 2.5cm, landscape]{geometry}
\pagestyle{empty}

\usepackage{tikz}
    \usetikzlibrary{calendar, positioning}

\makeatletter
\tikzstyle{week list}=[
    execute before day scope={%
        \ifdate{day of month=1}{\ifdate{equals=\pgfcalendarbeginiso}{}
            {% On first of month, except when first date in calendar.
            \pgfmathsetlength{\pgf@x}{\tikz@lib@cal@month@xshift}
            \pgftransformxshift{\pgf@x}
            }
        }{}
},
    execute at begin day scope={%
        \ifodd\pgfcalendarcurrentday\relax \color{red} \fi %%% <-- added line to alternate number colors {thanks to Hood Chatham}
        \pgfmathsetlength\pgf@y{\tikz@lib@cal@yshift}%
        \pgf@y=\pgfcalendarcurrentweekday\pgf@y%
        \pgftransformyshift{-\pgf@y}%
        },
   execute after day scope={%
        \ifdate{Sunday}{%
        \pgfmathsetlength{\pgf@x}{\tikz@lib@cal@xshift}%
        \pgftransformxshift{\pgf@x}
        }{}%
    },
    % % According to Berteun the following should be defined:
    % << tikz@lib@cal@width=7 >>. (I don't know why.)
    ]

    \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}%
        \pgftransformxshift{\pgf@xa}
        \foreach \d/\l in {
    0/\sc{Monday},1/\sc\textcolor{red}{Tuesday},     % <----------------------- |
    2/\sc{Wednesday},3/\sc\textcolor{red}{Thursday},    % <----- modified lines |
    4/\sc{Friday},5/\sc\textcolor{red}{Saturday},6/\sc{Sunday}}{     % <------- |
% had been: {0/Monday,1/Tuesday,2/Wednesday,
%            3/Thursday,4/Friday,5/Saturday,6/Sunday} {
        \pgf@ya=\d\pgf@ya%
        \pgftransformxshift{-\pgf@xa}%
        \pgftransformyshift{-\pgf@ya}%
        \node[every day, day heading, anchor = base]{\l};%
            }
        }{}%
    }%
]
\makeatother

\newcommand{\calyear}{2018}
\newcommand{\mon}[1]{\calendar[dates = \calyear-#1-01 to \calyear-#1-last];}

\begin{document}
    \begin{tikzpicture}[every calendar/.style = {
        month label above centered,
        month text = {\Large \%y- \hspace{.5cm} \textsc{\%mt} \hspace{.5cm} \%y- },
        week list,
        day letter headings,
        day heading/.style={xshift=-2cm} % <--- modified line
        % had been: day heading/.style={red, xshift=-2cm}
    }]
    \matrix (Calendar) [column sep = 4em, row sep = 3em] {
        \mon{01} & \mon{02} & \mon{03} \\
        \mon{04} & \mon{05} & \mon{06} \\
        \mon{07} & \mon{08} & \mon{09} \\
        \mon{10} & \mon{11} & \mon{12} \\ };
    \end{tikzpicture}
\end{document}

为了使星期几的名称以小写字母打印,并在黑色和红色之间交替,我在最初给出星期几标题文本的行中插入了小写字母和红色文本的命令;我还[red]从样式定义中删除了,day heading/.style因为将默认的黑色更改为红色需要三次较少的颜色更改(三次更改为红色,四次更改为黑色)。相关行现在显示为:

\foreach \d/\l in {
    0/\sc{Monday},1/\sc\textcolor{red}{Tuesday},2/\sc{Wednesday},
    3/\sc\textcolor{red}{Thursday},4/\sc{Friday},
    5/\sc\textcolor{red}{Saturday},6/\sc{Sunday}}

day heading/.style={xshift=-2cm} 

我确信有更好的方法来实现这一点,而不是对每日标题的每个实例进行“硬连线”——但这个临时解决方案是可行的。

答案1

我做了一些更改:我假设您希望日历在页面上垂直和水平居中。为此,我将边距设置为零,并使用命令\centering水平居中。要使日历垂直居中,我说\let\@texttop\vfill\let\@textbottom\vfill

您无需在循环中手动输入每个星期几来创建星期几,而是可以使用星期几。要将奇数日设为红色,请\pgfcalendarweekdayname{\d}在此之前添加。\d\ifodd\d \color{red}\fi

要使日期左对齐,您需要指定text width,这将使节点成为固定宽度的矩形,并将文本左对齐其中。最长的星期几名称是星期三,所以我们说text width = width("Wednesday")

为了使标题的长度正确,我们需要已经知道月份的宽度。在绘制日历的其余部分之前pgfcalendar放置,这为此很不方便。相反,我在绘制月份的其余部分之后将月份标题放置在宏中。然后我们可以找到日期节点的西锚点和月份最后一天的节点的东锚点之间的距离,并将月份标题的设置为此(减去一个小的偏移量以考虑星期几和月份节点的)。month label\montextwidthinner sep

\documentclass{article}
\usepackage[margin = 0cm, landscape]{geometry}
\makeatletter
\AtBeginDocument{\centering}
\let\@texttop\vfill
\let\@textbottom\vfill
\pagestyle{empty}

\usepackage{tikz}
\usetikzlibrary{calendar, positioning}

\tikzstyle{week list}=[
    execute before day scope={%
        \ifdate{day of month=1}{\ifdate{equals=\pgfcalendarbeginiso}{}
            {% On first of month, except when first date in calendar.
            \pgfmathsetlength{\pgf@x}{\tikz@lib@cal@month@xshift}
            \pgftransformxshift{\pgf@x}
            }
        }{}
},
    execute at begin day scope={%
        \ifodd\pgfcalendarcurrentday\relax \color{red} \fi %%% <-- added line to alternate number colors {thanks to Hood Chatham}
        \pgfmathsetlength\pgf@y{\tikz@lib@cal@yshift}%
        \pgf@y=\pgfcalendarcurrentweekday\pgf@y%
        \pgftransformyshift{-\pgf@y}%
        },
   execute after day scope={%
        \ifdate{Sunday}{%
        \pgfmathsetlength{\pgf@x}{\tikz@lib@cal@xshift}%
        \pgftransformxshift{\pgf@x}
        }{}%
    },
    % % According to Berteun the following should be defined:
    % << tikz@lib@cal@width=7 >>. (I don't know why.)
    ]

    \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}%
        \pgftransformxshift{\pgf@xa}
        \foreach \d/\l in {0,...,6}{     % <------- |
            \pgf@ya=\d\pgf@ya%
            \pgftransformxshift{-\pgf@xa}%
            \pgftransformyshift{-\pgf@ya}%
            \node[every day, day heading, anchor = base,text width=width("Wednesday")] (day-\d) {\ifodd\d \color{red}\fi\sc{\pgfcalendarweekdayname{\d}}};%
        }
    }{}}%
]

\newcount\tempcount
\newcommand{\calyear}{2018}
\newcommand{\mon}[1]{
    \calendar (cal) [dates = \calyear-#1-01 to \calyear-#1-last]; 
    % Add the title
    % Get the date of the last day of the month
    \pgfcalendardatetojulian{\calyear-#1-last}{\tempcount}
    \pgfcalendarjuliantodate{\tempcount}{\throwaway}{\throwaway}{\lastday}
    % Find the distance between the west end of the weekday and the east end of the last day of the month
    \pgfpointdiff{\pgfpointanchor{day-0}{west}}{\pgfpointanchor{cal-\calyear-#1-\lastday}{east}}
    % The width of the month should be this distance minus some extra padding
    \edef\monthwidth{\the\dimexpr\pgf@x-7pt}
    % Draw the month title
    \node[above left=0em of day-0,above right, text width=\monthwidth] {\Large \calyear\hfill \textsc{\pgfcalendarmonthname{#1}} \hfill \calyear}; 
}
\makeatother
\begin{document}
    \begin{tikzpicture}[every calendar/.style = {
        week list,
        day letter headings,
        day heading/.style={xshift=-2cm} % <--- modified line
    }]
    \matrix (Calendar) [column sep = 4em, row sep = 3em] {
        \mon{01} & \mon{02} & \mon{03} \\
        \mon{04} & \mon{05} & \mon{06} \\
        \mon{07} & \mon{08} & \mon{09} \\
        \mon{10} & \mon{11} & \mon{12} \\ };
    \end{tikzpicture}
\end{document} 

相关内容