TikZ 坐标为文本底部有凹凸不平的部分

TikZ 坐标为文本底部有凹凸不平的部分

我知道可以将 TikZ 节点放置在相对于页面指定的位置,如下所示在 TikZ 中相对于页面的定位

我还知道可以获得相对于边距的节点,例如将 tikz 节点对齐到页面底部(不是纸张;包括边距)

但是,我想将 tikz 节点放置在页面底部或页边距之外,而是放置在使用时文本块实际填充的最低位置raggedbottom(因此据我所知,从页边距计算并不是很有帮助)。更准确地说,我如何使用 为 tikz 提供当前页面中最后一行排版基线的 y 坐标raggedbottom?由于我想用 来做的事情,用 手动指定最后一行tikzmark并不是一个可行的选择(据我所知),所以我想指定的是最后一行的坐标,无论排版时它是什么。

为了获得 MWE,我提供以下内容,这些内容可能很方便,但实际上并没有尝试解决问题,因为我对此感到困惑:

\documentclass{article}
\usepackage{tikz}
\usepackage[paperheight=8cm,paperwidth=12cm]{geometry}
\usepackage[defaultlines=4,all]{nowidow}
\usepackage{blindtext}
\raggedbottom

\begin{document}
\thispagestyle{empty}
\begin{tikzpicture}[remember picture,overlay]
  \node[anchor=south] at (current page.south) {I am south-bound...};
  \draw[thick] (current page.south west) rectangle (current page.north east);
\end{tikzpicture}
\blindtext
\end{document}

更新:我最初试图让问题更抽象,但正如评论中所建议的那样,也许更多的背景信息可能会有所帮助。我试图完善 Gonzalo Medina 的解决方案用波浪线标记(突出显示)某个段落(\item{…}),以便稍后注意raggedbottom上下文。在横线通过分页符绘制的情况下,第一页中该部分的 y 底部坐标计算为y of current page.center -0.5\textheight,因此如果页面较短,则raggedbottom线会延伸得太远。以下代码略微改编自 Gonzalo Medina 的答案,说明了这个问题:

\documentclass{article}
\usepackage{refcount}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing,calc}
\usepackage{lipsum}
\usepackage[defaultlines=6,all]{nowidow}
\raggedbottom

\newcounter{tmp}
\newcommand\tikzmark[1]{%
  \tikz[overlay,remember picture] \node (#1) {};}

\newcommand\Startsquiggly{%
  \stepcounter{tmp}%
  \tikzmark{a}\label{a\thetmp}%
  \ifnum\getpagerefnumber{a\thetmp}=\getpagerefnumber{b\thetmp} \else
  \begin{tikzpicture}[overlay, remember picture]
    \draw [decoration={coil,aspect=0},decorate,ultra thick,gray]
      let \p1 = (a.north), \p2 = (b), \p3 = (current page.center) in
      ( $ (\x3,\y1) + (.55\textwidth,0) $ ) --  ( $ (\x3,\y3) + (0.55\textwidth,-0.5\textheight) $ );
  \end{tikzpicture}%
  \fi%
}

\newcommand\Endsquiggly{%
\tikzmark{b}\label{b\thetmp}
  \ifnum\getpagerefnumber{a\thetmp}=\getpagerefnumber{b\thetmp}
  \begin{tikzpicture}[overlay, remember picture]
    \draw [decoration={coil,aspect=0},decorate,ultra thick,gray]
      let \p1 = (a.north), \p2 = (b), \p3 = (current page.center) in
      ( $ (\x3,\y1) + (.55\textwidth,0) $ ) --  ( $ (\x3,\y2) + (.55\textwidth,0) $ );
  \end{tikzpicture}%
  \else
  \begin{tikzpicture}[overlay, remember picture]
    \draw [decoration={coil,aspect=0},decorate,ultra thick,gray]
      let \p1 = (a.north), \p2 = (b), \p3 = (current page.center) in
      ( $ (\x3,\y3) + (.55\textwidth,.5\textheight) $ ) -- ( $ (\x3,\y2) + (.55\textwidth,0) $ );
  \end{tikzpicture}%
  \fi
}

\newcommand\Squ[1]{\Startsquiggly#1\Endsquiggly}
\begin{document}

\begin{itemize}
\item \lipsum*[1]
\item \Startsquiggly\lipsum*[1]\Endsquiggly
\item \lipsum*[1]
\item \Startsquiggly\lipsum*[1]\Endsquiggly
\end{itemize}

\end{document}

过度拉伸的线条如下所示:

在此处输入图片描述

欢迎提出解决最初一般问题的想法,或适合具体情况的替代方法。

答案1

这是一份非常初步的答案,有许多打印件。实际上,它只是对我们的聊天。这其实不是我的答案,所有棘手的问题都被 Heiko Oberdiek 在他的惊人的答案。基本思路是利用 lineno 包,它不会在空行上放置行号。Heiko 能够在最后一行上放置一个 tikz 节点。这为我们提供了最后一行的垂直位置。其余部分是简单的模数异常,因为似乎违反了因果关系的 TeX 输出程序。

\documentclass{article}
\usepackage{refcount}
\usepackage{tikz,tikzpagenodes}
\usetikzlibrary{decorations.pathmorphing,calc}
\usepackage{lipsum}
\usepackage[defaultlines=6,all]{nowidow}
\raggedbottom


\usepackage{atbegshi}
\usepackage[pagewise]{lineno}
\newcommand{\Later}{}

\makeatletter
\newcount\AbsolutePageNumber % zero-based
\AbsolutePageNumber=\z@
\newcommand*{\UnknownLineNumber}{??}
\let\FirstLineNumber\UnknownLineNumber
\let\LastLineNumber\UnknownLineNumber
\newcommand*{\GetLineNumbers}{%
  \begingroup
    \let\nextLN\relax
    \def\pageLN##1##2##3{%
      \ifnum##1=\AbsolutePageNumber
        \xdef\FirstLineNumber{\the\numexpr##3+1}%
        \global\let\LastLineNumber\@LastLineNumber
      \fi
      \ifnum##1>\AbsolutePageNumber
        \let\nextLN\relax
      \fi
    }%
    \let\firstLN\@gobble
    \def\lastLN##1{%
      \def\@LastLineNumber{\the\numexpr##1+1}%
    }%
    \LN@Pfirst
  \endgroup
}
\AtBeginShipout{%
  \GetLineNumbers
  \AtBeginShipoutAddToBox{%
    \ifx\FirstLineNumber\UnknownLineNumber
    \else
%       \fbox{%
%         \the\numexpr\LastLineNumber + 1 - \FirstLineNumber\relax
%         ~(\FirstLineNumber--\LastLineNumber)%
%       }%
    \fi
    \expandafter\ifx\csname Anchor\LastLineNumber\endcsname\relax
    \else
%       \tikz[overlay,remember picture]{%
%         \draw[thick,blue,latex-](ln\LastLineNumber)--++(-2cm,0);%
%       }%
    \fi
  }%
  \global\advance\AbsolutePageNumber\@ne
}

\renewcommand\thelinenumber{%
  %\arabic{linenumber}%
  \GetLineNumbers
  \ifx\LastLineNumber\UnknownLineNumber
  \else
    \ifnum\LastLineNumber=\numexpr\FirstLineNumber+\value{linenumber}-1\relax
      \tikz[overlay,remember picture]{%
        \node(ln\LastLineNumber){\strut};%
      }%
      \typeout{done\space with\space ln\LastLineNumber}
      \Later
      \renewcommand{\Later}{}
      \global\expandafter\let\csname Anchor\LastLineNumber\endcsname\@empty
    \fi
  \fi
}
\makeatother

\newcounter{tmp}
\newcommand\tikzmark[1]{%
  \tikz[overlay,remember picture] \node (#1) {};}

\newcommand\Startsquiggly{%
  \stepcounter{tmp}%
  \typeout{executing\space Startsquiggly\space\thetmp}
  \tikzmark{a}\label{a\thetmp}%
  \ifnum\getpagerefnumber{a\thetmp}=\getpagerefnumber{b\thetmp} \else
  \typeout{\getpagerefnumber{a\thetmp},\getpagerefnumber{b\thetmp}}
  \GetLineNumbers
  \xdef\NoWay{0}
  % here we define a command that will be executed at page shipout
  \renewcommand{\Later}{\typeout{executing\space Later\space \thetmp\space on \space page\space\thepage}
  \ifnum\NoWay=0
  \begin{tikzpicture}[overlay, remember picture]
  \draw [decoration={coil,aspect=0},decorate,ultra thick,gray]
  ([xshift=3mm]current page text area.east |- a.north)
  --([xshift=3mm]current page text area.east |- ln\LastLineNumber);
  \end{tikzpicture}
  \fi
  \xdef\NoWay{1}
  }
%   \begin{tikzpicture}[overlay, remember picture]
%     \draw [decoration={coil,aspect=0},decorate,ultra thick,gray]
%       let \p1 = (a.north), \p2 = (b), \p3 = (current page.center) in
%       ( $ (\x3,\y1) + (.55\textwidth,0) $ ) --  ( $ (\x3,\y3) + (0.55\textwidth,-0.5\textheight) $ );
%   \end{tikzpicture}%
  \fi%
}

\newcommand\Endsquiggly{%
\tikzmark{b}\label{b\thetmp}
  \ifnum\getpagerefnumber{a\thetmp}=\getpagerefnumber{b\thetmp}
  \typeout{endcase1:\getpagerefnumber{a\thetmp},\getpagerefnumber{b\thetmp}}
  \begin{tikzpicture}[overlay, remember picture]
    \draw [decoration={coil,aspect=0},decorate,ultra thick,gray]
    ([xshift=3mm]current page text area.east |- a.north)
    --([xshift=3mm]current page text area.east |- b.south);
%       let \p1 = (a.north), \p2 = (b), \p3 = (current page.center) in
%       ( $ (\x3,\y1) + (.55\textwidth,0) $ ) --  ( $ (\x3,\y2) + (.55\textwidth,0) $ );
  \end{tikzpicture}%
  \else
  \typeout{endcase2:\getpagerefnumber{a\thetmp},\getpagerefnumber{b\thetmp}}
  \begin{tikzpicture}[overlay, remember picture]
     \draw [decoration={coil,aspect=0},decorate,ultra thick,gray]
    ([xshift=3mm]current page text area.north east)
    --([xshift=3mm]current page text area.east |- b.south);
%       let \p1 = (a.north), \p2 = (b), \p3 = (current page.center) in
%       ( $ (\x3,\y3) + (.55\textwidth,.5\textheight) $ ) -- ( $ (\x3,\y2) + (.55\textwidth,0) $ );
  \end{tikzpicture}%
  \fi
}

\newcommand\Squ[1]{\Startsquiggly#1\Endsquiggly}
\begin{document}
\linenumbers
\begin{itemize}
\item \lipsum*[1]
\item \Startsquiggly\lipsum*[1]\Endsquiggly
\item \lipsum*[1]
\item \Startsquiggly\lipsum*[1]\Endsquiggly
\end{itemize}

\end{document}

请注意,我使用了 tikzpagenodes 包来绘制波浪线。因此,线条略有偏移,但您可以通过操作来重新调整水平位置[xshift=3mm]。我很乐意帮助您进行风格改进。

相关内容