Tikz 标注:定位指针的开始

Tikz 标注:定位指针的开始

我的 Tikz 标注矩形的指针始终从矩形的中间开始。但这种指针有时会妨碍其他对象(例如,在下面的示例中,指针的起点应该更靠左)。

因此我想定位指针的起始位置手动,例如通过 degree 或.south west类似方式。(如何)我可以这样做吗?我可以以某种方式修改标准 tikz 调用,以便可以通过某些参数确定此定位吗?或者有其他替代包吗?


这是一个最小工作示例(mwe):

\documentclass[10pt,a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\usetikzlibrary{shapes}
\begin{document}
\begin{tikzpicture}[>=latex]
\node[draw, align=center, rounded corners=2pt, rectangle] at (2.6,-1.7) (c22) {Further Rectangle};

\node[rectangle callout,draw,inner sep=2pt,color=red,
   callout absolute pointer={(c22.west)}] at (1.48,-.95) {no
     workarounds; no exceptions to optimizations}; 
\end{tikzpicture}
\end{document}

mwe 的结果是第一个图,但我想要第二个图那样的东西。

在此处输入图片描述

在此处输入图片描述

答案1

标注形状的指针位于线上,该线经过给定的坐标(在您的情况下为 c22.west)和标注形状的中心。在您的情况下,您根据其形状中心确定标注位置。

我很担心,我不太明白你想要实现什么,所以下面是 mwe,它显示了我将如何设计你的草图:

\documentclass[tikz,border=5mm]{standalone}
    \usetikzlibrary{positioning,shapes}
\begin{document}
\begin{tikzpicture}[>=latex]
\node[draw, align=center, rounded corners=2pt,
      rectangle] at (2.6,-1.7) (c22) {Further Rectangle};

\node[rectangle callout,draw,inner sep=2pt,color=red,align=left,
      callout absolute pointer=(c22.west),
      above left= 5pt and 0pt of c22.north west]
      {no workarounds;  \\
       no exceptions    \\
       to optimizations};

\node[draw, align=center, rounded corners=2pt,
      rectangle] at (2.6,-3.7) (d22) {Further Rectangle};

\node[rectangle callout,draw,inner sep=2pt,color=red,align=left,
      callout absolute pointer=(d22.west),
      above left= 5pt and 0pt of d22.north east]
      {no workarounds;  no exceptions  to optimizations};
\end{tikzpicture}
\end{document}

在示例中,我使用库定位,这为放置标注形状提供了自由。如果您坚持要求标注中的文本只有一行,则只需在文本中省略反斜杠即可。要将标注移到更左侧(指针不会穿过形状),只需确定标注形状的新位置,类似于我对第二种情况所做的操作

在此处输入图片描述

答案2

虽然这个问题已经很老了,但似乎还没有官方的方法来解决这个问题。我查看了原始定义,找到了一种移动起点的方法:我引入了两个新选项

callout pointer xshift = <dim>
callout pointer yshift = <dim>

可用于将指针起始点移动<dim>。它可以与现有rectangle callout形状一起使用,如下所示:

\node at (2,3) [
   draw,
   rectangle callout,
   callout absolute pointer = (A.north),
   callout pointer xshift = -20mm,
] {This is a long callout with a pointer \textbf{not} starting from the middle};

图像的上部显示了原始指针起点的标注,下部显示了移位后的标注。

在此处输入图片描述

这需要添加行

\advance\pgf@x\callout@move@pointer@start@x

\advance\pgf@y\callout@move@pointer@start@y

在 的定义中,其中计算了\pgf@lib@rectanglecallout@pointer两个点\beforecalloutpointer和。这些行只是将带有新关键选项的集合添加到最初计算的坐标中。\aftercalloutpointer<dim>

完整代码

\documentclass{article}

\usepackage{parskip}

\usepackage{tikz}
\usetikzlibrary{shapes.callouts}

\makeatletter

\newlength{\callout@move@pointer@start@x}
\newlength{\callout@move@pointer@start@y}
\pgfkeys{/pgf/.cd,
    callout pointer xshift/.code={\setlength{\callout@move@pointer@start@x}{#1}},
    callout pointer yshift/.code={\setlength{\callout@move@pointer@start@y}{#1}},
}

% \pgf@lib@rectanglecallout@pointer
%
% Internal macro for calculations relating to the rectangle callout.
%
% Requires the following to be set up:
%
% \calloutpointer - the location of the callout point.
% \xtemp          - the half width of the rectangle
% \ytemp          - the half height of the rectangle
% \pointerwidth   - the width of the pointer.
%
\def\pgf@lib@rectanglecallout@pointer{%
    %
    % Ensure that the pointer never connects to the main shape
    % too near to a corner. This is done for two reasons:
    % 1. It can look ugly.
    % 2. If the corners are rounded, a mess can result.
    %
    \pgfextract@process\borderpoint{%
            \pgfpointborderrectangle{%
                \centerpoint%
                \pgf@xa\pgf@x%
                \pgf@ya\pgf@y%
                \calloutpointer%
                \advance\pgf@x-\pgf@xa%
                \advance\pgf@y-\pgf@ya%
            }{\pgfqpoint{\xtemp}{\ytemp}}%
        }%
    \pgfmathanglebetweenpoints{\pgfpointorigin}{\borderpoint}%
    \let\borderangle\pgfmathresult%
    %
    \pgfutil@tempdima\pointerwidth\relax%
    \pgf@xa\xtemp\relax%
    \advance\pgf@xa-\pgfutil@tempdima%
    \pgf@ya\ytemp\relax%
    \advance\pgf@ya-\pgfutil@tempdima%
    %
    \pgf@process{%
        \pgfutil@ifundefined{pgf@corner@arc}{\pgfpointorigin}{%
            \expandafter\pgfqpoint\pgf@corner@arc}%
    }%
    \advance\pgf@xa-\pgf@x%
    \advance\pgf@ya-\pgf@y%
    %
    \borderpoint%
    \pgf@xb\pgf@x%
    \pgf@yb\pgf@y%
    %
    \pgf@xc0pt\relax%
    \pgf@yc0pt\relax%
    %
    \pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfqpoint{\xtemp}{\ytemp}}%
    \ifdim\borderangle pt<\pgfmathresult pt\relax%
        \[email protected]\pgfutil@tempdima%
        \ifdim\pgf@yb>\pgf@ya%
            \pgf@yb\pgf@ya%
        \fi%
        %
        % Establish the order for drawing the rectangle corners.
        %
        \edef\firstpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
        \edef\secondpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
        \edef\thirdpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
        \edef\fourthpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
    \else%
        \pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfqpoint{-\xtemp}{\ytemp}}%
        \ifdim\borderangle pt<\pgfmathresult pt\relax%
            \[email protected]\pgfutil@tempdima%
            \ifdim\pgf@xb>\pgf@xa%
                \pgf@xb\pgf@xa%
            \else%
                \ifdim\pgf@xb<-\pgf@xa%
                    \pgf@xb-\pgf@xa%
                \fi%
            \fi%
            \edef\firstpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
            \edef\secondpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
            \edef\thirdpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
            \edef\fourthpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
        \else%
            \pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfqpoint{-\xtemp}{-\ytemp}}%
            \ifdim\borderangle pt<\pgfmathresult pt\relax%
                \[email protected]\pgfutil@tempdima%
                \ifdim\pgf@yb>\pgf@ya%
                    \pgf@yb\pgf@ya%
                \else%
                    \ifdim\pgf@yb<-\pgf@ya%
                        \pgf@yb-\pgf@ya%
                    \fi%
                \fi%
                \edef\firstpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
                \edef\secondpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
                \edef\thirdpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
                \edef\fourthpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
            \else%
                \pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfqpoint{\xtemp}{-\ytemp}}%
                \ifdim\borderangle pt<\pgfmathresult pt\relax%
                    \[email protected]\pgfutil@tempdima%
                    \ifdim\pgf@xb>\pgf@xa%
                        \pgf@xb\pgf@xa%
                    \else%
                        \ifdim\pgf@xb<-\pgf@xa%
                            \pgf@xb-\pgf@xa%
                        \fi%
                    \fi%
                    \edef\firstpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
                    \edef\secondpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
                    \edef\thirdpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
                    \edef\fourthpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
                \else%
                    \[email protected]\pgfutil@tempdima%
                    \ifdim\pgf@yb<-\pgf@ya%
                        \pgf@yb-\pgf@ya%
                    \fi%
                    \edef\firstpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
                    \edef\secondpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
                    \edef\thirdpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
                    \edef\fourthpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
                \fi%
            \fi%
        \fi%
    \fi%
    \pgfextract@process\beforecalloutpointer{%
        \centerpoint%
        \advance\pgf@x\pgf@xb%
        \advance\pgf@x\callout@move@pointer@start@x% <------------------ ADDED HERE
        \advance\pgf@y\pgf@yb%
        \advance\pgf@y\callout@move@pointer@start@y% <------------------ ADDED HERE
        \advance\pgf@x-\pgf@xc%     
        \advance\pgf@y-\pgf@yc%
    }%  
    \pgfextract@process\aftercalloutpointer{%
        \centerpoint%
        \advance\pgf@x\pgf@xb%
        \advance\pgf@x\callout@move@pointer@start@x% <------------------ ADDED HERE
        \advance\pgf@y\pgf@yb%
        \advance\pgf@y\callout@move@pointer@start@y% <------------------ ADDED HERE
        \advance\pgf@x\pgf@xc%      
        \advance\pgf@y\pgf@yc%
    }%  
    %
    % Now calculate the pointer anchor.
    %
    \pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength\pgf@y{\pgfkeysvalueof{/pgf/outer ysep}}%
    \ifdim\pgf@x>\pgf@y%
        \edef\outersep{\the\pgf@x}%
    \else%
        \edef\outersep{\the\pgf@y}%
    \fi%
    \pgf@lib@callouts@pointeranchor%
}

\makeatother

\begin{document}

\begin{tikzpicture}
   \node [fill, gray,circle] (A) at (2,1) {};
   \node at (2,3) [
      draw,
      rectangle callout,
      callout absolute pointer = (A.north),
   ] {This is a long callout with a pointer starting from the middle};
   \node at (5,1) [
      draw,
      rectangle callout,
      callout absolute pointer = (A.east),
      text width = 40mm,
   ] {This is a long callout with a pointer starting from the middle};
\end{tikzpicture}

\bigskip
\begin{tikzpicture}
   \node [fill, gray,circle] (A) at (2,1) {};
   \node at (2,3) [
      draw,
      rectangle callout,
      callout absolute pointer = (A.north),
      callout pointer xshift = -20mm,
   ] {This is a long callout with a pointer \textbf{not} starting from the middle};
   \node at (5,1) [
      draw,
      rectangle callout,
      callout absolute pointer = (A.east),
      callout pointer yshift = 4mm,
      text width = 40mm,
   ] {This is a long callout with a pointer \textbf{not} starting from the middle};
\end{tikzpicture}

\end{document}

相关内容