我的 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}