Как установить ширину узла tikz на основе узла в той же строке

Как установить ширину узла tikz на основе узла в той же строке

Я хочу создать следующую tikzpicture:

введите описание изображения здесь

На данный момент у меня есть следующее:

\documentclass{article}
\usepackage[showframe]{geometry}
\usepackage{tikz}
\usetikzlibrary{positioning,backgrounds}
\begin{document}
\noindent\begin{tikzpicture}[background rectangle/.style={fill=gray!25}, show background rectangle,every node/.style={inner sep=0pt,outer sep=0pt,draw}]

\begin{scope}[local bounding box=scope1]
\path[use as bounding box] (0,0) rectangle (.5\textwidth,0);
\filldraw (0,0) circle (2pt); 
\node [text width=0.5\textwidth, align=left,anchor=north west](n1) {scope 1, node 1};
\node [below = 0pt of n1.south west,anchor=north west] (n2) {scope 1, node 2};
\node [below left = 0pt and 0pt of n2.north east,anchor=north west,align=left,text width=5.1cm] (n3) {scope 1, node 3 that includes longer text to be broken into lines};
\end{scope}

\begin{scope}[shift={(scope1.north east)},anchor=north west]
\node [text width=0.5\textwidth, align=left](n1) {scope 2, node 1};
\node [below = 0pt of n1.south west,anchor=north west] (n2) {scope 2, node 2};
\node [below left = 0pt and 0pt of n2.north east,anchor=north west,align=left,text width=5.1cm] (n3) {scope 2, node 3 which also includes longer text to be broken into lines};
\end{scope}

\end{tikzpicture}
\end{document}

введите описание изображения здесь

Мне нужна помощь по двум вопросам:

  1. Как мне определить ширину узла n3, чтобы общая ширина n2и n3была равна n1(которая равна .5\textwidth)? На данный момент я установил ее на 5,1 см, потому что она выглядит нормально, но если я изменю содержимое узла 2, то размер узла 3 также должен измениться. Как мне использовать ограничивающую рамку, которую я создал для первой области видимости?

  2. Как мне вставить разделитель между двумя областями (например, тот, что нарисован желтым на первой картинке)? Почему ширина двух областей выходит за пределы textwidth? Слева и справа есть серое поле, хотя outer sep=0pt.

решение1

Фоновый прямоугольник имеет отступ (который называется ), поэтому он отображается более серым цветом, чем фактическое содержимое. Используйтеinner frame [xy]septight backgroundчтобы изменить это.
Кроме того, ширина линии (любого пути, не только узлов, независимо от любых внешних разделителей) будет способствовать окончательному ограничивающему прямоугольнику изображения, что также немного сбивает окончательное размещение изображения (и приводит к переполнению hbox).
В вашей исходной настройке вы можете перезаписать горизонтальное измерение ограничивающего прямоугольника, используя trim left=0pt, trim right=\textwidth. В моем коде ниже я использую , ±.5\textwidthпотому что я создаю изображение, центрированное относительно начала координат.

Для создания узлов, имеющих размеры, соответствующие другим узлам, используется библиотека fit, которая устанавливает ширину/высоту/глубину текста, что плохо, если вы хотите, чтобы узлы действительно имели текст.

Моя ext.positioning-plusбиблиотека делает похожие вещи, используя fitбиблиотеку , но контролирует размер нового узла с помощью minimum widthи minimum height, что лучше для размещения текста в узле, но требует некоторой работы для текста, который длиннее, чем тот, который может поместиться в узле.

Я использую здесь очень простой text width betweenключ, который используетcalc библиотеку для измерения расстояния между двумя произвольными точками вИксизмерение и использует его для установки text widthузла. Нам нужно вычестьinner xsep дважды (чтобы конечный узел фактически покрывал областьсвнутренний xsep). Это в основном способ установитьфиксированная ширинавместо минимальной ширины. (Для других форм коэффициент 2 отличается.)

Для синхронизации размеров узлов я могу предложитьext.node-familiesбиблиотекамоегоtikz-extупаковка.

Каждый узел, который node family={height=row1}установил, разделяет тот же minimum height. Это выровняет тексты в каждом узле вертикально по центру.

Оба синих узла, а также желтый разделитель (тоже узел) будут охватывать одно и то же вертикальное пространство.

Код (Семейство узлов)

\documentclass{article}
\usepackage[showframe]{geometry}
\usepackage{tikz, amsmath}
\makeatletter % https://tex.stackexchange.com/a/656319/16595
\tikzset{parse let/.code={\def\tikz@cc@stop@let in{}\tikz@let@command et #1in}}
\makeatother
\usetikzlibrary{calc, positioning, backgrounds, ext.node-families}
\tikzset{
  text width between/.style args={#1 and #2}{
    parse let={\p@=($(#2)-(#1)$)},
    text width/.expanded={abs(\x@)-2*(\noexpand\pgfkeysvalueof{/pgf/inner xsep}}}}
\begin{document}
\noindent
\begin{tikzpicture}[
  background rectangle/.style={fill=gray!25},
  show background rectangle, tight background,
  trim left=-.5\textwidth, trim right=.5\textwidth,
  every node/.style={outer sep=+0pt},
  Yellow/.style={fill=yellow, node family={height=row1}},
  Blue/.style  ={fill=blue,   node family={height=row1}, text=white},
  Red/.style   ={fill=red,   align=center},
  Green/.style ={fill=green, align=center},
  node distance=+0pt
]
\node[Yellow] (sep) {};
\node[Blue, left=of sep,  text width between={-.5\textwidth,0 and sep.west}]
  (Blue-left) {scope 1, node 1 $\displaystyle e^x = \cfrac{1}{1 - \cfrac{x}{1 + x -
                               \cfrac{\frac{1}{2}x}{1 + \frac{1}{2}x - \ddots}}}$};
\node[Blue, right=of sep, text width between={ .5\textwidth,0 and sep.east}]
  (Blue-right) {scope 1, node 1};

\node[Red, below right=of Blue-left.south  west] (Red-left)  {scope 1,\\ node 2};
\node[Red, below right=of Blue-right.south west] (Red-right) {scope 1,\\ node 2};

\node[Green, below left=of Blue-left.south east,
     text width between=Red-left.east and Blue-left.east]
  (Red-left) {scope 1, node 3 that includes longer text to be broken into lines};

\node[Green, below left=of Blue-right.south east,
     text width between=Red-right.east and Blue-right.east]
  (Red-left) {scope 2, node 3 which also includes longer text to be broken into lines
    \dots\ and here's an extra linre};
\end{tikzpicture}
\end{document}

Код (без семейства узлов)

\documentclass{article}
\usepackage[showframe]{geometry}
\usepackage{tikz, amsmath}
\makeatletter % https://tex.stackexchange.com/a/656319/16595
\tikzset{parse let/.code={\def\tikz@cc@stop@let in{}\tikz@let@command et #1in}}
\makeatother
\usetikzlibrary{calc, positioning, backgrounds}
\tikzset{
  text width between/.style args={#1 and #2}{
    parse let={\p@=($(#2)-(#1)$)},
    text width/.expanded={abs(\x@)-2*(\noexpand\pgfkeysvalueof{/pgf/inner xsep}}},
  minimum height of three nodes/.style n args={3}{
    parse let={\p1=($(#1.north)-(#1.south)$),
               \p2=($(#2.north)-(#2.south)$),
               \p3=($(#3.north)-(#3.south)$),
               \n@={max(\y1,\y2,\y3)}},
    minimum height/.expanded={\n@}}}
\DeclareDocumentCommand{\tikzthreenodessameheight}{O{} m O{} m O{} m}{
  \node[#1,alias=@1,overlay,path only,outer ysep=+0pt]{\phantom{#2}};
  \node[#3,alias=@2,overlay,path only,outer ysep=+0pt]{\phantom{#4}};
  \node[#5,alias=@3,overlay,path only,outer ysep=+0pt]{\phantom{#6}};
  \node[#1,minimum height of three nodes={@1}{@2}{@3}] {#2};
  \node[#3,minimum height of three nodes={@1}{@2}{@3}] {#4};
  \node[#5,minimum height of three nodes={@1}{@2}{@3}] {#6};}
\begin{document}
\noindent
\begin{tikzpicture}[
  background rectangle/.style={fill=gray!25},
  show background rectangle, tight background,
  trim left=-.5\textwidth, trim right=.5\textwidth,
  every node/.style={outer sep=+0pt},
  Yellow/.style={fill=yellow},
  Blue/.style  ={fill=blue,   text=white},
  Red/.style   ={fill=red,   align=center},
  Green/.style ={fill=green, align=center},
  node distance=+0pt
]
\tikzthreenodessameheight
  [Yellow, name=sep]{}
  [Blue, left=of sep, name=Blue-left,
   text width between={-.5\textwidth,0 and sep.west}]
  {scope 1, node 1 $\displaystyle e^x = \cfrac{1}{1 - \cfrac{x}{1 + x -
                          \cfrac{\frac{1}{2}x}{1 + \frac{1}{2}x - \ddots}}}$}
  [Blue, right=of sep, text width between={ .5\textwidth,0 and sep.east}, name=Blue-right]
  {scope 1, node 1};

\node[Red, below right=of Blue-left.south  west] (Red-left)  {scope 1,\\ node 2};
\node[Red, below right=of Blue-right.south west] (Red-right) {scope 1,\\ node 2};

\node[Green, below left=of Blue-left.south east,
     text width between=Red-left.east and Blue-left.east]
  (Red-left) {scope 1, node 3 that includes longer text to be broken into lines};

\node[Green, below left=of Blue-right.south east,
     text width between=Red-right.east and Blue-right.east]
  (Red-left) {scope 2, node 3 which also includes longer text to be broken into lines
    \dots\ and here's an extra linre};
\end{tikzpicture}
\end{document}

Выход

введите описание изображения здесь

решение2

При использовании растра tcbraster(или tcbitemize) fromtcolorbox \texwidth) по умолчанию каждый столбец растра имеет одинаковую ширину, но их также можно настроить вручную., we can leave the package to do all the work for us. Theuse

\documentclass{article}
\usepackage[showframe]{geometry}
\usepackage[most]{tcolorbox}

\begin{document}

\begin{tcbitemize}[raster every box/.style={sharp corners,  
    fontupper=\sffamily, colupper=white, boxrule=0pt, halign=center},
    raster left skip=0pt, raster right skip=0pt, 
    raster before skip=0pt, raster row skip=0pt, 
    raster after skip=0pt, raster valign=top]
    \tcbitem[colback=blue!90!black] scope 1, node 1
    \tcbitem[colback=blue!90!black] scope 2, node 1
    \tcbitem[blankest, raster column skip=0pt]
        \begin{tcbitemize}[raster force size=false]
            \tcbitem[colback=red!90!black, width=.4\linewidth] scope 1, node 2
            \tcbitem[colback=green!90!black, width=.6\linewidth] scope 1, node 3 that includes longer text to be broken into lines
        \end{tcbitemize}
    \tcbitem[blankest, raster column skip=0pt]
        \begin{tcbitemize}[raster force size=false]
            \tcbitem[colback=red!90!black, width=.4\linewidth] scope 2, node 2
            \tcbitem[colback=green!90!black, width=.6\linewidth] scope 2, node 3 which also includes longer text to be broken into lines
        \end{tcbitemize}
\end{tcbitemize}
\end{document}

введите описание изображения здесь

решение3

введите описание изображения здесь

Я старался придерживаться вашего исходного кода. Но есть одна проблема, которую не учли: что произойдет, если высота правого верхнего узла больше высоты левого верхнего узла. Решением может быть обратная конструкция и верхний правый узел в качестве опорного.

Код

\documentclass{article}
\usepackage[showframe]{geometry}
\usepackage{lipsum}
\usepackage{tikz}
\usetikzlibrary{calc, positioning}

\begin{document}

\lipsum[1]
\bigskip

\tikzset{%
  T/.style={blue!50!black, fill=blue!50!black, text=white,
    minimum width=0.48\textwidth, text width=0.48\textwidth-1ex
  },
  BW/.style={green!50!black, fill=green!70!black, text=black,
    minimum width=0.17\textwidth, text width=0.17\textwidth-1ex
  },
  BE/.style={red!75!black, fill=red!95!black, text=black,
    minimum width=0.30\textwidth, text width=0.30\textwidth-1ex,
  }
}
\noindent\begin{tikzpicture}[%
  every node/.style={draw, inner sep=1ex, outer sep=0pt, align=center,
  minimum height=7ex}
  ]
  \node[T, anchor=north west] at (0, 0)
  (nTW) {\bfseries \lipsum[2]};
  \node[BW, below=0pt of nTW.south west, anchor=north west]
  (n2) {scope 1, node 2};
  \node[BE, below left=0pt and 0pt of n2.north east, anchor=north west]
  (n3) {scope 1, node 3 that includes longer text to be broken into lines};

  \path ($(nTW.south) -(nTW.north)$);
  \pgfgetlastxy{\newW}{\newH}

  \node[T, right=.02\textwidth of nTW.north east,
  anchor=north west, minimum height={-\newH}]
  (nTE) {\bfseries scope 2, node 1};
  \node[BW, below=0pt of nTE.south west, anchor=north west]
  (n2E) {scope 2, node 2};
  \node[BE, below left=0pt and 0pt of n2E.north east, anchor=north west]
  (n3E) {scope 2, node 3 that includes longer text to be broken
    into lines; can be longer than the West corresponding node};

  \fill[yellow!90!red] (nTW.north east) rectangle (nTE.south west);
\end{tikzpicture}
\end{document}

решение4

Альтернативное предложение. Мой код менее техничен (но, возможно, и менее элегантен?).

Вы можете настроить ширину желтого разделителя ( \yellowGapв моем коде) и процент ширины узла 1 ( percentAmountцелое число от 0 до 100, но лучше не выбирать значение слишком близкое к 0 или 100, чтобы избежать очень узких столбцов), чтобы получить ширину узла 2.

Наконец, вы можете отрегулировать длину внутреннего разделителя в узлах \innerXSep.

\documentclass[a4paper,10pt]{article}
\usepackage[showframe]{geometry}
\usepackage[x11names]{xcolor}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{calc}

\newlength{\yellowGap}
\setlength{\yellowGap}{3mm}
\newcounter{percentAmount}
\setcounter{percentAmount}{40}% =40% of the width of the first node. Value needs to be integer
\newlength{\innerXSep}
\setlength{\innerXSep}{.3333em}% default value

\newlength{\mainNodeWidth}
\setlength{\mainNodeWidth}{(\textwidth-\yellowGap)/2}
\newlength{\secondNodeWidth}
\setlength{\secondNodeWidth}{\mainNodeWidth*\value{percentAmount}/100}
\newlength{\thirdNodeWidth}
\setlength{\thirdNodeWidth}{\mainNodeWidth-\secondNodeWidth}

\begin{document}

\noindent\begin{tikzpicture}[outer sep=0pt,inner xsep=\innerXSep,text=white]
    \node[text width=\mainNodeWidth-2\innerXSep,fill=DodgerBlue3,align=center]  (mainLeft) {Scope 1, Node 1};
    \node[text width=\secondNodeWidth-2\innerXSep,fill=Firebrick2,align=center,anchor=north west] (secondLeft) at (mainLeft.south west) {Scope 1,\\Node 2};
    \node[text width=\thirdNodeWidth-2\innerXSep,fill=Green3,align=center,anchor=north west] (thirdLeft) at (secondLeft.north east) {Scope 1, Node 3\\ that includes longer text to be broken into lines};
    \fill[DarkGoldenrod1] (mainLeft.north east) rectangle ($(mainLeft.south east)+(\yellowGap,0)$);
    \node[text width=\mainNodeWidth-2\innerXSep,fill=DodgerBlue3,align=center,anchor=north west]    (mainRight) at ($(mainLeft.north east)+(\yellowGap,0)$) {Scope 2, Node 1};
    \node[text width=\secondNodeWidth-2\innerXSep,fill=Firebrick2,align=center,anchor=north west] (secondRight) at (mainRight.south west) {Scope 2,\\Node 2};
    \node[text width=\thirdNodeWidth-2\innerXSep,fill=Green3,align=center,anchor=north west] at (secondRight.north east) {Scope 2, Node 3\\ which also includes longer text to be broken into lines};
\end{tikzpicture}
\end{document}

введите описание изображения здесь

Связанный контент