Tikz (or pgf) patterns can solve your problem.
To fill with n-color stripes (n >= 2) using an uncolored pattern (also called "form-only"), you have to apply a pattern n-1 times since an uncolored pattern can only have a single color, which is specified by option pattern color
.
Notice how the linked answer uses normal filling and an uncolored pattern in postaction
to achieve a two-color stripes. So a three-color stripes will need two postaction
.
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{patterns.meta}
\begin{document}
\begin{tikzpicture}
\fill[fill=red,
% set `line width` to 1/3 of the `distance`
% set `xshift` according to both `angle` and `line width`
postaction={
pattern={Lines[angle=30, distance=9pt, line width=3pt,
xshift=3pt/sin(30)]},
pattern color=green},
postaction={
pattern={Lines[angle=30, distance=9pt, line width=3pt,
xshift=-3pt/sin(30)]},
pattern color=blue},
]
(0,0) rectangle +(2,1);
\end{tikzpicture}
\end{document}
To do the same task using a colored pattern, a new pattern Stripes
is defined in the example below. It is similar to the pattern Lines
from tikz library patterns.meta
, with a new option color series={<comma list of colors>}
. The line width
option is invalid and now auto computed as 1/n of distance
in which n is the length of color series
. Hence with distance=6pt, color series={red, blue}
, the line width is 3pt; with distance=6pt, color series={red, green, blue}
, the line width is 2pt.
color series
has initial and default value red, green, blue
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{patterns.meta}
\usepackage{pgfgantt}
\makeatletter
\newlength\pgf@pat@distance % or defined by the more portable \newdimen
% based on pattern `Lines`, defined in pgflibrarypatterns.meta.code.tex
\pgfdeclarepattern{
name=Stripes,
type=colored,
parameters={
\pgfkeysvalueof{/pgf/pattern keys/distance},
\pgfkeysvalueof{/pgf/pattern keys/angle},
\pgfkeysvalueof{/pgf/pattern keys/xshift},
\pgfkeysvalueof{/pgf/pattern keys/yshift},
\pgfkeysvalueof{/pgf/pattern keys/color series},
},
bottom left={%
\pgfpoint{-.5*\pgf@pat@distance}{-.5*\pgf@pat@distance}},
top right={%
\pgfpoint{.5*\pgf@pat@distance}{.5*\pgf@pat@distance}},
tile size={%
\pgfpoint
{\pgfkeysvalueof{/pgf/pattern keys/distance}}%
{\pgfkeysvalueof{/pgf/pattern keys/distance}}},
tile transformation={%
\pgftransformshift{%
\pgfpoint
{\pgfkeysvalueof{/pgf/pattern keys/xshift}}%
{\pgfkeysvalueof{/pgf/pattern keys/yshift}}}%
\pgftransformrotate{\pgfkeysvalueof{/pgf/pattern keys/angle}}},
defaults={
distance/.initial=6pt,
angle/.initial=0,
xshift/.initial=0pt,
yshift/.initial=0pt,
color series/.initial={red,green,blue},
},
code={%
\pgf@pat@colorseries@parse
% set line width
\pgfsetlinewidth{\pgf@pat@distance/\pgfutil@tempcnta}%
% \pgfutil@tempdima holds the y-coord of a stripe
\pgfutil@tempdima=\dimexpr-.5\pgf@pat@distance+.5\pgflinewidth\relax
% draw stripes
\pgfutil@tempcnta=0
\pgfutil@for\pgf@pat@temp:=\pgf@pat@colorseries\do{%
\ifx\pgf@pat@temp\pgfutil@empty
\else
\pgfsetstrokecolor{\pgf@pat@temp}%
\pgfpathmoveto{%
\pgfpoint{-.5*\pgf@pat@distance}{\pgfutil@tempdima}}%
\pgfpathlineto{%
\pgfpoint{ .5*\pgf@pat@distance}{\pgfutil@tempdima}}%
\pgfusepath{stroke}%
\advance\pgfutil@tempdima\pgflinewidth
\fi
}%
},
set up code={%
\pgfmathsetlength{\pgf@pat@distance}{\pgfkeysvalueof{/pgf/pattern keys/distance}}%
}
}
% util
\def\pgf@pat@colorseries@parse{%
% prepare \pgf@pat@colorseries and store its length in \pgfutil@tempcnta
\let\pgf@pat@colorseries\pgfutil@empty
\pgfutil@tempcnta=0
\pgfkeysgetvalue{/pgf/pattern keys/color series}{\pgf@pat@colorseries@temp}%
\pgfutil@for\pgf@temp:=\pgf@pat@colorseries@temp\do{%
% strip spaces around color names and skip empty items
% the total effect is to convert `red, blue,, cyan` to `red,blue,cyan`
\expandafter\pgfkeys@spdef\expandafter\pgf@temp\expandafter{\pgf@temp}%
\ifx\pgf@temp\pgfutil@empty
\else
\edef\pgf@pat@colorseries{%
\unexpanded\expandafter{\pgf@pat@colorseries},%
\unexpanded\expandafter{\pgf@temp}}%
\advance\pgfutil@tempcnta by 1
\fi
}%
% ensure the resulting color series is never empty
\ifnum\pgfutil@tempcnta=0
\def\pgf@pat@colorseries{red,green,blue}%
\fi
}
\makeatother
\begin{document}
\begin{tikzpicture}
\fill[pattern={Lines[angle=30]}]
(0,0) rectangle +(2,1);
\fill[pattern={Stripes[angle=30]}]
(0,-1.5) rectangle +(2,1);
\fill[pattern={Stripes[angle=30, color series={gray, darkgray}]}]
(3,-1.5) rectangle +(2,1);
\fill[pattern={Stripes[angle=30, distance=12pt, color series={cyan, magenta, yellow, black}]}]
(6,-1.5) rectangle +(2,1);
\fill[pattern={Stripes[angle=30, distance=12pt, color series={cyan!50!black!50}]}]
(9,-1.5) rectangle +(2,1);
\end{tikzpicture}
\bigskip
% helper option
\pgfqkeys{/pgfgantt}{
bar pattern/.style={
bar/.append style={
pattern={Stripes[angle=45,distance=15pt,color series={#1}]}
}
},
bar pattern/.default={red,green,blue},
}
\noindent
\begin{ganttchart}[expand chart=\textwidth]{1}{48}
\gantttitle[]{Year 1}{12}
\gantttitle[]{Year 2}{12}
\gantttitle[]{Year 3}{12}
\gantttitle[]{Year 4}{12} \\
\ganttbar[bar pattern]{WP1}{1}{48} \\
\ganttbar[bar pattern={blue, green}]{WP2}{4}{15} \\
\ganttbar[bar pattern={blue, red}]{WP3}{10}{30} \\
\ganttbar[bar pattern={red}]{WP4}{20}{45}
\end{ganttchart}
\end{document}