Cómo establecer el ancho del nodo tikz en función de un nodo en la misma línea

Cómo establecer el ancho del nodo tikz en función de un nodo en la misma línea

Quiero crear la siguiente imagen tikz:

ingrese la descripción de la imagen aquí

Lo que tengo en este momento es esto:

\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}

ingrese la descripción de la imagen aquí

Necesito ayuda con dos cosas:

  1. ¿Cómo puedo definir el ancho del nodo n3para que el ancho total de n2y n3sea el de n1(que es .5\textwidth)? Por el momento lo configuré en 5,1 cm porque se ve bien, pero si cambio el contenido del nodo 2, la dimensión del nodo 3 también debería cambiar. ¿Cómo puedo utilizar el cuadro delimitador que creé para el primer alcance?

  2. ¿Cómo puedo insertar un separador entre los dos visores (como el dibujado en amarillo en la primera foto)? ¿Por qué el ancho de los dos ámbitos se extiende más allá textwidth? Aunque hay un margen gris a la izquierda y a la derecha outer sep=0pt.

Respuesta1

El rectángulo de fondo tiene un relleno (que se llama ), por lo que se muestra más en gris que el contenido real. Usarinner frame [xy]septight backgroundpara cambiar esto.
Además, el ancho de la línea (de cualquier camino, no solo de los nodos, independientemente de los espacios exteriores) contribuirá al cuadro delimitador final de la imagen, lo que también altera un poco la ubicación final de la imagen (y conducirá a un hbox excesivo).
En su configuración original, puede sobrescribir la medida horizontal del cuadro delimitador usando trim left=0pt, trim right=\textwidth. En mi código a continuación, lo estoy usando ±.5\textwidthporque creo la imagen centrada en el origen.

Para crear nodos que tienen tamaños relacionados con otros nodos, son la fitbiblioteca que funciona estableciendo el ancho/alto/profundidad del texto, lo cual es malo si desea que los nodos realmente tengan texto.

Mi ext.positioning-plusbiblioteca hace cosas similares usando la fitbiblioteca, pero controla el tamaño del nuevo nodo usando minimum widthy minimum heightcuál es mejor para tener texto en el nodo, pero necesita un poco de trabajo para el texto que es más largo de lo que cabe en el nodo.

Estoy usando aquí una text width betweenclave muy básica que usa la calcbiblioteca para medir la distancia entre dos puntos arbitrarios en elXdimensión y la utiliza para establecer la text widthdel nodo. Necesitamos restar inner xsepdos veces aquí (para que el nodo final realmente cubra el áreaconxsep interior). Esta es básicamente una manera de establecer unancho fijoen lugar de un ancho mínimo. (El factor 2 es diferente para otras formas).

Para sincronizar tamaños de nodos, puedo ofrecer elext.node-familiesbibliotecade mitikz-extpaquete.

Cada nodo que se ha node family={height=row1}configurado comparte lo mismo minimum height. Esto alineará los textos en cada nodo verticalmente centrados.

Tanto los nodos azules como el separador amarillo (también un nodo) abarcarán el mismo espacio vertical.

Código (familia de nodos)

\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}

Código (sin familia de nodos)

\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}

Producción

ingrese la descripción de la imagen aquí

Respuesta2

Con un ráster tcbraster(o tcbitemize) fromtcolorbox \texwidth` de forma predeterminada, cada columna ráster tiene el mismo ancho, pero también es posible ajustarlas manualmente., 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}

ingrese la descripción de la imagen aquí

Respuesta3

ingrese la descripción de la imagen aquí

Intenté mantenerme cerca de tu código inicial. Sin embargo, hay una cuestión que no se considera: ¿qué sucede si la altura del nodo superior derecho es mayor que la altura del nodo superior izquierdo? Una solución podría ser revertir la construcción y que el nodo superior derecho sea la referencia.

El código

\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}

Respuesta4

Sugerencia alternativa. Mi código es menos técnico (¿pero quizás también menos elegante?).

Puede ajustar el ancho del separador amarillo ( \yellowGapen mi código) y el porcentaje del ancho del nodo 1 ( percentAmount, un número entero entre 0 y 100, pero es mejor no elegir un valor demasiado cercano a 0 o 100 para evitar columnas estrechas), para obtener el ancho del nodo 2.

Por último, puede ajustar la longitud del espacio interior en los nodos \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}

ingrese la descripción de la imagen aquí

información relacionada