34

Imagine I want to draw a filled shape behind something already typeset in the page. The usual approach is to define a \tikzmark command which simply remembers a coordinate using remember picture and overlay options, and later use that coordinate to draw tikz stuff using transparency.

For example:

\documentclass{article}
\usepackage{tikz}
\usepackage{lipsum}
\usetikzlibrary{backgrounds}
\def\tikzmark#1{\tikz[remember picture,overlay]\coordinate(#1);}
\begin{document}
\noindent\tikzmark{A}\lipsum[11]

\begin{tikzpicture}[remember picture, overlay]
  \fill[yellow, opacity=.3] (A) circle(2em);
\end{tikzpicture}
\end{document}

Which produces:

Result

But now assume that I want a solid yellow. The obvious idea is to use pgfonlayer and draw it on the background. However, the concept of background/foreground apparently only exists inside tikz environments. Since the main text in the page was already typeset, it is behind tikz's background:

\documentclass{article}
\usepackage{tikz}
\usepackage{lipsum}
\usetikzlibrary{backgrounds}
\def\tikzmark#1{\tikz[remember picture,overlay]\coordinate(#1);}
\begin{document}

\noindent\tikzmark{A}\lipsum[11]

\begin{tikzpicture}[remember picture, overlay]
\begin{pgfonlayer}{background}
  \fill[yellow] (A) circle(2em);
\end{pgfonlayer}
\end{tikzpicture}
\end{document}

Bad

Can it be done?

8
  • 3
    The usual approach to putting things behind the page is to add the picture to the page head then it will be typeset first Dec 12, 2012 at 11:32
  • 2
    @DavidCarlisle Thank you. But that approach is incompatible with \tikzmark trick. You can't use in the header the absolute coordinates of a node which will be defined later via \tikzmark, because the node is unknown yet.
    – JLDiaz
    Dec 12, 2012 at 11:36
  • You could use \pdfsavepos and store the position in the aux-file. The marginnote package uses this method to place the notes. And the zref package has a module savepos which you could use. Dec 12, 2012 at 11:47
  • @JLDiaz Yes you can. Use the new improved tikzmark. Functionally, this is the same as the suggestions that Ulrike makes but it's designed to be used with TikZ so is probably the better choice if you want to use TikZ to do the drawing. Dec 12, 2012 at 12:00
  • Doesn't tikzmark just use pdfsavemark internally, I'd assumed it does (but don't really know anything about tikz) also the page header is executed after the page contents (but placed earlier in the output when the output routine assembles the page, so I don't see why it should not work) Dec 12, 2012 at 12:02

1 Answer 1

33

Thanks to Andrew Stacey for pointing me to the new improved tikzmkark. I was not aware of it. This version of \tikzmark allows for using the defined coordinates before the point of its definition. Using \tikzmark{foo} a new coordinate named (pic cs:foo) is available and can be used anywhere in the page.

Using the new \tikzmark, taken from the preamble of https://tex.stackexchange.com/a/50054/12571 the problem can be solved like this:

\begin{document}
\noindent\begin{tikzpicture}[remember picture, overlay]
  \fill[yellow] (pic cs:A) circle(2em);
\end{tikzpicture}%
\tikzmark{A}\lipsum[11]
\end{document}

With the desired result:

Good

Appendix

For completeness, the code of the whole document, including the preamble in which the new \tikzmark appears, is included here:

\documentclass{article}
\usepackage{tikz}
\usepackage{lipsum}
\makeatletter
\tikzset{%
  remember picture with id/.style={%
    remember picture,
    overlay,
    save picture id=#1,
  },
  save picture id/.code={%
    \edef\pgf@temp{#1}%
    \immediate\write\pgfutil@auxout{%
      \noexpand\savepointas{\pgf@temp}{\pgfpictureid}}%
  },
  if picture id/.code args={#1#2#3}{%
    \@ifundefined{save@pt@#1}{%
      \pgfkeysalso{#3}%
    }{
      \pgfkeysalso{#2}%
    }
  }
}

\def\savepointas#1#2{%
  \expandafter\gdef\csname save@pt@#1\endcsname{#2}%
}
\def\tmk@labeldef#1,#2\@nil{%
  \def\tmk@label{#1}%
  \def\tmk@def{#2}%
}

\tikzdeclarecoordinatesystem{pic}{%
  \pgfutil@in@,{#1}%
  \ifpgfutil@in@%
    \tmk@labeldef#1\@nil
  \else
    \tmk@labeldef#1,(0pt,0pt)\@nil
  \fi
  \@ifundefined{save@pt@\tmk@label}{%
    \tikz@scan@one@point\pgfutil@firstofone\tmk@def
  }{%
  \pgfsys@getposition{\csname save@pt@\tmk@label\endcsname}\save@orig@pic%
  \pgfsys@getposition{\pgfpictureid}\save@this@pic%
  \pgf@process{\pgfpointorigin\save@this@pic}%
  \pgf@xa=\pgf@x
  \pgf@ya=\pgf@y
  \pgf@process{\pgfpointorigin\save@orig@pic}%
  \advance\pgf@x by -\pgf@xa
  \advance\pgf@y by -\pgf@ya
  }%
}
\newcommand\tikzmark[2][]{%
\tikz[remember picture with id=#2] #1;}
\makeatother

\begin{document}
\noindent\begin{tikzpicture}[remember picture, overlay]
  \fill[yellow] (pic cs:A) circle(2em);
\end{tikzpicture}%
\tikzmark{A}\lipsum[11]
\end{document}

NOTE: Anyone inclined to vote for this self-answer, should vote for https://tex.stackexchange.com/a/50054/12571 instead :-)


Update

As noted by Ulrike Fischer in a comment, putting the tikzpicture which draws the background too close to the decorated paragraph can have side effects on previous paragraph:

\begin{document}
\lipsum[5] % <------ Added a previous paragraph
\medskip
\noindent\begin{tikzpicture}[remember picture, overlay]
  \fill[yellow] (pic cs:A) circle(2em);
\end{tikzpicture}%
\tikzmark{A}\lipsum[11]
\end{document}

Bad :-(

However, separating too much the tikzpicture from the \tikzmark we risk ending with those in separate pages, and thus the background will appear in the wrong page.

The best solution is then to use some solution which "stores" the required picture and "activates" its output as background at same time that we place the \tikzmark, as for example the solution proposed by Ulrike in the comment.

I explored another option, which is to use the wonderful background package by Gonzalo Medina (thanks to Andrew for suggesting it in a chat!). Using this package we set-up the background picture anywhere in the document, and "activate" it with \BgThispage at same time that we place the \tikzmark. Using this approach there is no need for the new improved tikzmark and instead the old minimalistic tikzmark can be used.

It is important also to give appropiate values to options placement and scale, in order to get the drawing at the appropiate coordinates. There is the MWE:

\documentclass{article}
\usepackage{tikz}
\usepackage[pages=some]{background}
\usepackage{lipsum}
\def\tikzmark#1{\tikz[remember picture, overlay]\coordinate(#1);}

\begin{document}
\backgroundsetup{scale=1,placement=bottom,contents={%
\noindent\begin{tikzpicture}[remember picture,overlay]
  \fill[yellow] (A) circle(2em);
\end{tikzpicture}%
}}

\lipsum[5]
\medskip
\noindent\tikzmark{A}\BgThispage\lipsum[11]
\end{document}

And after three (why three?) compilations I get:

Good!

3
  • 4
    It doesn't work if the \tikzmark is on another page than the tikzpicture, and if you keep the tikzpicture near the \tikzmark the picture can overwrite text above if it isn't at the start of the page. So you probably should define a special page style, put the picture in the header and use \thispagestyle{special}\tikzmark{A}. Dec 12, 2012 at 12:42
  • 3
    Sadly I'm unable to vote for the linked answer so I'll vote for this one instead. Dec 12, 2012 at 13:41
  • 1
    You could also use the tikzmark library (browse the code at launchpad.net): this will simplify your life in the appendix (besides providing other useful extras). Dec 12, 2012 at 18:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .