我正在尝试在 TikZ 中围绕节点制作一个自动缩放的矩形云形状。下面的第一次尝试给出了一个椭圆形的云,但我不喜欢那样。我希望它是矩形的,就像第二次尝试一样。但那一次失败了;角是错误的,边缘是内外颠倒的。
\documentclass{book}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,decorations.pathmorphing}
\newcommand{\thinkA}[1] {
\begin{tikzpicture}
\node[cloud, draw, align=left, cloud puffs=20,cloud puff arc=110, aspect=2, inner sep=0mm]{#1};
\end{tikzpicture}
}
\newcommand{\thinkB}[1] {
\begin{tikzpicture}
\node [rectangle, draw, decoration=bumps, decorate, align=left, inner sep=4mm] {#1};
\end{tikzpicture}
}
\begin{document}
\thinkA{$3+5=8$\\$8+1=9$\\$9+6=15$}
\thinkB{$3+5=8$\\$8+1=9$\\$9+6=15$}
\end{document}
编辑:
感谢您迄今为止的反馈。这些解决方案看起来很有希望,但与提供的示例相比,其他内容存在一些缺陷:
我试图制定一个我可以使用的内容的计划:最好是一个带有三个参数的命令;第一个是内容,第二个是边距,第三个是圆的直径,如下图所示:
必须计算绿色填充,以便边缘周围的圆圈图案能够正常工作。在上图中,边距设置为 2 毫米,圆圈直径为 5 毫米。内容恰好是 32 毫米宽和 16 毫米高。因此,我们需要 4 毫米额外宽度和 0 毫米额外高度来使圆圈匹配。
我尝试过做类似的东西,但我在编写 TikZ 程序时真的很吃力。下面的示例是我找到的修改版本别处在论坛上:
\documentclass{book}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,decorations.pathmorphing,calc}
\begin{document}
\begin{tikzpicture}[x=1mm,y=1mm]
\coordinate (NW) at (-30,20);
\coordinate (NE) at (30,20);
\coordinate (SW) at (-30,-20);
\coordinate (SE) at (30,-20);
\foreach \i in {0,2,...,12}{
\draw[black] ([xshift=\i*5mm]NW) circle (5mm); % Draw circles on top
\draw[black] ([xshift=\i*5mm]SW) circle (5mm); % Draw circles on bottom
}
\foreach \i in {2,4,...,6}{
\draw[black] ([yshift=-\i*5mm]NW) circle (5mm); % Draw circles on left
\draw[black] ([yshift=-\i*5mm]NE) circle (5mm); % Draw circles on right
}
\fill[white] (NW) rectangle (SE);
\node {contents};
\end{tikzpicture}
\end{document}
编辑2:
我正在努力理解 let 命令,并将其与循环结合起来,沿边缘绘制一系列圆弧。哎呀:我甚至无法计算两点之间的距离!我真的很烂。我意识到实际上不需要三个参数,我很乐意让边距在命令中使用 inner sep 固定,并为圆半径设置另一个固定大小,因为我可能会一直使用相同的半径。
编辑3:
有时你只需要咬紧牙关,坐下来研究文档。所以我这样做了,并制定了以下解决方案。如果云弧半径与内容的宽度和高度相比非常大,则代码很丑陋并且不起作用,但这个解决方案对我来说是有效的:
\documentclass{book}
\usepackage{tikz}
\usetikzlibrary{calc}
\newcommand{\think}[1] {
\begin{tikzpicture}
\node (X) [rectangle, align=left, inner sep=2mm] {#1};
\def\R{1.7mm}% Radius of cloud arcs
\draw let
\p1 = ($ (X.north east) - (X.north west) $),
\p2 = ($ (X.north east) - (X.south east) $),
\n{width} = {veclen(\x1,\y1)},
\n{height}= {veclen(\x2,\y2)},
\n{wnum} = {ceil(\n{width}/(2*\R)) - 1},
\n{hnum} = {ceil(\n{height}/(2*\R)) - 1},
\n{newwidth} = {(2*\R) * (\n{wnum}+1)},
\n{newheight} = {(2*\R) * (\n{hnum}+1)},
\p3 = ($ (X.center) + (-\n{newwidth}/2,\n{newheight}/2) $)
in
\foreach \m in {1,2,...,\n{wnum}} {
($(\p3) + (\R+\m*2*\R,0)$) arc(0:180:\R)
($(\p3) + (-\R+\m*2*\R,-\n{newheight})$) arc(180:360:\R)
}
\foreach \m in {1,2,...,\n{hnum}} {
($(\p3) + (0,\R-\m*2*\R)$) arc(90:270:\R)
($(\p3) + (\n{newwidth},-\R-\m*2*\R)$) arc(-90:90:\R)
}
($ (\p3) + (\R,0) $) arc(0:270:\R)% top left corner
($ (\p3) + (\n{newwidth},-\R) $) arc(-90:180:\R)% top right corner
($ (\p3) + (0,-\n{newheight}+\R) $) arc(90:360:\R)% bottom left corner
($ (\p3) + (\n{newwidth}-\R,-\n{newheight}) $) arc(-180:90:\R);% bottom right corner
\end{tikzpicture}
}
\begin{document}
\think{$3+5=8$\\$8+1=9$\\$9+6=15$}
\end{document}
答案1
以下示例从矩形节点中删除线条绘制。相反,它会在之后绘制装饰线。通过将角替换为四分之一圆来修复角:
\documentclass{book}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,decorations.pathmorphing}
\usetikzlibrary{calc}
\newcommand{\thinkC}[1] {
\begin{tikzpicture}
\node (X) [rectangle,
% draw,
% rounded corners,
% decoration={snake, amplitude=2pt},
% decorate,
align=left, inner sep=4mm] {#1};
\def\R{11pt}
\draw[
decoration={bumps,segment length=8.1192pt},
decorate,
]
($(X.south west) + (\R, 0)$) arc(270:180:\R) --
($(X.north west) + (0, -\R)$) arc(180:90:\R) --
($(X.north east) + (-\R, 0)$) arc(90:0:\R) --
($(X.south east) + (0, \R)$) arc(0:-90:\R) --
cycle
;
\end{tikzpicture}
}
\begin{document}
\thinkC{$3+5=8$\\$8+1=9$\\$9+6=15$}
\end{document}
缺点:需要仔细选择段长度以避免路径末端出现直线,因为剩余空间太小而无法形成完整的“凸起”。
以下方法使用带有 的装饰矩形path has corners
。然后矩形稍微变大一些,宽度和高度都适合整数个凸起,请参阅代码中的注释:
\documentclass{book}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,decorations.pathmorphing}
\usetikzlibrary{calc}
\newcommand*{\StartSegmentLength}{8pt}
\newcommand{\thinkC}[1] {
\begin{tikzpicture}
% The rectangle node without frame
\node (X) [
rectangle,
align=left,
inner sep=4mm,
] {#1};
% Get the width \WD and height \HT of the rectangle
\pgfpointdiff{\pgfpointanchor{X}{south west}}{\pgfpointanchor{X}{north east}}
\pgfgetlastxy\WD\HT
% The shorter lenght of \WD and \HT is used to adapt the
% segment length. \L is the shorter of \WD and \HT.
% It is assumed that both \WD and \HT are large enough to contain
% quite a few bumps, thus that the recalculated segment length
% does not change too much. Also it is assumed, that enlarging the
% larger length (width or height) is visually noticed less than
% enlarging the smaller length.
\ifdim\WD<\HT
\let\L\WD
\else
\let\L\HT
\fi
% Recalculate the segment length.
% Option "segment length" seems to cover *two* bumps.
% Thus the calculations/roundings are done with half of the segment
% length.
\pgfmathsetlengthmacro\SegmentLength{\L / round(\L*2/\StartSegmentLength)}
% Calculate the new height and width as multiple of half of
% the segment length.
% The addition of .1pt should protect from rounding errors.
\pgfmathsetlengthmacro\newHT{
round(\HT/\SegmentLength) * \SegmentLength + .1pt
}
\pgfmathsetlengthmacro\newWD{
round(\WD/\SegmentLength) * \SegmentLength + .1pt
}
% Calculate the offsets for the corner points of the rectangle
\pgfmathsetlengthmacro\XOff{(\newWD - \WD)/2}
\pgfmathsetlengthmacro\YOff{(\newHT - \HT)/2}
% Full segment length
\pgfmathsetlengthmacro\SegmentLength{2 * \SegmentLength}
% Now the decoration:
\draw[
decoration={
bumps,
segment length=\SegmentLength,
path has corners,
},
decorate,
line join=round,
]
($(X.south west) - (\XOff, \YOff)$) rectangle
($(X.north east) + (\XOff, \YOff)$)
;
% Debugging only: The red box shows the original rectangle.
% \draw[very thin, red] (X.south west) rectangle (X.north east);
\end{tikzpicture}
}
\begin{document}
\centering
\thinkC{$3+5=8$\\$8+1=9$\\$9+6=15$}
\thinkC{21212121212121}
\end{document}
更新: line join=round
增加了凸块之间的更好连接。
修复原始解决方案中的圆角问题
可以通过定义宏来配置每个角的凸起数量\BumpsPerCorner
。
\documentclass{book}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,decorations.pathmorphing}
\usetikzlibrary{calc}
\newcommand{\thinkC}[1]{
\begin{tikzpicture}
% The rectangle node without frame
\node (X) [
rectangle,
align=left,
inner sep=4mm,
] {#1};
\def\SegmentLength{8pt}
\def\BumpsPerCorner{4}
% A bump uses half of the segment length
\pgfmathsetlengthmacro\BumpLength{\SegmentLength/2}
% Calculate radius, large enough for specified \BumpsPerCorner
% Addition of .1pt should protect from rounding errors
\pgfmathsetlengthmacro\R{
\BumpsPerCorner * 2 * \BumpLength / pi + .1pt
}
% Get the width \WD and height \HT of the rectangle
\pgfpointdiff{\pgfpointanchor{X}{south west}}
{\pgfpointanchor{X}{north east}}
\pgfgetlastxy\WD\HT
% Get \WD and \HT as length of the straight lines
\pgfmathsetlengthmacro\WD{\WD - 2 * \R}
\pgfmathsetlengthmacro\HT{\HT - 2 * \R}
% Calculate new lengths as integer factor of the Bump length
\pgfmathsetlengthmacro\newWD{
round(\WD/\BumpLength) * \BumpLength + .1pt
}
\pgfmathsetlengthmacro\newHT{
round(\HT/\BumpLength) * \BumpLength + .1pt
}
% Calculate the offsets for the corner points of the rectangle
\pgfmathsetlengthmacro\XOff{(\newWD - \WD)/2}
\pgfmathsetlengthmacro\YOff{(\newHT - \HT)/2}
% Full segment length
\pgfmathsetlengthmacro\SegmentLength{2 * \BumpLength}
% Now the decoration:
\draw[
decoration={
bumps,
segment length=\SegmentLength,
path has corners,
},
decorate,
line join=round,
]
($(X.south west) + (-\XOff, -\YOff) + (\R, 0)$) arc(270:180:\R) --
($(X.north west) + (-\XOff, \YOff) + (0, -\R)$) arc(180:90:\R) --
($(X.north east) + (\XOff, \YOff) + (-\R, 0)$) arc(90:0:\R) --
($(X.south east) + (\XOff, -\YOff) + (0, \R)$) arc(0:-90:\R) --
cycle
;
% Debugging only: The red box shows the original rectangle.
% \draw[very thin, red] (X.south west) rectangle (X.north east);
\iffalse
\draw[red, very thin]
($(X.south west) + (-\XOff, -\YOff) + (\R, 0)$) arc(270:180:\R) --
($(X.north west) + (-\XOff, \YOff) + (0, -\R)$) arc(180:90:\R) --
($(X.north east) + (\XOff, \YOff) + (-\R, 0)$) arc(90:0:\R) --
($(X.south east) + (\XOff, -\YOff) + (0, \R)$) arc(0:-90:\R) --
cycle
;
\fi
\end{tikzpicture}
}
\begin{document}
\centering
\thinkC{$3+5=8$\\$8+1=9$\\$9+6=15$}
\thinkC{21212121212121}
\end{document}
每个角落的凸起数:4
每角凸起数:6
答案2
像这样吗?
装饰代码改为
decoration={bumps, path has corners, amplitude=-2.5pt, segment length=15pt}
2.5pt
是默认值amplitude
。将其设为负数会导致凸起朝相反方向凸起。默认值为segment length
。10pt
因此15pt
会稍微拉伸凸起。但是,请小心使用,因为值越大,失真越大。path has corners
使 Ti钾Z 会“更加小心地”绕过拐角,并且当路径有尖角时通常会改善结果。
完整代码:
\documentclass[border=10pt,multi,tikz]{standalone}
\usetikzlibrary{decorations.pathmorphing}
\newcommand{\thinkB}[1]{%
\begin{tikzpicture}
\node [rectangle, draw, decoration={bumps, path has corners, amplitude=-2.5pt, segment length=15pt}, decorate, align=left, inner sep=4mm] {#1};
\end{tikzpicture}%
}
\begin{document}
\thinkB{$3+5=8$\\$8+1=9$\\$9+6=15$}
\end{document}
答案3
该解决方案基于Heiko 的一个。它不使用 ,decoration
而是使用绘制节点的命令\ThinkA
,然后使用cloud
。此命令有一个强制参数(节点内容)和一个可选参数,用于定义凸块的直径(默认为 5mm)。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning, calc}
\newcommand{\ThinkA}[2][5mm]{%
\begin{tikzpicture}
\node[align=left, inner sep=4mm] (X) {#2};
% Get the width \WD and height \HT of the rectangle
\pgfpointdiff{\pgfpointanchor{X}{south west}}{\pgfpointanchor{X}{north east}}
\pgfgetlastxy\WD\HT
% Define diameter for bumps
\pgfmathsetlengthmacro\Diameter{#1}
% Calculate the new height and width as multiple of
% the radius
\pgfmathsetlengthmacro\newHT{
round(\HT/\Diameter) * \Diameter + .1pt
}
\pgfmathsetlengthmacro\newWD{
round(\WD/\Diameter) * \Diameter + .1pt
}
% Calculate the offsets for the corner points of the rectangle
\pgfmathsetlengthmacro\XOff{(\newWD - \WD)/2}
\pgfmathsetlengthmacro\YOff{(\newHT - \HT)/2}
\path ([shift={(-\XOff,\YOff)}]X.north west) coordinate (X1) rectangle ([shift={(\XOff,-\YOff)}]X.south east) coordinate (X2);
\pgfmathsetmacro{\HBumps}{\newWD/\Diameter-1}
\pgfmathsetmacro{\VBumps}{\newHT/\Diameter-1}
% Draw upper and lower bumps
\foreach \i in {1,...,\HBumps}{
\draw ([xshift=-\Diameter/2+\i*\Diameter]X1) arc(180:0:\Diameter/2);
\draw ([xshift=\Diameter/2-\i*\Diameter]X2) arc(0:-180:\Diameter/2);
}
% Draw left and right bumps
\foreach \i in {1,...,\VBumps}{
\draw ([yshift=\Diameter/2-\i*\Diameter]X1) arc(90:270:\Diameter/2);
\draw ([yshift=-\Diameter/2+\i*\Diameter]X2) arc(-90:90:\Diameter/2);
}
% Draw corners bumps
\draw ([xshift=\Diameter/2]X1) arc(0:270:\Diameter/2);
\draw ([xshift=-\Diameter/2]X1-|X2) arc(180:-90:\Diameter/2);
\draw ([yshift=\Diameter/2]X1|-X2) arc(90:360:\Diameter/2);
\draw ([yshift=\Diameter/2]X2) arc(90:-180:\Diameter/2);
\end{tikzpicture}
}
\begin{document}
\ThinkA{$3+5=8$\\$8+1=9$\\$9+6=15$}
\ThinkA[4mm]{$3+5=8$\\$8+1=9$\\$9+6=15$}
\ThinkA[7mm]{21212121212121}
\end{document}
答案4
编辑
第二次尝试
正如 cfr 评论的那样,这可能不是您的本意。但是,您可以更改选项,decorate
使其反映模式。然后,您还可以使用 设置每个装饰的大小,segment length
并使用 指示您的节点有角path has corners
。不幸的是,您必须设置一个minimum width
,minimum height
因此它是n*(segment length-tiny bit)
。
我希望这能满足你的需要。
结果
代码
\documentclass[convert]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,decorations.pathmorphing}
\newcommand{\thinkB}[1] {%
\begin{tikzpicture}%
\node [rectangle, draw, decoration={mirror, bumps, segment length=0.495cm, path has corners=true}, decorate, align=left, minimum width=2.5cm, minimum height=2.5cm] {#1};%
\end{tikzpicture}%
}
\begin{document}
\thinkB{$3+5=8$\\$8+1=9$\\$9+6=15$}
\end{document}
上一个答案
改变aspect=1
。
代码
\documentclass[convert]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,decorations.pathmorphing}
\newcommand{\thinkA}[1]{%
\begin{tikzpicture}%
\node[cloud, draw, align=left, cloud puffs=20,cloud puff arc=110, aspect=1, inner sep=0mm]{#1};%
\end{tikzpicture}%
}%
\begin{document}
\thinkA{$3+5=8$\\$8+1=9$\\$9+6=15$}
\end{document}