Erstellen des Aussehens von Notizbuchpapier in einer Farbbox; Probleme beim Zeichnen der richtigen Anzahl von Linien

Erstellen des Aussehens von Notizbuchpapier in einer Farbbox; Probleme beim Zeichnen der richtigen Anzahl von Linien

Ich versuche, in einer Umgebung etwas zu erstellen, das wie ein Ausschnitt aus einem Notizbuch aussieht, tcolorboxindem ich horizontale und eine vertikale Linie zeichne. Mein Problem ist, dass ich nicht weiß, wie ich die Obergrenze der Zeilenanzahl festlegen soll, es sei denn, ich codiere sie fest. Dies führt zu einem Problem, wenn das Farbfeld über eine Seite umbricht und die Felder unterschiedliche Höhen haben. Die Linien werden vom unteren Rand des Felds gezeichnet. Wenn das Feld zwei unterschiedliche Längen hat, ist es schwierig, die Linien so aussehen zu lassen, als wären sie gleichmäßig verteilt und von oben gezeichnet worden.

Wie kann ich die Höhe der Farbbox ermitteln? Ich habe es versucht\tcbTexthöheaber das für die vertikale Linie zu verwenden, funktioniert nicht einmal. Außerdem wüsste ich nicht, wie ich die Schleife mit Ereignisunterteilungen schreiben soll. Am liebsten hätte ich Linien, die die Größe des Zeilenabstands des Dokuments haben, aber das ist nicht erforderlich. Nachdem ich die Höhe ermittelt habe, müsste die Linienzeichnung oben in der Box beginnen und nicht unten.

\documentclass[letterpaper, 10pt]{article}

\usepackage[skins, raster, breakable]{tcolorbox}
\usepackage{tikz}
\usetikzlibrary{decorations,decorations.markings,optics}
\usepackage[english]{babel}
\usepackage{blindtext}

\begin{document}
\pagestyle{empty}

\tikzset{normal lines/.style={gray, very thin}} 

\tcbset{paper/.style={enhanced,colback=green!10,colframe=green!65!black,width=\textwidth,breakable,left=1.3in,
        overlay={
            \begin{tcbclipframe}
              \foreach \y in {0.25, 0.5,...,10.25}
                  \draw[style=normal lines](0,\y in) -- (8.5in, \y in);
              \draw[style=normal lines] (1.25in,0)--(1.25in, 3in);
            \end{tcbclipframe}
        }   
    }   
}
\blindtext[5]
\begin{tcolorbox}[paper]
\blindtext[2]
\end{tcolorbox}

\end{document}

Bildbeschreibung hier eingeben

Antwort1

tcolorboxIch schlage vor, dies mit einem Unterskin von zu tun enhanced(der für zerbrechliche Boxen geeignet ist). Im unten angegebenen Code definieren wir ein Skin namens , paperdas von abgeleitet ist enhanced, und sorgen dafür, dass der tcolorboxStil paperausgeführt wird skin=paper(unter anderem durch Festlegen der gewünschten Rahmen- und Hintergrundfarben). Wir definieren außerdem drei Unterskins paperfirst, papermiddleund , paperlastdie jeweils von enhancedfirst, enhancedmiddleund abgeleitet sind enhancedlast; diese ermöglichen es uns, der Box in allen Fällen das gewünschte Aussehen zu geben (ununterbrochen, oben unterbrochen und unten nicht, unten unterbrochen und oben nicht, oben und unten unterbrochen).

Da das enhancedSkin festlegt /tcb/geometry nodes=true, definiert es Knoten mit den Namen frame, interior, segmentation, und title, die uns den Zugriff auf interessante Punkte der ermöglichen tcolorbox. Hier kann man entweder frameoder verwenden interior, um die Boxhöhe zu berechnen (diese liefern nicht genau dasselbe Ergebnis, da /tcb/leftrule, /tcb/toprule, /tcb/rightruleund /tcb/bottomrulezu den gehören frame, aber nicht zu den interior). In dem paperunten definierten Skin verwenden wir den interiorKnoten, um die Anzahl der zu zeichnenden horizontalen Linien zu berechnen und geeignete Kombinationen von frameund interiorfür die Ausdehnung der vertikalen Linie, je nachdem, ob die Box oben und unten unterbrochen ist. Die Berechnung der Anzahl der zu zeichnenden horizontalen Linien kann beispielsweise mit erfolgen (sie könnte auch mit innerhalb eines Aufrufs \pgfmathtruncatemacroerfolgen ).int()\pgfmathsetmacro

Hinweis: Ich habe eine kleine Änderung an Ihrem normal linesStil vorgenommen. Das line widthist größer, aber die Regeln werden mit gezeichnet opacity=..., wie durch definiert /tcb/paper/rule opacity. Diese Zeichnung erfolgt innerhalb eines , transparency groupdessen Zweck es ist, sicherzustellen, dass Regelüberschreitungen nicht dunkler sind als andere Stellen in den Regeln.

\documentclass{article}
\usepackage{tcolorbox}
\tcbuselibrary{breakable, skins}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{lipsum}

\makeatletter

\tikzset{normal lines/.style={gray, thin}}
\tcbset{paper/left margin/.initial=1.25in,
        paper/line spacing/.initial=1cm,
        paper/rule opacity/.initial=0.4,
        paper/.style={
          skin=paper, colback=green!10, colframe=green!65!black,
          breakable, left=1.3in,
        }
}

\newif\if@paper@broken@top
\newif\if@paper@broken@bottom
\pgfkeys{/tcb/paper/broken top/.is if=@paper@broken@top,
         /tcb/paper/broken bottom/.is if=@paper@broken@bottom
}

% The various parts don't have the same skin when a box is broken. This also
% influences where we want the vertical rule to extend to.
\tcbsubskin{paperfirst}{enhancedfirst}{
  paper/broken top=false, paper/broken bottom=true
}
\tcbsubskin{papermiddle}{enhancedmiddle}{
  paper/broken top=true, paper/broken bottom=true
}
\tcbsubskin{paperlast}{enhancedlast}{
  paper/broken top=true, paper/broken bottom=false
}

\tcbsubskin{paper}{enhanced}{
  skin first=paperfirst, skin middle=papermiddle, skin last=paperlast,
  paper/broken top=false, paper/broken bottom=false,
  overlay={
    \begin{tcbclipinterior}
    \begin{scope}[opacity=\pgfkeysvalueof{/tcb/paper/rule opacity},
                  transparency group]
    % Make sure the vertical rule extends exactly as far as we want, depending
    % on where the box is broken.
    \if@paper@broken@top
      \coordinate (top for vert rule) at (frame.north west);
    \else
      \coordinate (top for vert rule) at (interior.north west);
    \fi
    %
    \if@paper@broken@bottom
      \coordinate (bottom for vert rule) at (frame.south west);
    \else
      \coordinate (bottom for vert rule) at (interior.south west);
    \fi
    %
    \draw[transform canvas={xshift=\pgfkeysvalueof{/tcb/paper/left margin}},
          style=normal lines] (top for vert rule) -- (bottom for vert rule);
    %
    \path let \p1=($(interior.north)-(interior.south)$) in
      \pgfextra{%
        \pgfmathtruncatemacro{\tmp}{veclen(\p1) /
                                    \pgfkeysvalueof{/tcb/paper/line spacing}}%
        \xdef\paperskin@nblines{\tmp}};
    \foreach \i in {1,..., \paperskin@nblines} {
       \pgfmathsetlengthmacro{\paperskin@shift}{
         -\i*\pgfkeysvalueof{/tcb/paper/line spacing}}
       \draw[style=normal lines]
         ([yshift=\paperskin@shift]interior.north west) --
         ([yshift=\paperskin@shift]interior.north east);
    }
    \end{scope}
    \end{tcbclipinterior}
  },
}

\makeatother

\pagestyle{empty}

\begin{document}

\lipsum[1]
\begin{tcolorbox}[paper]
\lipsum[2]
\end{tcolorbox}

\lipsum[3]
\begin{tcolorbox}[paper]
\lipsum[4-5]
\end{tcolorbox}

\end{document}

Bildschirmfoto

Ungebrochene Kiste:

Nahaufnahme der intakten Box

firstTeil der kaputten Box:

Nahaufnahme der kaputten Kiste, erster Teil

lastTeil der kaputten Box:

Nahaufnahme der kaputten Schachtel, letzter Teil

Ein middleTeil (oben gebrochenUndunten) würde auch gut gezeichnet werden, wobei die vertikale Linie beliebig weit verlängert werden kann:

Karton oben und unten gebrochen

Hinweis: der folgende Teil meines Codes:

\tcbsubskin{paper}{enhanced}{
  ...
  overlay={
    ...
    % Make sure the vertical rule extends exactly as far as we want, depending
    % on where the box is broken.
    \if@paper@broken@top
      \coordinate (top for vert rule) at (frame.north west);
    \else
      \coordinate (top for vert rule) at (interior.north west);
    \fi
    %
    \if@paper@broken@bottom
      \coordinate (bottom for vert rule) at (frame.south west);
    \else
      \coordinate (bottom for vert rule) at (interior.south west);
    \fi

kann auch so geschrieben werden:

\newcommand*{\paper@defcoord}[3]{
  \coordinate (#2 for vert rule) at (#1.#3 west);
}

\tcbsubskin{paper}{enhanced}{
  ...
  overlay={
    ...
    % Make sure the vertical rule extends exactly as far as we want, depending
    % on where the box is broken.
    \edef\tmp{\if@paper@broken@top frame\else interior\fi}
    \expandafter\paper@defcoord\expandafter{\tmp}{top}{north}
    \edef\tmp{\if@paper@broken@bottom frame\else interior\fi}
    \expandafter\paper@defcoord\expandafter{\tmp}{bottom}{south}

Die erste Möglichkeit scheint jedoch viel einfacher zu lesen, daher habe ich beschlossen, diese im vollständigen Beispiel beizubehalten.

Antwort2

Anstelle eines handgezeichneten Rasters können Sie ein TikZRaster mit einem großen verwenden xstep. Der folgende Code zeigt eine mögliche Lösung (inspiriert vom Beispiel in der tcolorboxDokumentation, Seite 131). Er löst nicht das Problem mit defekten Kästchen und dem Anpassen der vertikalen Position.

\documentclass{article}
\usepackage[most]{tcolorbox}
\usepackage{lmodern}
\usepackage{blindtext}

\newtcolorbox{notebook}{
    enhanced,
    breakable,
    colback=green!10,
    colframe=green!65!black,
    left=1.3in,
    underlay={%
        \begin{tcbclipinterior}
        \draw[help lines, ystep=\baselineskip, xstep=\linewidth, 
            shift={(interior.north west)}](interior.south west) grid (interior.north east);
        \draw[help lines] ([xshift=1.25in]interior.north west)--
            ([xshift=1.25in]interior.south west);
        \end{tcbclipinterior}}
    }

\begin{document}
\blindtext[1]
\begin{notebook}
\blindtext[3]
\end{notebook}
\end{document}

Bildbeschreibung hier eingeben

verwandte Informationen