%% 版本:1.0 %% 作者:杨永全 %% 本文件的主要目的,是为了定义列表等内部元素的样式 %% 完成时间:2022-05-09 \RequirePackage{listings,verbatim}%引入代码包 \RequirePackage{caption} \usepackage{tcolorbox} %引入彩色框 \tcbuselibrary{most} %引入所有包 %列表样式,使用了fontawesome图标 \setbeamertemplate{itemize item}{\faBookmark} \setbeamertemplate{itemize subitem}{\faHandORight} \setbeamertemplate{itemize subsubitem}{\faSquare} %超链接的颜色等信息 \hypersetup{ %colorlinks=true, %超链接颜色,全部使用海大红。 linkcolor=oucred, urlcolor=oucred, citecolor=oucred, anchorcolor=oucred, } %代码块的一些设定,原模板代码 \renewcommand{\ttdefault}{pcr} \lstset{ frame=shadowbox, numbers=left, numberstyle=\small, basicstyle=\ttfamily\upshape\small, breaklines=true, backgroundcolor=\color{oucsilver10}, xleftmargin=0.8cm, framexleftmargin=0em, keywordstyle=\bfseries\color{oucblue}, stringstyle=\color{oucblue}, commentstyle=\color{mygreen}, rulesepcolor= \color{oucsilver40}, rulecolor=\color{oucblue}, deletekeywords={compile}, escapechar=\&, escapeinside={<@}{@>} } %% 代码块标题设定 \DeclareCaptionFormat{codecaptionformat}{% \parbox{\textwidth}{\hspace{2em}\textcolor{violet}\faCode~\textcolor{violet}{#1#2}\hspace{.5em}#3}%代码块caption的设置 } \captionsetup[lstlisting]{format=codecaptionformat} %设置信息框titlebox \newtcolorbox{titlebox}[2][] { title=#1, %标题 colback = white, %标题背景是白色 colframe = #2, %边框颜色 coltitle = #2, %标题颜色 boxrule=.5pt,%边框的粗细,细一点感觉更精致 boxed title style={size=normal,colframe=white,boxrule=0pt},%标题栏没有背景色和边框,只有文字 left=5pt, right=5pt, top=5pt, bottom=0pt,%内部文字边距 boxsep=5pt, colbacktitle = white, enhanced,%标题的背景,白色 attach boxed title to top center={yshift=-4mm},%把标题放在中间 opacityupper={100}, %上面边框透明度 } %设置笔记提示框 \newtcolorbox{notebox}[1][] { enhanced, arc=2pt,%圆角 boxrule=.5pt,%边框 left=5pt, right=5pt, top=0pt, bottom=0pt,%文字边距 boxsep=5pt, colframe=oucblue, colback=oucblue10, colbacktitle=oucblue10, coltext=oucblue, title={\textcolor{oucblue}{\faStickyNoteO\hspace{.5em}\bfseries{\textbf{#1}}}}, halign=left, } %设置重要提示框 \newtcolorbox{importantbox}[1][] { enhanced, arc=2pt, boxrule=.5pt, left=5pt, right=5pt, top=0pt, bottom=0pt, boxsep=5pt, colframe=oucred, colback=oucred10, colbacktitle=oucred10, coltext=oucred, title={\textcolor{oucred}{\faExclamationCircle\hspace{.5em}\bfseries{\textbf{#1}}}}, halign=left, } %列表框 \newtcolorbox{vcolorbox}[2][] { boxrule=0.5pt,%边框,很细 arc=0pt,outer arc=0pt,%不要圆角 left=5pt, right=5pt, top=0pt, bottom=0pt, leftrule=5pt, %左侧边框的宽度 colframe=#2,%边框的颜色 colback=white, colbacktitle=white, coltext=black,%内部文字的颜色,如果要和标题保持一致,可改为#2 title={\textcolor{#2}{\bfseries{\textbf{#1}}}},%标题样式 halign=left, } %要点框 \newtcolorbox{pointbox}[3][] { colback = white, %背景是白色 boxrule=0.5pt,%边框的粗细,细一点感觉更精致 colframe = #2, %边框颜色 fonttitle = \bfseries,%标题加粗 colbacktitle = #2, enhanced, left=2pt, right=2pt, top=5pt, bottom=0pt,%内部文字边距 attach boxed title to top center={yshift=-2mm}, width=\textwidth, height=#3, title=#1 } %% ====================================================================== %% 要点框自动排布:pointboxgrid %% ---------------------------------------------------------------------- %% 把任意多个要点自动排成「每行最多 4 个」的网格: %% \begin{pointboxgrid}{高度} %% \pointitem{标题}{颜色}{内容} %% ... %% \end{pointboxgrid} %% %% 排布规则(行数尽可能少,并尽量均匀): %% 1~4 个 → 一行 %% 5 个 → 上行 3 + 下行 2 %% 6 个 → 3 + 3 %% 7 个 → 4 + 3 %% 8 个 → 4 + 4 %% 9 个 → 3 + 3 + 3 %% 10 个 → 4 + 3 + 3 %% 11 个 → 4 + 4 + 3 %% 12 个 → 4 + 4 + 4 %% 一般地:行数 = ceil(N/4),前 N mod 行数 行每行多放 1 个。 %% %% 说明: %% - 高度参数与 pointbox 的 height 含义相同(固定高度,内容别超出)。 %% - 较多行时请自行减小高度,避免总高超出页面(建议行数 ≤ 4)。 %% - 「每行最多几个」由 \ouc_pbg_max 控制;间距由 \ouc_pbg_gap / %% \ouc_pbg_vgap 控制,需要时在导言区改这两个长度。 %% ====================================================================== \ExplSyntaxOn \int_new:N \l_ouc_pbg_cnt \int_new:N \l_ouc_pbg_n \int_new:N \l_ouc_pbg_rows \int_new:N \l_ouc_pbg_base \int_new:N \l_ouc_pbg_rem \int_new:N \l_ouc_pbg_k \int_new:N \l_ouc_pbg_km \int_new:N \l_ouc_pbg_i \int_new:N \l_ouc_pbg_max \dim_new:N \l_ouc_pbg_est \dim_new:N \l_ouc_pbg_colw \dim_new:N \l_ouc_pbg_gap \dim_new:N \l_ouc_pbg_vgap \dim_new:N \l_ouc_pbg_h \int_set:Nn \l_ouc_pbg_max { 4 } \dim_new:N \l_ouc_pbg_avail \dim_set:Nn \l_ouc_pbg_avail { 243pt } \dim_set:Nn \l_ouc_pbg_gap { 8pt } \dim_set:Nn \l_ouc_pbg_vgap { 6pt } %% 收集一个要点:内容按原样存进带索引的宏,不做任何展开 \NewDocumentCommand \pointitem { m m m } { \int_incr:N \l_ouc_pbg_cnt \tl_set:cn { l_ouc_pbg_t_ \int_use:N \l_ouc_pbg_cnt } {#1} \tl_set:cn { l_ouc_pbg_c_ \int_use:N \l_ouc_pbg_cnt } {#2} \tl_set:cn { l_ouc_pbg_b_ \int_use:N \l_ouc_pbg_cnt } {#3} } %% 画一个要点框:按序号直接取用存好的宏 \cs_new_protected:Npn \ouc_pbg_emit:n #1 { \begin{pointbox} [ \tl_use:c { l_ouc_pbg_t_#1 } ] { \tl_use:c { l_ouc_pbg_c_#1 } } { \dim_use:N \l_ouc_pbg_h } \tl_use:c { l_ouc_pbg_b_#1 } \end{pointbox} } %% 列宽 = (正文宽 - (k-1)*间距) / k %% 注:某些 TeX Live 下 expl3 的维度乘法(*)会静默算出 0, %% 因此走 fp_eval + dim_to_fp 的浮点路径,稳妥。 \cs_new_protected:Nn \ouc_pbg_setcolw: { \int_set:Nn \l_ouc_pbg_km { \int_use:N \l_ouc_pbg_k - 1 } \dim_set:Nn \l_ouc_pbg_colw { \fp_eval:n { ( \dim_to_fp:n { \textwidth } - \int_use:N \l_ouc_pbg_km * \dim_to_fp:n { \l_ouc_pbg_gap } ) / \int_use:N \l_ouc_pbg_k } pt } } \cs_new_protected:Nn \ouc_pbg_typeset: { \int_set:Nn \l_ouc_pbg_n { \int_use:N \l_ouc_pbg_cnt } \int_compare:nNnT { \int_use:N \l_ouc_pbg_n } > { 0 } { %% 行数 = ceil(N / max) \int_set:Nn \l_ouc_pbg_rows { \int_div_truncate:nn { \int_use:N \l_ouc_pbg_n + \int_use:N \l_ouc_pbg_max - 1 } { \int_use:N \l_ouc_pbg_max } } %% 均匀分配:前 rem 行每行多 1 个(上行不少于下行) \int_set:Nn \l_ouc_pbg_base { \int_div_truncate:nn { \int_use:N \l_ouc_pbg_n } { \int_use:N \l_ouc_pbg_rows } } \int_set:Nn \l_ouc_pbg_rem { \int_use:N \l_ouc_pbg_n - \int_use:N \l_ouc_pbg_base * \int_use:N \l_ouc_pbg_rows } %% 预估总高度并与正文可用高度比较(公式按实测校准): %% 总高 ≈ 69pt(首行含标题条) + 行数*高度 + (行数-1)*25pt(行间距) \dim_set:Nn \l_ouc_pbg_est { \fp_eval:n { 69 + \int_use:N \l_ouc_pbg_rows * \dim_to_fp:n { \l_ouc_pbg_h } + ( \int_use:N \l_ouc_pbg_rows - 1 ) * 25 } pt } \ifdim \l_ouc_pbg_est > \l_ouc_pbg_avail \PackageWarning{oucslide} { 要点框共 \int_use:N \l_ouc_pbg_n\space 个,排成 \int_use:N \l_ouc_pbg_rows\space 行、每框高 \dim_use:N \l_ouc_pbg_h, 预估总高 \dim_use:N \l_ouc_pbg_est\space 已超过正文可用高度 \dim_use:N \l_ouc_pbg_avail,可能超出页面底部。 请把高度改小(4 行时建议不超过 24pt)或减少要点个数 } \fi \int_zero:N \l_ouc_pbg_i \int_step_inline:nn { \int_use:N \l_ouc_pbg_rows } { \int_set:Nn \l_ouc_pbg_k { \int_use:N \l_ouc_pbg_base } %% 注意:此处的比较必须用 \ifnum。 %% expl3 的 \int_compare:nNnT 在这套 TeX Live 下判定有误, %% 会把所有 ##1 都判成"小于等于",导致行内个数分配失效。 \ifnum ##1 > \int_use:N \l_ouc_pbg_rem \else \int_incr:N \l_ouc_pbg_k \fi \ouc_pbg_setcolw: %% 必须用 [onlytextwidth],否则默认 columns 会带来 %% 左/右边距,4 列时左右各溢出约 10pt。 \begin{columns}[onlytextwidth] \int_step_inline:nn { \int_use:N \l_ouc_pbg_k } { \int_incr:N \l_ouc_pbg_i \begin{column}{\dim_use:N \l_ouc_pbg_colw} \ouc_pbg_emit:n { \int_use:N \l_ouc_pbg_i } \end{column} } \end{columns} \ifnum ##1 < \int_use:N \l_ouc_pbg_rows \vspace{\dim_use:N \l_ouc_pbg_vgap} \fi } } } %% 友好设置:\pointboxsetup{每行最多几个}{横向间距}{纵向间距} %% 例如 \pointboxsetup{5}{6pt}{4pt} \NewDocumentCommand \pointboxsetup { m m m } { \int_set:Nn \l_ouc_pbg_max {#1} \dim_set:Nn \l_ouc_pbg_gap {#2} \dim_set:Nn \l_ouc_pbg_vgap {#3} } \NewDocumentEnvironment { pointboxgrid } { m } { \int_zero:N \l_ouc_pbg_cnt \dim_set:Nn \l_ouc_pbg_h {#1} } { \ouc_pbg_typeset: } \ExplSyntaxOff %% ====================================================================== %文本框textbox \newtcolorbox{textbox}[1]{ colback=#1!5!white, colframe=#1, boxrule=0.5pt, arc=2pt, } %标题框headbox \newtcolorbox{headbox}[1]{ colback=#1, colframe=#1, boxrule=0.5pt, arc=2pt, coltext=white, fontupper= \bfseries, left=0pt, right=0pt, top=0pt, bottom=0pt,%内部文字边距 } %一些元素的中文名称 \renewcommand{\figurename}{图} \renewcommand{\tablename}{表} \renewcommand{\lstlistingname}{代码} \renewcommand{\abstractname}{摘要} %% ====================================================================== %% 扁平简约图示组件 (flat diagrams) %% --------------------------------------------------------------------- %% 设计基调:圆角块 + 实心纯色 + 白字 + 细箭头 %% **无渐变、无阴影、无立体** %% %% 所有组件都支持「颜色列表」:写一个颜色则全部同色; %% 写多个颜色(逗号分隔)则按顺序循环取色。 %% \flatflow{oucblue} % 4 个块全为海大蓝 %% \flatflow{oucblue,oucred,oucpine} % 4 个块循环取这 3 色 %% \flatflow{oucblue,oucred,oucpine,oucdusk,oucamber} % 5 色各不同 %% ====================================================================== \RequirePackage{tikz} \usetikzlibrary{positioning,arrows.meta,calc,shapes.geometric} %% ---------------- 防错:颜色参数必须写在 [] 里 ---------------- %% \flatflow 这类命令的「颜色列表」是可选参数,必须写成方括号 [颜色]。 %% 若误写成花括号 {颜色},颜色会被当成第一个条目(静默出错、极难排查), %% 因此这里检查每个条目是不是模板的颜色名,是则明确报错。 \newcommand{\flcheckitems}[1]{% \foreach \flci in {#1}{% %% 注意:\foreach 每轮迭代会开组,内层的 \def 出组即失效, %% 因此这里必须用 \global\def(否则检测永远不触发)。 \global\def\flhit{0}% \foreach \flck in {oucblue,ouclightblue,oucred,ouccherry,oucbrown,% oucgolden,oucsilver,oucpine,oucdusk,oucamber}{% %% 注意:此处 \ifstrequal 在本机不生效(恒为假),必须用 \ifx \ifx\flci\flck\global\def\flhit{1}\fi }% \ifnum\flhit=1 \PackageError{oucslide}{图示组件的颜色要写在方括号里}{% 命令 \string\flatflow[颜色列表]{条目1, 条目2} 中的颜色是可选参数,% 必须用方括号 [ ],不能用花括号 { }。\MessageBreak 现在「\flci」被当成了条目内容(它看起来是颜色名)。}% \fi }% } %% ---------------- 辅助:长度 / 计数 / 取色 ---------------- \newlength\flgap \newlength\flbw \newcount\flcnt \def\flcntval{0} %% 数条目个数,并存成**纯数字宏**(本机 pgfmath 的算式里不能出现计数器) \newcommand{\flcount}[1]{% \flcnt=0 \foreach \flzz in {#1}{\global\advance\flcnt by 1}% \xdef\flcntval{\the\flcnt}% } \newcount\flcolcnt \def\flcoln{0} \newcommand{\flcolcount}[1]{% \flcolcnt=0 \foreach \flzz in {#1}{\global\advance\flcolcnt by 1}% \xdef\flcoln{\the\flcolcnt}% } \def\flcur{oucblue} \def\flmain{oucblue} %% 第 #2 个块取颜色列表 #1 中的颜色(超出则循环),结果存进 \flcur \newcommand{\flpick}[2]{% \pgfmathtruncatemacro{\flidx}{mod(#2-1,\flcoln)+1}% \foreach \flzz [count=\fljj] in {#1}{% \ifnum\fljj=\flidx \xdef\flcur{\flzz}\fi }% } %% 取列表第一项作为「主色」(箭头、轴线等用) \newcommand{\flsetmain}[1]{\flpick{#1}{1}\xdef\flmain{\flcur}} %% ---------------- 公共样式 ---------------- \tikzset{ flblk/.style={rectangle, rounded corners=2pt, draw=none, text=white, align=center, inner sep=4pt, font=\small}, flblkl/.style={rectangle, rounded corners=2pt, draw=none, align=center, inner sep=4pt, font=\footnotesize}, flarr/.style={line width=1pt, -{Stealth[length=1.7mm,width=1.4mm]}} } %% ================== 1. 横向箭头流程 ================== %% \flatflow[颜色列表]{条目1, 条目2, ...} \NewDocumentCommand \flatflow { O{oucblue} m }{{% \flcheckitems{#2}\flcount{#2}\flcolcount{#1}\flsetmain{#1}% \setlength{\flgap}{16pt}% \pgfmathsetlength{\flbw}{(0.99\textwidth-(\flcntval-1)*\flgap)/\flcntval}% \begin{tikzpicture} \foreach \flx [count=\fli] in {#2} { \flpick{#1}{\fli}% \pgfmathtruncatemacro{\flprev}{\fli-1} \ifnum\fli=1 \node[flblk, fill=\flcur, minimum height=20pt, text width=\dimexpr\flbw-8pt\relax] (fn1) at (0,0) {\flx}; \else \node[flblk, fill=\flcur, minimum height=20pt, text width=\dimexpr\flbw-8pt\relax, right=\flgap of fn\flprev] (fn\fli) {\flx}; \fi }% \foreach \flx [count=\fli] in {#2} { \ifnum\fli>1 \pgfmathtruncatemacro{\flprev}{\fli-1} \draw[flarr, draw=\flmain!70!black] (fn\flprev.east) -- (fn\fli.west); \fi }% \end{tikzpicture}% }} %% ================== 2. 纵向流程 ================== \NewDocumentCommand \flatstack { O{oucblue} m }{{% \flcheckitems{#2}\flcount{#2}\flcolcount{#1}\flsetmain{#1}% \begin{tikzpicture} \foreach \flx [count=\fli] in {#2} { \flpick{#1}{\fli}% \pgfmathtruncatemacro{\flprev}{\fli-1} \ifnum\fli=1 \node[flblk, fill=\flcur, minimum height=18pt, minimum width=0.7\textwidth] (fn1) at (0,0) {\flx}; \else \node[flblk, fill=\flcur, minimum height=18pt, minimum width=0.7\textwidth, below=8pt of fn\flprev] (fn\fli) {\flx}; \fi }% \foreach \flx [count=\fli] in {#2} { \ifnum\fli>1 \pgfmathtruncatemacro{\flprev}{\fli-1} \draw[flarr, draw=\flmain!70!black] (fn\flprev.south) -- (fn\fli.north); \fi }% \end{tikzpicture}% }} %% ================== 3. 循环图 ================== \NewDocumentCommand \flatcycle { O{oucblue} m }{{% \flcheckitems{#2}\flcount{#2}\flcolcount{#1}\flsetmain{#1}% \begin{tikzpicture} \foreach \flx [count=\fli] in {#2} { \flpick{#1}{\fli}% \pgfmathsetmacro{\flang}{90-360/\flcntval*(\fli-1)} \node[circle, fill=\flcur, text=white, align=center, inner sep=1pt, minimum size=32pt, font=\footnotesize] (cn\fli) at (\flang:34pt) {\flx}; }% \foreach \flx [count=\fli] in {#2} { \pgfmathtruncatemacro{\flnext}{mod(\fli,\flcntval)+1} \draw[flarr, draw=\flmain!50!black] (cn\fli) to[bend left=20] (cn\flnext); }% \end{tikzpicture}% }} %% ================== 4. 中心辐射 ================== %% \flathub[颜色列表]{中心文字}{环绕1, 环绕2, ...} \NewDocumentCommand \flathub { O{oucblue} m m }{{% \flcheckitems{#3}\flcount{#3}\flcolcount{#1}\flsetmain{#1}% \begin{tikzpicture} \foreach \flx [count=\fli] in {#3} { \flpick{#1}{\fli+1}% % 环绕从颜色列表第 2 项起取色 \pgfmathsetmacro{\flang}{90-360/\flcntval*(\fli-1)} \node[rectangle, rounded corners=2pt, draw=\flcur!30!white, line width=0.6pt, fill=\flcur!7!white, text=\flcur!55!black, align=center, inner sep=3pt, font=\footnotesize, minimum height=17pt] (ln\fli) at (\flang:3.1cm) {\flx}; \draw[draw=\flcur!40!white, line width=0.7pt] (0,0) -- (ln\fli); }% \flsetmain{#1}% \node[circle, fill=\flmain, text=white, align=center, inner sep=2pt, minimum size=40pt, font=\small\bfseries] at (0,0) {#2}; \end{tikzpicture}% }} %% ================== 5. 阶梯递进 ================== \NewDocumentCommand \flatsteps { O{oucblue} m }{{% \flcheckitems{#2}\flcolcount{#1}% \begin{tikzpicture} \foreach \flx [count=\fli] in {#2} { \flpick{#1}{\fli}% \pgfmathsetlengthmacro{\flsx}{(\fli-1)*2.6cm} \pgfmathsetlengthmacro{\flsy}{(\fli-1)*13pt} \node[flblk, fill=\flcur, minimum height=16pt, minimum width=2.4cm, anchor=south west] at (\flsx,\flsy) {\flx}; }% \end{tikzpicture}% }} %% ================== 6. 时间轴 ================== %% \flattime[颜色列表]{年份列表}{事件列表} \NewDocumentCommand \flattime { O{oucblue} m m }{{% \flcheckitems{#2}\flcheckitems{#3}\flcount{#2}\flcolcount{#1}\flsetmain{#1}% \begin{tikzpicture} \pgfmathsetlengthmacro{\flstep}{0.9\textwidth/\flcntval}% \draw[line width=1.8pt, draw=\flmain, -{Stealth[length=2mm,width=1.6mm]}] (0,0) -- (0.9\textwidth,0); \foreach \fly [count=\fli] in {#2} { \flpick{#1}{\fli}% \pgfmathsetlengthmacro{\flxx}{(\fli-0.5)*\flstep} \node[circle, fill=\flcur, minimum size=6pt, inner sep=0pt] at (\flxx,0) {}; \node[rectangle, fill=\flcur, text=white, inner sep=2.5pt, font=\footnotesize\bfseries, rounded corners=1pt] at (\flxx,0.22cm) {\fly}; }% \foreach \fle [count=\fli] in {#3} { \flpick{#1}{\fli}% \pgfmathsetlengthmacro{\flxx}{(\fli-0.5)*\flstep} \ifodd\fli \node[flblkl, fill=\flcur!7!white, draw=\flcur!25!white, line width=0.5pt, text=\flcur!55!black, text width=2.3cm, anchor=south] at (\flxx,0.45cm) {\fle}; \else \node[flblkl, fill=\flcur!7!white, draw=\flcur!25!white, line width=0.5pt, text=\flcur!55!black, text width=2.3cm, anchor=north] at (\flxx,-0.22cm) {\fle}; \fi }% \end{tikzpicture}% }} %% ================== 7. 四象限 ================== %% \flatquad[颜色列表]{左上}{右上}{左下}{右下} \NewDocumentCommand \flatquad { O{oucblue} m m m m }{{% \flcolcount{#1}% \flpick{#1}{1}\xdef\flcA{\flcur}% \flpick{#1}{2}\xdef\flcB{\flcur}% \flpick{#1}{3}\xdef\flcC{\flcur}% \flpick{#1}{4}\xdef\flcD{\flcur}% \begin{tikzpicture} \node[flblkl, fill=\flcA!8!white, text=\flcA!55!black, text width=4.5cm, minimum height=34pt] (q1) at (0,0) {#2}; \node[flblkl, fill=\flcB!14!white, text=\flcB!55!black, text width=4.5cm, minimum height=34pt, right=3pt of q1] (q2) {#3}; \node[flblkl, fill=\flcC!14!white, text=\flcC!55!black, text width=4.5cm, minimum height=34pt, below=3pt of q1] (q3) {#4}; \node[flblkl, fill=\flcD!8!white, text=\flcD!55!black, text width=4.5cm, minimum height=34pt, right=3pt of q3] (q4) {#5}; \end{tikzpicture}% }} %% ================== 8. 金字塔 ================== %% \flatpyramid[颜色列表]{顶层, 第二层, ...} (按书写顺序自上而下) %% %% 说明:这里**不用** tikz 的 trapezium 形状。原因是它在给定 minimum width %% 时会同时撑开上边和下边,结果上下边等宽、整体平移 —— 画出来是「平行四边形」 %% 而不是梯形。改为用显式坐标自绘:每一层的上/下宽度沿同一条斜线连续变化, %% 因此整体是一个真正的金字塔。 \NewDocumentCommand \flatpyramid { O{oucblue} m }{{% \flcheckitems{#2}\flcolcount{#1}\flcount{#2}% \begin{tikzpicture}[x=1cm, y=1cm] %% ---- 形状参数(要改金字塔的胖瘦/高矮,只动这三个数)---- \pgfmathsetmacro{\flpw}{0.75} % 顶层上边的「半宽」(cm);越大顶越平 \pgfmathsetmacro{\flbw}{3.30} % 底层下边的「半宽」(cm);越大底越宽 \pgfmathsetmacro{\fllyh}{0.55} % 每层高度 (cm) \pgfmathsetmacro{\flgapy}{0.035}% 层间空隙 (cm),让各层分得清 %% ---------------------------------------------------- \pgfmathsetmacro{\flH}{\flcntval*\fllyh} \foreach \flx [count=\fli] in {#2} { \flpick{#1}{\fli}% \pgfmathsetmacro{\flt}{(\fli-1)*\fllyh} % 该层上沿相对高度 \pgfmathsetmacro{\flb}{\fli*\fllyh} % 该层下沿相对高度 %% 半宽沿斜线线性变化:顶端 \flpw → 底端 \flbw \pgfmathsetmacro{\flwt}{\flpw+(\flbw-\flpw)*(\flt/\flH)} \pgfmathsetmacro{\flwb}{\flpw+(\flbw-\flpw)*(\flb/\flH)} \pgfmathsetmacro{\flya}{-\flt} % 上沿 y(向下为负) \pgfmathsetmacro{\flyb}{-\flb+\flgapy} % 下沿 y(留出空隙) %% 真正的梯形:上边窄、下边宽 \fill[\flcur] (-\flwt,\flya) -- (\flwt,\flya) -- (\flwb,\flyb) -- (-\flwb,\flyb) -- cycle; \pgfmathsetmacro{\flmid}{(\flya+\flyb)/2} \node[text=white, font=\footnotesize, inner sep=1pt, align=center] at (0,\flmid) {\flx}; }% \end{tikzpicture}% }} %% ================== 9. 左右对比 ================== %% \flatcompare[左色][右色]{左标题}{左内容}{右标题}{右内容} \NewDocumentCommand \flatcompare { O{oucblue} O{oucamber} m m m m }{{% \begin{tikzpicture} \node[flblk, fill=#1, minimum width=4.7cm, minimum height=19pt] (h1) at (0,0) {#3}; \node[flblk, fill=#2, minimum width=4.7cm, minimum height=19pt, right=8pt of h1] (h2) {#5}; \node[flblkl, fill=#1!7!white, text=#1!55!black, text width=4.5cm, minimum height=54pt, below=3pt of h1] {#4}; \node[flblkl, fill=#2!7!white, text=#2!55!black, text width=4.5cm, minimum height=54pt, below=3pt of h2] {#6}; \end{tikzpicture}% }}