[Tex/LaTex] How to shade text in different colors

colorshadingtikz-pgf

I need a single character in two colors. Figuring I could use the shadings library of TikZ, I followed the manual (section 23.4.1, the TikZ example):

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{fadings,shadings}

\begin{document}

\begin{tikzfadingfrompicture}[name=mixed 4]
  \node[text=transparent!0] {$4$};
\end{tikzfadingfrompicture}
\fbox{\tikz[scale=10]\shade[path fading=mixed 4,top color=orange,bottom color=purple] 
  (0,0) rectangle (2ex,2ex);}

\end{document}

enter image description here

However, the result is no good for two reasons:

  1. The surrounding box is far too large; it's not possible to use the
    character in text of formulae.
  2. Only the center part of the shading is visible in the character, rendering it almost invisible.

How can I make the shading apply only to the character, without any surrounding space?

If it's easier, I can also do without the shading but a hard change of colors, that is something like this (gimped):

enter image description here

The angle of the separation line is not that important.

Best Answer

Here is another suggestion:

\documentclass[varwidth,margin=5mm]{standalone} 

\usepackage{tikz}
\usetikzlibrary{fadings}

\newcommand\fadingtext[3][]{%
  \begin{tikzfadingfrompicture}[name=fading letter]
    \node[text=transparent!0,inner xsep=0pt,outer xsep=0pt,#1] {#3};
  \end{tikzfadingfrompicture}%
  \begin{tikzpicture}[baseline=(textnode.base)]
    \node[inner sep=0pt,outer sep=0pt,#1](textnode){\phantom{#3}}; 
    \shade[path fading=fading letter,#2,fit fading=false]
    (textnode.south west) rectangle (textnode.north east);% 
  \end{tikzpicture}% 
}

\begin{document} 
\setlength\fboxsep{0pt}
\fbox{%
  \fadingtext[scale=10]{top color=orange,bottom color=purple}{$4$}%
}
\end{document}

enter image description here

You can use this to color text:

enter image description here

Code:

\documentclass[varwidth,margin=5mm]{standalone} 
\usepackage{tikz}
\usetikzlibrary{fadings}
\newcommand\fadingtext[3][]{%
  \begin{tikzfadingfrompicture}[name=fading letter]
    \node[text=transparent!0,inner xsep=0pt,outer xsep=0pt,#1] {#3};
  \end{tikzfadingfrompicture}%
  \begin{tikzpicture}[baseline=(textnode.base)]
    \node[inner sep=0pt,outer sep=0pt,#1](textnode){\phantom{#3}}; 
    \shade[path fading=fading letter,#2,fit fading=false]
    (textnode.south west) rectangle (textnode.north east);% 
  \end{tikzpicture}% 
}
\usepackage{lipsum}
\begin{document} 
\setlength\fboxsep{0pt}
\fbox{%
  \fadingtext[scale=4]{top color=orange,bottom color=purple}{$4$}%
}

A short test with green and purple: \fadingtext{left color=green,right color=purple}{green to purple} 

\noindent\fadingtext{top color=blue,bottom color=red,middle color=green!80!black}{\parbox[b]{\linewidth}{\strut\lipsum[1]}}
\end{document}

Here is an additional suggestion with a sharp border between the two colors:

enter image description here

Code:

\documentclass[margin=5mm,varwidth]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{lipsum}
\tikzset{
    bctleft/.style={.},
    text left/.style={bctleft/.append style={#1}},
    bctright/.style={.},
    text right/.style={bctright/.append style={#1}},
}
\newcommand\bicolortext[2][]{%
    \tikz[baseline=(n.base),inner sep=0pt,outer xsep=0pt,#1]{
      \node(n){\phantom{#2}};
      \foreach \a/\c in {north west/bctleft,south east/bctright}{
        \begin{scope}
          \clip(n.south west)--(n.\a)--(n.north east)--cycle;
          \node[\c]at(n){#2};
        \end{scope}
      }}}
\begin{document}
\tikzset{text left=orange,text right=purple}
    \setlength\fboxsep{0pt}
    \fbox{%
      \bicolortext[scale=4,transform shape]{$4$}%
    }

    A short test with green and purple: \bicolortext[text left=green, text right=purple]{green to purple} 

    \noindent\bicolortext{\parbox[b]{\linewidth}{\strut\lipsum[1]}}
\end{document}

With TikZ version 3.0 you can also use the transparency group=knockout option. Then it is possible to shade diagonal. But AFAIK only Acrobat Reader shows the correct result, because only this viewer is able to handle transparencies.

enter image description here

Code:

\documentclass[varwidth,margin=5mm]{standalone} 
\usepackage{tikz}
\newcommand\fadingtext[3][]{%
  \begin{tikzpicture}[baseline=(textnode.base)]
    \node[shade,#2,inner sep=0pt,outer sep=0pt,#1,shading angle=45](textnode){\phantom{#3}};
    \begin{scope}[transparency group=knockout]
      \fill[white](textnode.south west)rectangle(textnode.north east);
      \node[opacity=0,inner sep=0pt,outer xsep=0pt,#1]{#3};
    \end{scope}
  \end{tikzpicture}% 
}
\usepackage{lipsum}
\begin{document} 
\setlength\fboxsep{0pt}
\fbox{\fadingtext[scale=10]{top color=orange,bottom color=purple}{$4$}}

A short test with green and purple: \fadingtext{left color=green,right color=purple}{green to purple} 

\noindent\fadingtext{top color=blue,bottom color=red,middle color=green!80!black}{\parbox[b]{\linewidth}{\strut\lipsum[1]}}
\end{document}