Я хотел бы изменить приведенный ниже код, чтобы использовать метод соединения цепочек вместо помещения узла между ними. Есть идеи, как это реализовать?
\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.arrows, calc,chains}
\tikzset{
myarr/.style args={#1 -- #2}{
insert path={let \p1=($(#1)-(#2)$) in},
single arrow, draw=black, minimum width=20mm, minimum height={veclen(\x1,\y1)},
inner sep=0mm, single arrow head extend=1pt,
},
every join/.style={->},
}
\begin{document}
\begin{tikzpicture}[start chain=going right,node distance= 2cm and 2cm]
\def\data{
A,
B,
C,
D%
}
\foreach \p [count=\i from 1] in \data {
\node[draw,on chain,join,minimum width=2cm,minimum height=4cm] (P\i) {\p};
}
% move below logic to use join method
\path (P1) -- (P2) node[midway,->,myarr={P1.east -- P2.west},single arrow] {};
\path (P2) -- (P3) node[midway,->,myarr={P2.east -- P3.west},single arrow] {};
\path (P3) -- (P4) node[midway,->,myarr={P3.east -- P4.west},single arrow] {};
\end{tikzpicture}
\end{document}
решение1
Вы можете разместить узел через соединение в цепочке, просто настроив , to path
который делает именно это: размещает узел.
Внутри to path
у вас есть доступ к \tikztostart
и \tikztotarget
– а также к , \tikztonodes
но мы проигнорируем это здесь… или вам нужен текст где-то?
Затем разницу можно вычислить, как и прежде veclen
, а также ее направление/угол с помощью atan2
. Затем результаты можно использовать с , node
как и прежде, который теперь является единственным (визуальным) выводом to path
.
Все это сделано в myarr with anchors
стиле:
\tikzset{
myarr with anchors/.style 2 args={
to path={
let \p0=($(\tikztotarget.#2)-(\tikztostart.#1)$) in
node[myarr node,
minimum height={veclen(\x0,\y0)},
shape border rotate={atan2(\y0,\x0)}] at (\tikztostart.#1) {}}}}
Для простых цепей это так же просто, как
\tikz[
start chain=going right, node distance=2cm and 2cm,
every join/.style={myarr with anchors={east}{west}},
every on chain/.append style={draw, minimum width=2cm, minimum height=4cm}]
\node foreach \t in {A, ..., D} [on chain, join]{\t};
Мне больше нравятся автоматические подходы, при которых система сама находит точки на границе.
Для этого я предоставляю myarr
стиль, который использует edge
для поиска точек на границе, а затем использует их в тех же вычислениях, что и раньше.
При желании он также принимает два аргумента, которые либо пусты (автоматический подход или не узел), либо содержат спецификацию якоря (с .
).
Ссылка:Можно ли использовать `let` (из `TikZ`) внутри определения стиля узла?.
Код
\documentclass[tikz]{standalone}
\usetikzlibrary{shapes.arrows, calc, chains}
\tikzset{
myarr node/.style={
shape=single arrow, draw=black, minimum width=20mm, anchor=tail,
shape border uses incircle, single arrow head extend=+1pt,
inner sep=+0pt, outer sep=+0pt},
%
myarr with anchors/.style 2 args={
to path={
let \p0=($(\tikztotarget.#2)-(\tikztostart.#1)$) in
node[myarr node,
minimum height={veclen(\x0,\y0)},
shape border rotate={atan2(\y0,\x0)}] at (\tikztostart.#1) {}}},
%
myarr/.default={}{},
myarr/.style 2 args={
to path={
\expanded{
(\tikztostart#1) edge[path only, overlay, line to]
coordinate[at start] (@start)
coordinate[at end] (@end) (\tikztotarget#2)}
let \p0=($(@end)-(@start)$) in
node[myarr node,
minimum height={veclen(\x0,\y0)},
shape border rotate={atan2(\y0,\x0)}] at (@start) {}}}}
\begin{document}
\pgfmathsetseed{872607}
\tikz[
start chain=going right, node distance=2cm and 2cm,
every join/.style={myarr with anchors={east}{west}},
every on chain/.append style={draw, minimum width=2cm, minimum height=4cm}]
\node foreach \t in {A, ..., D} [on chain, join]{\t};
\tikz[
start chain=going right, node distance=2cm and 2cm,
every join/.style=myarr,
every on chain/.append style={draw, minimum width=2cm, minimum height=4cm}]
\node foreach \t in {A, ..., D} [on chain, join]{\t};
\tikz[
start chain=going above right, node distance=.4cm and 2cm,
every join/.style=myarr,
every on chain/.append style={draw, circle, minimum size=2cm}]
\node foreach \t in {A, ..., D} [on chain, join, shift={(3*rand, 3*rand)}]{\t};
\tikz[
start chain=going above right, node distance=.4cm and 2cm,
every join/.style={myarr={.north east}{.south west}},
every on chain/.append style={draw, minimum width=2cm, minimum height=1cm}]
\node foreach \t in {A, ..., D} [on chain, join]{\t};
\end{document}
Выход
решение2
Я не совсем понимаю, что вы пытаетесь сделать, но, возможно, вы хотите что-то вроде следующего?
\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.arrows, calc,chains}
\tikzset{
myarr/.style args={#1 -- #2}{
insert path={let \p1=($(#1)-(#2)$) in},
single arrow, draw=black, minimum width=20mm, minimum height={veclen(\x1,\y1)},
inner sep=0mm, single arrow head extend=1pt,
},
my arr/.style={
insert path={let \p1=(20mm,0pt) in},
single arrow, draw=black, minimum width=20mm, minimum height={veclen(\x1,\y1)},
inner sep=0mm, single arrow head extend=1pt,
},
}
\begin{document}
\begin{tikzpicture}[start chain=going right,node distance=2cm and 0cm]
\def\data{
A,
B,
C,
D%
}
\foreach \p [count=\i from 1,remember=\i as \ilast] in \data {
\edef\tempa{1}\edef\tempb{\i}%
\ifx\tempa\tempb\relax
\else \node (A-\ilast-\i) [draw,on chain,my arr] {};
\fi
\node[draw,on chain,join,minimum width=2cm,minimum height=4cm] (P\i) {\p};
}
\end{tikzpicture}
\end{document}
решение3
Небольшая вариация хорошего ответа @cfr.
- Макрос join предназначен (судя по всему) только для рисования стрелок (любого вида) между узлами, но он не способен вставлять узлы между ними.
- Из-за вышесказанного вы не можете вставлять узлы с
single arrow
формой между основными узлами в цепочке с помощью макросаjoin
. Они могут быть вставлены только как обычные узлы в цепочке. - Этот
single arrow
узел может хорошо вписаться между двумя основными узлами в цепочке, вам необходимо соответствующим образом определить его стиль (см. MWE ниже). - МВЭ:
\documentclass[margin=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc, chains,
shapes.arrows}
\begin{document}
\begin{tikzpicture}[
node distance = 0mm,
start chain = going right,
SA/.style = {% single arrow
single arrow, single arrow head extend=3mm,
draw, minimum width=20mm, minimum height=20mm,
inner sep=0mm,
node contents=\vphantom{A},
on chain
},
N/.style = {draw, semithick, on chain,
minimum width=2cm, minimum height=4cm}
]
\def\data{A, B, C, D}
\foreach \i [count=\j] in \data
{
\node[N] {\i};
\ifnum\j<4
\node[SA];
\fi
}
\end{tikzpicture}
\end{document}