7

I would like to define horizontal shading, that could be stretched depending on needs. What I did to far is this

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\pgfdeclarehorizontalshading{pressure}{1cm}{color(0cm)=(black!30); color(1cm)=(black!50); color(3cm)=(black!10); color(4cm)=(black!30)}
\shade[shading=pressure] (0,0) rectangle (10cm,2cm);
\end{tikzpicture}

\end{document}

but it just does not work. Why?

EDIT: This is not about fancy background. I have to present the changes in pressure in the air and I do not have exact measures of the rectangle. Had I knew exact measures of the rectangle (\leng), I could use 0.25*\leng, 0.75*\leng and \leng

Pygmalion
  • 6,387
  • 4
  • 34
  • 68
  • I think you need to use \pgfuseshading{pressure}. – Peter Grill Dec 18 '14 at 16:13
  • You shading works very well ! Did you read the explanations from pgfmanual (p.1090 of TikZ/PGF v3.0)? There is always some hidden parts in a shading... – Paul Gaborit Dec 18 '14 at 16:30
  • @PaulGaborit I did check the manual. The problem is I want the whole shade to be fully displayed, i.e. middle gray to full gray to light gray and back to middle gray. And it does not. – Pygmalion Dec 18 '14 at 16:39

3 Answers3

9

As described in the manual, the shading is scaled so that the middle 50% fills the path which while useful in many cases (particularly with excessively non-rectangular paths or rotated shadings), is a bit of nuisance in this case.

However, one can exploit the path picture feature, get the size of the path and scale the shading manually. It involves some basic layer shenanigans and no shading rotation is supported (at least in the example below). The default shading is on the left, the path picture shading is on the right:

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{calc}
\newbox\shbox
\tikzset{%
  path picture shading/.style={%
    path picture={%
%
\pgfpointdiff{\pgfpointanchor{path picture bounding box}{south west}}%
  {\pgfpointanchor{path picture bounding box}{north east}}%
\pgfgetlastxy\pathwidth\pathheight%
\pgfinterruptpicture%
   \global\setbox\shbox=\hbox{\pgfuseshading{#1}}%
 \endpgfinterruptpicture%
\pgftransformshift{\pgfpointanchor{path picture bounding box}{center}}%
\pgftransformxscale{\pathwidth/(\wd\shbox)}%
\pgftransformyscale{\pathheight/(\ht\shbox)}% \dp will (should) be 0pt
\pgftext{\box\shbox}%
%
    }
  }
}
\pgfdeclarehorizontalshading{pressure}{25bp}{color(0bp)=(red); color(25bp)=(yellow); color(50bp)=(pink); color(75bp)=(green); color(100bp)=(blue)}


\begin{document}
\begin{tikzpicture}
\node at (3,0) {\tt shading=pressure};
\node at (9,0) {\tt path picture shading=pressure};
\foreach \i in {1,...,6}{
\draw [shading=pressure] (0,\i) rectangle +(\i,1);
\draw [path picture shading=pressure] (7,\i) rectangle +(\i,1);
}
\end{tikzpicture}
\end{document}

enter image description here

Mark Wibrow
  • 70,437
  • Please don't use \tt etc. For LaTeX documents, they were made obsolete by the recent publication of LaTeX 2e. – cfr Dec 18 '16 at 03:12
6

You shading works very well ! There is always some hidden parts in a shading (cf. pgfmanual p.1090 of TikZ/PGF v3.0).

If you want to use the whole shading, you may use \pgfuseshading{pressure} as content of a node using xscale and yscale to resize it (and inner sep=0 to remove unwanted margins).

Edit: Using the calc TikZ library, you may calculate the scaling factors.

enter image description here

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\pgfdeclarehorizontalshading{pressure}{1cm}{
  color(0cm)=(red);
  color(1cm)=(black!50);
  color(2cm)=(yellow!10);
  color(3cm)=(blue)
}
\begin{document}
\begin{tikzpicture}
  \node[inner sep=0,xscale=10/3,yscale=2/1]
  at (0,0) {\pgfuseshading{pressure}};
  \node[inner sep=0,xscale=10/3,yscale=.5/1]
  at (0,2) {\pgfuseshading{pressure}};

  \coordinate (a) at (-2,5);
  \coordinate (b) at (8,6);

  \path let \p1=(a), \p2=(b),
  \p3=({(\x2-\x1)/3cm},{(\y2-\y1)/1cm}),
  \p4=($(\p1)!.5!(\p2)$)
  in node[at=(\p4),inner sep=0,xscale=\x3,yscale=\y3]{\pgfuseshading{pressure}};
\end{tikzpicture}
\end{document}
Paul Gaborit
  • 70,770
  • 10
  • 176
  • 283
  • The problem here is that I have to shade a square between points (a) and (b), so I don't have exact dimensions and don't know the required scaling. – Pygmalion Dec 18 '14 at 21:27
  • @Pygmalion I have edited my answer to show how to calculate the scaling factors. – Paul Gaborit Dec 18 '14 at 22:53
  • Don't forget that any scope-wide node settings/styles would have to be reset, otherwise some undesirable effects might be produced (put execute at begin node=b in the tikzpicture options. It's a stupid example but it illustrates the point). – Mark Wibrow Dec 19 '14 at 06:19
  • @MarkWibrow I don't understand your comment... – Paul Gaborit Dec 19 '14 at 07:15
  • @PaulGaborit try putting [every node/.style={draw=red, line width=.5cm, shape=circle}, execute at begin node=b] as options to the tikzpicture. For a general solution each node with the shading might have to have some kind of "cancelling" style depending on the context in which it was used. – Mark Wibrow Dec 19 '14 at 08:18
  • @MarkWibrow Ok. I understand. But this remark also applies to most TikZ answers on this site. Those that modify every node/.style, or that use execute at begin node as global option, must take the consequences. – Paul Gaborit Dec 19 '14 at 10:22
3

You can always use a beautiful image as a background.

\documentclass{article}
\usepackage{tikz, graphicx}

\begin{document}
\begin{tikzpicture}
\node[inner sep=0pt] (x) at (0,0)
    {\includegraphics[width=.5\textwidth]{bg.jpg}};
\node[inner sep=0pt] (y) at (5,-6)
    {\includegraphics[width=.25\textwidth]{bg.jpg}};
\draw[<->,thick] (x.south east) -- (y.north west)
    node[midway,fill=white] {Backgrounds};
\end{tikzpicture}
\end{document}

Stretch it using the width key.

enter image description here

yannisl
  • 117,160