如何在 TikZ 中绘制一面飘扬的旗帜

如何在 TikZ 中绘制一面飘扬的旗帜

我们以德国国旗为例,因为这面国旗非常简单,其飘扬的状态可以很容易地“手动”绘制出来。但我问的是一般的国旗(任何国家/团体的国旗,甚至是我所在队的国旗)。


正常标志 (1)

\documentclass[tikz]{standalone}
\usepackage{xcolor}
\definecolor{gerbla}{RGB}{0,0,0}
\definecolor{gerred}{RGB}{255,0,0}
\definecolor{geryel}{RGB}{255,204,0}
\begin{document}
\begin{tikzpicture}
\fill[gerbla] (0,2) rectangle (5,3);
\fill[gerred] (0,1) rectangle (5,2);
\fill[geryel] (0,0) rectangle (5,1);
\end{tikzpicture}
\end{document}

在此处输入图片描述

挥舞旗帜(2)(比例可能不真实)

\documentclass[tikz]{standalone}
\usepackage{xcolor}
\definecolor{gerbla}{RGB}{0,0,0}
\definecolor{gerred}{RGB}{255,0,0}
\definecolor{geryel}{RGB}{255,204,0}
\begin{document}
\begin{tikzpicture}
\fill[gerbla] (0,3) to[out=0,in=180] (4,2) -- (4,1) to[out=180,in=0] (0,2) -- cycle;
\fill[gerred] (0,2) to[out=0,in=180] (4,1) -- (4,0) to[out=180,in=0] (0,1) -- cycle;
\fill[geryel] (0,1) to[out=0,in=180] (4,0) -- (4,-1) to[out=180,in=0] (0,0) -- cycle;
\end{tikzpicture}
\end{document}

在此处输入图片描述

高级挥舞旗帜(3)

在此处输入图片描述

(unTiZified – 图片取自表情符号百科


问题

如何绘制一面飘扬的旗帜?换句话说,假设我已经有一面矩形旗帜 (1),上面有许多图案和物品(甚至还有一些\includegraphics),我怎样才能“挥动”(1) 来获得 (2),其中

  1. 比例长度/宽度仍然正确。
  2. 旗帜上的图像、图案等也被飘扬,并且这些物品仍然与整体旗帜正确地契合。

附加问题

如果我已经有了(1)或(2),我怎样才能获得像(3)那样的阴影效果和灯光效果?


按照@marmot 的要求,美国国旗的代码如下:

\documentclass[tikz]{standalone}
\usetikzlibrary{shapes}
\usepackage{xcolor}
\begin{document}
\begin{tikzpicture}
\definecolor{usblue}{rgb}{.234,.233,.430}
\definecolor{usared}{rgb}{.698,.132,.203}
\fill[usared] (0,0) rectangle (1.9,1);
\foreach \i in {1,3,...,11}
    \fill[white] (0,\i/13) rectangle (1.9,{(\i+1)/13});
\fill [usblue] (0,6/13) rectangle ({1.9*2/5},1);
\foreach \i in {1,2,3,4,5,6} {
    \foreach \j in {1,2,3,4,5} {
        \node[star,star points=5,star point ratio=2.25,fill=white,minimum size=0.0616cm,inner sep=0pt] at ({(1.9/15)*\i-(1.9/30)},{6/13+(7/130)+(7*(\j-1)/65)}) {};
    }
}
\foreach \i in {1,2,3,4,5} {
    \foreach \j in {1,2,3,4} {
        \node[star,star points=5,star point ratio=2.25,fill=white,minimum size=0.0616cm,inner sep=0pt] at ({(1.9/15)*\i},{6/13+(7*\j/65)}) {};
    }
}
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案1

您可以使用非线性变换来实现此效果。

\documentclass[tikz,border=3.14mm]{standalone}
\usepgfmodule{nonlineartransformations}
\definecolor{gerbla}{RGB}{0,0,0}
\definecolor{gerred}{RGB}{255,0,0}
\definecolor{geryel}{RGB}{255,204,0}
\makeatletter
\def\flagtransformation{%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
%\typeout{old\space x=\pgf@xa\space old \space y=\pgf@ya}%
\pgfmathsetmacro{\myy}{\pgf@ya+7*sin(\pgf@xa*3.6)-0.1*\pgf@xa}%
%\typeout{at\space x=\the\pgf@xa:\space new\space y=\myy}%
\pgf@y=\myy pt}
\makeatother
\newcommand{\GermanFlag}{%
\fill[gerbla] (0,2) rectangle (4,3);
\fill[gerred] (0,1) rectangle (4,2);
\fill[geryel] (0,0) rectangle (4,1);}
\begin{document}
\begin{tikzpicture}[font=\sffamily,scale=1]
\begin{scope}[local bounding box=linear]
 \GermanFlag
\end{scope}
\node[anchor=south] (lin) at (linear.north){linear};
\begin{scope}[xshift=5cm,local bounding box=nonlinear,transform shape
nonlinear=true]
 \pgftransformnonlinear{\flagtransformation}
 \GermanFlag
 \shade[left color=black,right color=black,middle color=white,opacity=0.15]
 (0,0) rectangle (2,3);
 \shade[left color=black,right color=black,middle color=white,opacity=0.15]
 (2,0) rectangle (4,3);
\end{scope}
\node[anchor=south] at (lin.south-|nonlinear.north){nonlinear};
\end{tikzpicture}
\end{document}

在此处输入图片描述

当然,这适用于任何你有 Ti 的标志Z 代码,当然也包括漂亮的美国国旗。

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{shapes}
\usepgfmodule{nonlineartransformations}
\definecolor{usblue}{rgb}{.234,.233,.430}
\definecolor{usared}{rgb}{.698,.132,.203}
\makeatletter
\def\flagtransformation{%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
%\typeout{old\space x=\pgf@xa\space old \space y=\pgf@ya}%
\pgfmathsetmacro{\myy}{\pgf@ya+7*sin(\pgf@xa*3.6)-0.1*\pgf@xa}%
%\typeout{at\space x=\the\pgf@xa:\space new\space y=\myy}%
\pgf@y=\myy pt}
\makeatother
\newcommand{\USFlag}{%
\fill[usared] (0,0) rectangle (1.9,1);
\foreach \i in {1,3,...,11}
    \fill[white] (0,\i/13) rectangle (1.9,{(\i+1)/13});
\fill [usblue] (0,6/13) rectangle ({1.9*2/5},1);
\foreach \i in {1,2,3,4,5,6} {
    \foreach \j in {1,2,3,4,5} {
        \node[star,star points=5,star point ratio=2.25,fill=white,
        minimum size=0.0616cm,inner sep=0pt] at ({(1.9/15)*\i-(1.9/30)},{6/13+(7/130)+(7*(\j-1)/65)}) {};
    }
}
\foreach \i in {1,2,3,4,5} {
    \foreach \j in {1,2,3,4} {
        \node[star,star points=5,star point ratio=2.25,fill=white,minimum size=0.0616cm,inner sep=0pt] at ({(1.9/15)*\i},{6/13+(7*\j/65)}) {};
    }
}}
\begin{document}
\begin{tikzpicture}[font=\sffamily,scale=2,transform shape]
\begin{scope}[local bounding box=linear]
 \USFlag
\end{scope}
\node[anchor=south] (lin) at (linear.north){linear};
\begin{scope}[xshift=2.5cm,local bounding box=nonlinear,transform shape
nonlinear=true]
 \pgftransformnonlinear{\flagtransformation}
 \USFlag
 \shade[left color=black,right color=black,middle color=white,opacity=0.15]
 (0,0) rectangle (0.95,1);
 \shade[left color=black,right color=black,middle color=white,opacity=0.15]
 (0.95,0) rectangle (1.9,1);
\end{scope}
\node[anchor=south] at (lin.south-|nonlinear.north){nonlinear};
\end{tikzpicture}
\end{document}

在此处输入图片描述

这是 Black Mild 的东西。

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{shapes}
\usepgfmodule{nonlineartransformations}
\definecolor{usblue}{rgb}{.234,.233,.430}
\definecolor{usared}{rgb}{.698,.132,.203}
\makeatletter
\def\flagtransformation{%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
%\typeout{old\space x=\pgf@xa\space old \space y=\pgf@ya}%
\pgfmathsetmacro{\myy}{\pgf@ya+7*sin(\pgf@xa*3.6)-0.1*\pgf@xa}%
%\typeout{at\space x=\the\pgf@xa:\space new\space y=\myy}%
\pgf@y=\myy pt}
\tikzdeclarecoordinatesystem{flag}{% https://tex.stackexchange.com/a/434247/121799
    \tikz@scan@one@point\relax(#1)
    \flagtransformation
}
\makeatother
\newcommand{\USFlag}{%
\fill[usared] (0,0) rectangle (1.9,1);
\foreach \i in {1,3,...,11}
    \fill[white] (0,\i/13) rectangle (1.9,{(\i+1)/13});
\fill [usblue] (0,6/13) rectangle ({1.9*2/5},1);
\foreach \i in {1,2,3,4,5,6} {
    \foreach \j in {1,2,3,4,5} {
        \node[star,star points=5,star point ratio=2.25,fill=white,
        minimum size=0.0616cm,inner sep=0pt] at ({(1.9/15)*\i-(1.9/30)},{6/13+(7/130)+(7*(\j-1)/65)}) {};
    }
}
\foreach \i in {1,2,3,4,5} {
    \foreach \j in {1,2,3,4} {
        \node[star,star points=5,star point ratio=2.25,fill=white,minimum size=0.0616cm,inner sep=0pt] at ({(1.9/15)*\i},{6/13+(7*\j/65)}) {};
    }
}}
\begin{document}
\foreach \X in {0,5,...,95}
{\begin{tikzpicture}[font=\sffamily,scale=2,transform shape]
\begin{scope}[xshift=\X pt,
local bounding box=nonlinear,transform shape
nonlinear=true]
 \pgftransformnonlinear{\flagtransformation}
 \USFlag
 \shade[left color=black,right color=black,middle color=white,opacity=0.15]
 (0,0) rectangle (0.95,1);
 \shade[left color=black,right color=black,middle color=white,opacity=0.15]
 (0.95,0) rectangle (1.9,1); 
 \shade[left color=gray,right color=gray!70,middle color=gray!20] 
(0,1.05) rectangle ++ (-0.1,-3);
\end{scope}
\end{tikzpicture}}
\end{document}

在此处输入图片描述

这个答案有许多旗帜的代码,其中我选择了冰岛。(请注意,如果旗帜包含形状,则需要说transform shape nonlinear=true。)可以在顶部添加阴影。

\documentclass[tikz,border=3.14mm]{standalone}
\usepgfmodule{nonlineartransformations}
\makeatletter
\def\flagtransformation{%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
%\typeout{old\space x=\pgf@xa\space old \space y=\pgf@ya}%
\pgfmathsetmacro{\myy}{\pgf@ya+7*sin(\pgf@xa*3.6)-0.1*\pgf@xa}%
%\typeout{at\space x=\the\pgf@xa:\space new\space y=\myy}%
\pgf@y=\myy pt}
\makeatother
\definecolor{SkyBlue}{rgb}{0.00784314,0.32156864,0.61176473}
\definecolor{FireRed}{rgb}{0.86274511,0.11764706,0.20784314}
\newcommand\IcelandFlag{
\fill[SkyBlue] (0,0) rectangle (25,18);
\fill[white] (7,0) rectangle (11,18);
\fill[white] (0,7) rectangle (25,11);
\fill[FireRed] (8,0) rectangle (10,18);
\fill[FireRed] (0,8) rectangle (25,10);}
\begin{document}
\begin{tikzpicture}[font=\sffamily,scale=0.15]
\begin{scope}[local bounding box=linear]
 \IcelandFlag
\end{scope}
\node[anchor=south] (lin) at (linear.north){linear};
\begin{scope}[xshift=35cm,local bounding box=nonlinear]
 \pgftransformnonlinear{\flagtransformation}
 \IcelandFlag
 \shade[left color=black,right color=black,middle color=white,opacity=0.15]
 (0,0) rectangle (12.5,18);
 \shade[left color=black,right color=black,middle color=white,opacity=0.15]
 (12.5,0) rectangle (25,18);
\end{scope}
\node[anchor=south] at (lin.south-|nonlinear.north){nonlinear};
\end{tikzpicture}
\end{document}

在此处输入图片描述

为了绘制 3d 旗帜,您可以使用tikz-3dplot。使用\shade您可以获得类似这样的结果。

\documentclass[tikz]{standalone}
\usepackage{tikz-3dplot} 
\definecolor{gerbla}{RGB}{0,0,0}
\definecolor{gerred}{RGB}{255,0,0}
\definecolor{geryel}{RGB}{255,204,0}
\begin{document}
\tdplotsetmaincoords{70}{20} 
\begin{tikzpicture}[tdplot_main_coords]
% \draw[-stealth] (0,0,0) -- (2,0,0) node[pos=1.1]{$x$};
% \draw[-stealth] (0,0,0) -- (0,2,0) node[pos=1.1]{$y$};
\foreach \X [count=\Y] in {gerbla,gerred,geryel}
{\shade[left color=\X,right color=\X!70!black,middle color=\X!70!white] 
plot[variable=\x,domain=0:2] (\x,{0.2*sin(\x*90)},4-\Y)
-- 
plot[variable=\x,domain=2:0] (\x,{0.2*sin(\x*90)},3-\Y);
\shade[left color=\X!70!black,right color=\X,middle color=\X!70!white] 
plot[variable=\x,domain=2:4] (\x,{0.2*sin(\x*90)},4-\Y)
-- 
plot[variable=\x,domain=4:2] (\x,{0.2*sin(\x*90)},3-\Y);}
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容