关于多行文字分散对齐的CJKfilltwosides环境的提问

发布于 2022-01-19 09:09:27

各位大佬,使用CJKfilltwosides环境排版多行文字分散对齐时,发现一个问题,该环境外面的文字与多行环境没有居中对齐,应该如何修正?

\documentclass{ctexart}
\usepackage{xeCJKfntef}
\begin{document}
{\Large
2021年\quad\begin{CJKfilltwosides*}{0pt}
哈尔滨师大附中\\
东北师大附中\\
辽宁省实验中学
\end{CJKfilltwosides*}
\quad 高三第一次联考
}

{\Large
2022年\,\begin{CJKfilltwosides*}{0pt}
金华市\\
衢州市
\end{CJKfilltwosides*}
\,初三第一次联考
}
\end{document}

微信图片_20220119090436.jpg

查看更多

关注者
0
被浏览
1.5k
5 个回答
如果您有什么不同意见,您是对的,我是错的。
这家伙很懒,什么也没写!

加个 \parbox 之类的盒子

\parbox[c]{3cm}{东北师大附中}
{%
\begin{CJKfilltwosides*}{0pt}
哈尔滨师大附中\\
东北师大附中\\
辽宁省实验中学
\end{CJKfilltwosides*}
\quad 高三第一次联考
}
乙醇
乙醇 2022-01-19
这家伙很懒,什么也没写!

image.png

texlive2021, win10 21H2, xelatex 编译后并没有发现什么问题……好像?

Saino
Saino 2022-01-19
这家伙很懒,什么也没写!

这个东西本来很简单,

\Large
2021年\begin{tabular}[b]{c}
  哈尔滨师大附中\\
  \begin{tabular}[t]{@{}c@{}}
  辽宁省实验中学\\
  东北师大附中
  \end{tabular}
\end{tabular}高三第一次联考

这样就完事,间距还想宽一点就把里面的@{}c@{}换成c
写成一个环境也行,用\alignhere标记对齐位置。

\makeatletter
\def\parse@align#1#2#3\alignhere{%
  \def\@helper##1{\begin{tabular}[b]{#1}
    #3
    \begin{tabular}[t]{##1}}%
  \expandafter\@helper\expandafter{#2}}
\newenvironment{centertable}[2][]{%
  \ifx\\#1\\%
    \def\inner@preamble{#2}%
  \else
    \def\inner@preamble{#1}%
  \fi
  \parse@align{#2}\inner@preamble
}
{\end{tabular}\end{tabular}}
\makeatother

\fbox{\Large
2021年\begin{centertable}[@{}c@{}]{c}% [...]是内部表格的导言,默认跟外层相同
  哈尔滨师大附中\\
  \alignhere 辽宁省实验中学\\
  东北师大附中
\end{centertable}高三第一次联考
}

如果非要像正常一样书写,可以用tikz标记位置,代价是编译速度会慢很多。

\documentclass{ctexart}
\usepackage{tabularray}
\usepackage{tikz}
\usetikzlibrary{tikzmark} % \subnode

\SetTblrInner{rowsep=0pt} % 设置多行文字的行间距

\makeatletter
\ExplSyntaxOn
\int_new:N \g_centertblr_num_int % 编号避免标记名字重复
\tl_new:N \l_centertblr_current_label_tl
\bool_new:N \g_centertblr_odd_row_count_bool
\NewDocumentEnvironment { centertblr } { O{c} m +b }
  {
    \tl_set:Nx \l_centertblr_current_label_tl { centertblr-mark-\int_use:N \g_centertblr_num_int }
    
    \begin { tikzpicture }
      [
        baseline = ( \l_centertblr_current_label_tl.base ), % 1
        remember~picture
      ]
      
      \node
        [
          anchor = base,
          baseline = ( \l_centertblr_current_label_tl.base ), % 2 对齐设置两次
          inner~sep = 0,
        ]
        {
          \begin { tblr } [#1] {#2}
            \SetRows% 最中间的行处标记
              {
                preto = {
                  \bool_if:NTF \g_centertblr_odd_row_count_bool 
                    {
                      \int_compare:nNnT { \c@rownum * 2 - 1} = { \c@rowcount }
                        { \subnode { \l_centertblr_current_label_tl } {} }
                    }
                    {
                      \int_compare:nNnT { \c@rownum * 2 } = { \c@rowcount }
                        { \subnode { \l_centertblr_current_label_tl-up } {} }
                      \int_compare:nNnT { \c@rownum * 2 - 2} = { \c@rowcount }
                        { \subnode { \l_centertblr_current_label_tl-down } {} }
                    }
                  }
                }
              \bool_gset:Nn \g_centertblr_odd_row_count_bool % node 里面不能写\path,保存以在外面用
                { \int_if_odd_p:n { \int_use:N \c@rowcount } }
              #3
            \end { tblr }
          };
        \bool_if:NF \g_centertblr_odd_row_count_bool
          {
            \path (\l_centertblr_current_label_tl-up) -- (\l_centertblr_current_label_tl-down)
             coordinate[midway] (\l_centertblr_current_label_tl);% 标记中间两行anchor的中点
          }
      \end { tikzpicture }
    }
  { \int_gincr:N \g_centertblr_num_int }
\ExplSyntaxOff
\makeatother

\begin{document}

\fbox{\Large
2021年\begin{centertblr}{Q[c,leftsep=0pt,rightsep=0pt]} % leftsep, rightsep 用来设置多行环境的左右间距
  哈尔滨师大附中\\
  辽宁省实验中学\\
  东北师大附中
\end{centertblr}高三第一次联考
}

\fbox{\Large
  2022年\begin{centertblr}{Q[c,leftsep=0pt,rightsep=0pt]}
    金华市\\
    衢州市
  \end{centertblr}初三第一次联考
}

\fbox{\Large
  2021年\begin{centertblr}{Q[c,leftsep=0pt,rightsep=0pt]}
    哈尔滨师大\rule[-2cm]{1pt}{2cm}附中\\
    东北师大附中\\
    辽宁省实验中学
  \end{centertblr}高三第一次联考
}

\fbox{\Large
  2021年\begin{centertblr}{Q[c,leftsep=0pt,rightsep=0pt]}
    哈尔滨师大\rule[-2cm]{1pt}{2cm}附中\\
    东北师大附中\\
  \end{centertblr}高三第一次联考
}

\end{document}

image.png

寄存器
寄存器 2022-01-19
这家伙很懒,什么也没写!

我也来凑个热闹,参照用LaTeX3排版分散和居中对齐文字用LaTeX3实现这一需求:

\documentclass{ctexart}

\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn
% 获取文本长度函数,#1用于保存长度,#2是被检测的文字
\cs_new:Npn \l_get_text_width:Nn #1#2
  {
    % 将文字内容存入变量
    \hbox_set:Nn \l_tmpa_box {\l_font_tl #2}
    % 用\box_wd:N函数获取盒子宽度,并存入长度变量
    \dim_set:Nn #1 { \box_wd:N \l_tmpa_box }
  }
% 文本长度函数变体
\cs_generate_variant:Nn \l_get_text_width:Nn { NV }

% 获取clist中各个成员长度是大值,
% #1用于保存长度变量,#2是被检测clist变量
\cs_new:Npn \l_get_max_text_width:NN #1#2
  {
    \group_begin:
      % 将长度设置为小值
      \dim_set:Nn #1 {-999pt}
      \clist_set_eq:NN \l_tmpa_clist #2
      % 循环检测每个tl的长度,并更新是大值
      \bool_until_do:nn { \clist_if_empty_p:N \l_tmpa_clist }
        {
          \clist_pop:NN \l_tmpa_clist \l_tmpa_tl
          \l_get_text_width:NV \l_tmpa_dim \l_tmpa_tl
          \dim_gset:Nn #1 { \dim_max:nn {#1} { \l_tmpa_dim } }
        }
    \group_end:
  }

% 分散对齐盒子,
% #1是盒子长度变量,#2是需要排版的文字
\cs_new_protected:Npn \l_spread_box:nn #1#2
  {
    \mode_leave_vertical:
    \hbox_to_wd:nn {#1}
      { \tl_map_inline:xn {#2} { ##1 \hfil } \unskip }
  }
% 分散对齐盒子函数变体
\cs_generate_variant:Nn \l_spread_box:nn  { Vn }
\cs_generate_variant:Nn \l_spread_box:nn  { nV }

% 居中对齐盒子,
% #1是盒子长度变量,#2是需要排版的文字
\cs_new_protected:Npn \l_center_box:nn #1#2
  {
    \mode_leave_vertical:
    \dim_set:Nn \l_tmpa_dim {#1}
    \dim_add:Nn \l_tmpa_dim {0.6em}
    \makebox[0cm][l]{\rule[-0.5ex]{\l_tmpa_dim}{0.4 pt}}
      {\hbox_to_wd:nn {\l_tmpa_dim} { \hfil #2 \hfil }}
  }
% 居中对齐盒子函数变体
\cs_generate_variant:Nn \l_center_box:nn { Vn }

% 为文字添加下划线
\cs_new:Npn \l_text_uline:n #1
  {
    \l_get_text_width:Nn \l_tmpa_dim {#1}
    \dim_add:Nn \l_tmpa_dim {0.6em}
    % 将标尺盒子放到宽度为0的左右盒子中实现下划线
    \makebox[0pc][l]{\rule[-0.5ex]{\l_tmpa_dim}{0.4 pt}}
      % 用高度为0的标尺盒子在文字两端添加空白
      \rule{.3em}{0cm}#1\rule{.3em}{0cm}
  }

\clist_new:N \l_schools_clist

\dim_new:N \l_h_sep_dim
\dim_new:N \l_v_sep_dim

\coffin_new:N \l_output_coffin
\coffin_new:N \l_school_coffin

\tl_new:N \l_font_tl

\keys_define:nn { examinfo }
  {
    hsep .dim_set:N = \l_h_sep_dim,
    hsep .initial:n = 5pt,

    vsep .dim_set:N = \l_v_sep_dim,
    vsep .initial:n = 5pt,

    font .tl_set:N = \l_font_tl,
    font .initial:n = \normalsize,

    unknown .code:n = { \__examinfo_error:n { unknown-option } }
  }
\msg_new:nnn { examinfo } { unknown-option }
  { package~ option~ "\l_keys_key_tl"~ is~ unknown. }

\NewDocumentCommand \examinfoset { m }
  { \keys_set:nn { examinfo } {#1} }

% 居中对齐盒子函数
\cs_new_protected:Npn \__examinfo_cover:nnn #1#2#3
{
  \clist_set:Nn \l_schools_clist{#2}

  % 设置年度容器
  \hcoffin_set:Nn \l_tmpa_coffin {\l_font_tl #1}
  \hcoffin_set:Nn \l_tmpb_coffin {\l_font_tl #3}

  % 计算校名最大长度
  \l_get_max_text_width:NN \l_tmpa_dim \l_schools_clist

  % 排版第一个校名
  \clist_if_empty:NF \l_schools_clist
    {
      % 从左端弹出一个校名
      \clist_pop:NN \l_schools_clist \l_tmpa_tl
      % 设置输出结果容器内容
      \hcoffin_set:Nn \l_output_coffin
        {
          % 排版分散对齐盒子
          \tl_use:N \l_font_tl
          \l_spread_box:Vn \l_tmpa_dim { \l_tmpa_tl }
        }
    }
  % 排版其它校名
  \bool_until_do:nn { \clist_if_empty_p:N \l_schools_clist }
    {
      % 从左端弹出一个校名
      \clist_pop:NN \l_schools_clist \l_tmpa_tl
      % 设置校名容器内容
      \hcoffin_set:Nn \l_school_coffin
        {
          % 排版分散对齐盒子
          \tl_use:N \l_font_tl
          \l_spread_box:Vn \l_tmpa_dim { \l_tmpa_tl }
        }
      % 将校名容器拼接到输出结果窗口(按\l_v_sep_dim为间隔拼接)
      \coffin_join:NnnNnnnn \l_output_coffin { hc } { b }
        \l_school_coffin { hc } { t }  { 0pt } { -\l_v_sep_dim }
    }

  % 将年度容器拼接到输出结果容器(按\l_h_sep_dim为间隔拼接)
  \coffin_join:NnnNnnnn \l_output_coffin { vc } { l }
      \l_tmpa_coffin { vc } { r }  { -\l_h_sep_dim } { 0pt }
  % 将试卷名称容器拼接到输出结果容器(按\l_h_sep_dim为间隔拼接)
  \coffin_join:NnnNnnnn \l_output_coffin { vc } { r }
      \l_tmpb_coffin { vc } { l }  { \l_h_sep_dim } { 0pt }

  % 输出结果容器
  \coffin_typeset:Nnnnn \l_output_coffin { vc } { l } { 0pt } { 0pt }
}

% 定义用户接口
\NewDocumentCommand{\examinfo}{O{} m m m}
  {
    \group_begin:
      \keys_set:nn { examinfo } {#1}
      \__examinfo_cover:nnn {#2}{#3}{#4}
    \group_end:
  }
\ExplSyntaxOff


\begin{document}

\section{默认参数}
% 注意校名间用英文逗号分隔
\examinfo{2021年}{哈尔滨师大附中, 东北师大附中, 辽宁省实验中学}{高三第一次联考}

\bigskip

\section{指定间距}
% 可以用hsep指定年度、校名、考试名称间的水平距离
% 可以用vsep指定校名间的垂直距离\bfseries
\examinfo[hsep=1cm, vsep=15pt]{2022年}{金华市, 衢州市}{初三第一次联考}

\bigskip

\section{指定字体}
% 也可以用font设置字体参数
\examinfo[font=\Large\heiti\bfseries]{2022年}{金华市, 衢州市}{初三第一次联考}

\end{document}

image.png

夏大鱼羊-xkwxdyy
这家伙很懒,什么也没写!

想要那样的效果最直接的就是把外面的文字放在表格里:

\documentclass{ctexart}
\usepackage{tabularray}

\begin{document}
\begin{tblr}{
  cell{1}{1} = {r = 3}{c},
  column{2} = {c}
}
  2021年  & 哈尔滨师大附中 & \\
          &  东北师大附中  & 高三第一次联考 \\
          & 辽宁省实验中学
\end{tblr}
\end{document}

image.png

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览