如何为句子的各个部分创建悬垂标签?(进一步改进)

如何为句子的各个部分创建悬垂标签?(进一步改进)

这个问题是如何为句子的各个部分创建悬垂标签?。这个问题已经接受的答案经过贾昆。我希望他的解决方案能够得到进一步的改进。

第一次改进是否有可能实现完全相同的行为,但不影响行间空间 - 即标签应与普通文本重叠?为了清晰地阅读标签,标签应具有白色背景(或更一般地说,与页面背景具有相同的背景颜色)。

第二次改进是否可以作为可选参数,以将标签的位置定义为页面中的水平位置的方式更改标签的位置?这样应该更容易将所有标签水平对齐,甚至可能将所有标签放在页面边缘。

为什么其他套餐不能让我满意通常,在草稿模式下,我会使用todonotessoul(以及一些边注)来记录评论。至于后者,问题在于突出显示的文本和边注是两个不同的东西。在我看来,前者在语义上更正确,但由于评论插入在某个点中,因此评论所指的内容并不清楚,而 jakun 的解决方案提供了一个以文本的一部分作为参数的标签。此外,从纯粹的美学角度来看,jakun 的解决方案更美观。

答案1

  1. 我添加了一个布尔值选项smash。如果为真,则标签(和线条)不会影响 tikzpicture 的高度。(现在text ysep不再影响高度。)

    实施情况与我在评论中建议的不同我对原始问题的回答因为这是绝对定位所必需的。此实现的缺点是它需要运行两次。

    (该名称源自宏\smash。)

  2. 我已将新值添加到以pos结尾的键中abs,用于绝对(水平)位置。这些值将尝试将标签的左/右侧相对于文本的右/左边框进行定位。

    这些必须smash是真实的,因此隐式设置它。

    我使用了一种相当简单的算法来计算边距的大小。如果(\oddsidemargin\evensidemargin不相等)标签出现在同一个段落的分页符之后,它将失败(它将使用上一页的边距,因为它不知道它已经分页到下一页)。如果发生这种情况,您可以_offset x手动设置为我定义的边距命令之一(可能前面有一个减号)。

    \label使用和\pageref可以实现更加强大但更加困难的实现(需要两次运行) 。

    如果您不想担心这个问题,您可以将其设置_offset x为零,_anchor label水平翻转,取反shift x并相对于页面边框定位标签。

  3. 我添加了一些额外的新功能:

    • pos键值的左侧计数器部分
    • line style我对原始问题的答案的编辑建议
    • 其中label style值如text width, align, draw, fill,rounded corners可以应用Z 文档
    • 你可以pos = above left absabove left abs
\documentclass[twoside]{article}
\usepackage{blindtext}

\usepackage{tikz}


% --------------- margins ---------------

\newcommand{\oddmarginleft}{(1in+\hoffset+\oddsidemargin)}
\newcommand{\evenmarginleft}{(1in+\hoffset+\evensidemargin)}
\newcommand{\marginleft}{\ifodd\thepage\oddmarginleft\else\evenmarginleft\fi}

\newcommand{\oddmarginright}{(\paperwidth-\textwidth-\oddmarginleft)}
\newcommand{\evenmarginright}{(\paperwidth-\textwidth-\evenmarginleft)}
\newcommand{\marginright}{\ifodd\thepage\oddmarginright\else\evenmarginright\fi}


% --------------- def options ---------------

\newif\ifsmashmylabel

\pgfqkeys{/mylabel}{%
    % geometry
    shift x/.initial = 1.5em,
    shift y/.initial = .2em,
    slope width/.initial = .3em,
    text xsep/.initial  = .1em,
    text ysep/.initial  = .1em,
    label xsep/.initial = .3333em,
    label ysep/.initial = .3333em,
    smash/.is if = smashmylabel,
    xref/.initial = inline,
    %
    % colors
    line color/.initial  = black,
    text color/.initial  = black,
    label color/.initial = black,
    color/.style = {line color=#1, label color=#1},
    %
    % styles
    line style/.initial =,
    label style/.initial =,
    %
    % label position shortcuts
    /mylabel/pos/.is choice,
    /mylabel/pos/above/.style = {pos=above right},
    /mylabel/pos/below/.style = {pos=below right},
    %
    % label positions relative x
    /mylabel/pos/below right/.style = {%
        _anchor label  = north west,
        _sign x        =  ,
        _sign y        = -,
        _line pos      = south,
        xref           = inline,
        _offset x      = 0pt,
    },
    /mylabel/pos/above right/.style = {%
        _anchor label  = south west,
        _sign x        =  ,
        _sign y        =  ,
        _line pos      = north,
        xref           = inline,
        _offset x      = 0pt,
    },
    %
    /mylabel/pos/below left/.style = {%
        _anchor label  = north east,
        _sign x        = -,
        _sign y        = -,
        _line pos      = south,
        xref           = inline,
        _offset x      = 0pt,
    },
    /mylabel/pos/above left/.style = {%
        _anchor label  = south east,
        _sign x        = -,
        _sign y        =  ,
        _line pos      = north,
        xref           = inline,
        _offset x      = 0pt,
    },
    %
    % label positions absolute x
    /mylabel/pos/below right abs/.style = {%
        _anchor label  = north west,
        _sign x        =  ,
        _sign y        = -,
        _line pos      = south,
        xref           = current page.east,
        _offset x      = -\marginright,
        smash          = true,
    },
    /mylabel/pos/above right abs/.style = {%
        _anchor label  = south west,
        _sign x        =  ,
        _sign y        =  ,
        _line pos      = north,
        xref           = current page.east,
        _offset x      = -\marginright,
        smash          = true,
    },
    %
    /mylabel/pos/below left abs/.style = {%
        _anchor label  = north east,
        _sign x        = -,
        _sign y        = -,
        _line pos      = south,
        xref           = current page.west,
        _offset x      = \marginleft,
        smash          = true,
    },
    /mylabel/pos/above left abs/.style = {%
        _anchor label  = south east,
        _sign x        = -,
        _sign y        =  ,
        _line pos      = north,
        xref           = current page.west,
        _offset x      = \marginleft,
        smash          = true,
    },
    %
    % internal
    _anchor label/.initial,
    _direction/.initial,
    _line pos/.initial,
    _sign x/.initial,
    _sign y/.initial,
    _offset x/.initial,
    %
    % struts
    inline strut/.initial=\vphantom{Ap},
    label strut/.initial=\strut,
    %
    % try pos if key is unknown
    % based on pgfmanual page 900
    % I don't know why `.search also` does not work instead
    .unknown/.code = {%
        \let\searchname=\pgfkeyscurrentname
        \pgfkeysalso{/mylabel/pos/\searchname/.try}%
        \ifpgfkeyssuccess
        \else
            \let\pgfkeyscurrentkey=\searchname
            \def\pgfkeyscurrentvalue{\pgfkeysnovalue}%
            \def\pgfutilnext{\pgfkeysvalueof{/handlers/.unknown/.@cmd}\searchname\pgfeov}%
            \pgfutilnext
        \fi
    },
}

\newcommand{\setmylabel}[1]{%
    \pgfqkeys{/mylabel}{#1}%
}


% --------------- init options ---------------

\setmylabel{%
    pos = below,
}


% --------------- \mylabel command ---------------

\newcommand{\mylabel}[3][]{% [#1: options], #2: inline text, #3: label text
    \begingroup
    % process options
    \setmylabel{#1}
    %
    \begin{tikzpicture}[remember picture, baseline=(inline.base)]
        % draw inline text
        \node[%
            inner xsep = \pgfkeysvalueof{/mylabel/text xsep},
            inner ysep = 0pt,
            text = \pgfkeysvalueof{/mylabel/text color},
        ] (inline) {\pgfkeysvalueof{/mylabel/inline strut}#2};
        \ifsmashmylabel
    \end{tikzpicture}%
    \begin{tikzpicture}[remember picture, overlay]
        \fi
        % draw label
        \pgfkeys{/mylabel/label style/.get=\tmpLabelStyle}
        \node (label) [
            xshift = \pgfkeysvalueof{/mylabel/_sign x}\pgfkeysvalueof{/mylabel/shift x} + \pgfkeysvalueof{/mylabel/_offset x},
            yshift = \pgfkeysvalueof{/mylabel/_sign y}\pgfkeysvalueof{/mylabel/shift y},
            anchor = \pgfkeysvalueof{/mylabel/_anchor label},
            inner xsep = \pgfkeysvalueof{/mylabel/label xsep},
            inner ysep = \pgfkeysvalueof{/mylabel/label ysep},
            text = \pgfkeysvalueof{/mylabel/label color},
            /utils/exec = \expandafter \pgfkeysalso \expandafter {\tmpLabelStyle},
        ] at (\pgfkeysvalueof{/mylabel/xref} |- inline.\pgfkeysvalueof{/mylabel/_line pos})
        {\pgfkeysvalueof{/mylabel/label strut}#3};

        % draw lines
        \coordinate (line-w) at ([yshift = \pgfkeysvalueof{/mylabel/_sign y}\pgfkeysvalueof{/mylabel/text ysep}] inline.\pgfkeysvalueof{/mylabel/_line pos} west);
        \coordinate (line-e) at ([yshift = \pgfkeysvalueof{/mylabel/_sign y}\pgfkeysvalueof{/mylabel/text ysep}] inline.\pgfkeysvalueof{/mylabel/_line pos} east);
        \coordinate (line-c) at ([yshift = \pgfkeysvalueof{/mylabel/_sign y}\pgfkeysvalueof{/mylabel/text ysep}] inline.\pgfkeysvalueof{/mylabel/_line pos});

        \pgfkeys{/mylabel/line style/.get=\tmpLineStyle}%
        \expandafter \draw \expandafter [\tmpLineStyle, draw=\pgfkeysvalueof{/mylabel/line color}]
            (line-w) -- (line-e)
            (line-c) -- ([xshift=\pgfkeysvalueof{/mylabel/_sign x}\pgfkeysvalueof{/mylabel/slope width}] line-c |- label) -- (label);
        ;

        % set bounding box
        \ifsmashmylabel
        \else
            \pgfresetboundingbox
            \useasboundingbox 
                (inline.south west) rectangle (inline.north east)
                (inline |- label.south) rectangle (inline |- label.north)
            ;
        \fi
    \end{tikzpicture}%
    \endgroup
}


% --------------- test document ---------------

\setmylabel{%
    line color  = orange,
    text color  = blue,
    label color = green,
    pos = below right abs,
}

\begin{document}
    \blindtext
    text \mylabel[above left abs]{part}{label~1} of a \mylabel{sentence}{label~2}
    \blindtext
    \newpage
    \blindtext
    text \mylabel[above left abs]{part}{label~1} of a \mylabel{sentence}{label~2}
    \blindtext
\end{document}

在此处输入图片描述


label style使用方法示例:

\setmylabel{%
    label strut = ,
    label style = {text width=5em, draw=gray, fill=yellow!10!white, rounded corners,},
    pos/above left abs/.append style = {label style/.append={align=flush right}},
    pos/above right abs/.append style = {label style/.append={align=flush left}},
}

在此处输入图片描述


我注意到一些关键名称可能会引起混淆:

  • 它叫 Z xshift,是我给它命名的shift x
  • shift x更像是距离而不是偏移,反转方向时其值会自动取反。(不同于_offset x正值表示右,负值表示左。)

但我不想破坏向后兼容性(或者也许我只是懒得改变这一点......)

相关内容