我正在做一个项目,可能会使用TikZ
(或类似的软件包)来制作一些矢量图形。所有图形都由灰色线条组成。但是,线条看起来TikZ
太干净了。
有什么方法可以让这些线条看起来像是用石墨铅笔画出来的一样?
答案1
我发布此文只是因为您特别提到了这些台词。
我修改了bent
装饰,让它看起来更像手绘。它确实有问题,目前还不能在曲线上使用它……好吧,你可以,但结果至少是出乎意料的。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.pathmorphing,patterns}
\makeatletter
\pgfdeclaredecoration{penciline}{initial}{
\state{initial}[width=+\pgfdecoratedinputsegmentremainingdistance,auto corner on length=1mm,]{
\pgfpathcurveto%
{% From
\pgfqpoint{\pgfdecoratedinputsegmentremainingdistance}
{\pgfdecorationsegmentamplitude}
}
{% Control 1
\pgfmathrand
\pgfpointadd{\pgfqpoint{\pgfdecoratedinputsegmentremainingdistance}{0pt}}
{\pgfqpoint{-\pgfdecorationsegmentaspect\pgfdecoratedinputsegmentremainingdistance}%
{\pgfmathresult\pgfdecorationsegmentamplitude}
}
}
{%TO
\pgfpointadd{\pgfpointdecoratedinputsegmentlast}{\pgfpoint{1pt}{1pt}}
}
}
\state{final}{}
}
\makeatother
\begin{document}
\begin{tikzpicture}[decoration=penciline]
\draw[decorate,style=help lines] (-2,-2) grid[step=1cm] (4,4);
\draw[decorate,thick] (0,0) -- (0,3) -- (3,3);
\draw[decorate,ultra thick,blue] (3,3) arc (0:-90:2cm); %% This is supposed to be an arc!!
\draw[decorate,thick,pattern=north east lines] (-0.4cm,-0.8cm) rectangle (1.2,-2);
\node[decorate,draw,inner sep=0.5cm,fill=yellow,circle] (a) at (2,0) {}; %% That's not even an ellipse !!
\node[decorate,draw,inner sep=0.3cm,fill=red] (b) at (2,-2) {};
\draw[decorate] (b) to[in=-45,out=45] (a); %% This was supposed to be an edge!!
\node[decorate,draw,minimum height=2cm,minimum width=1cm] (c) at (-1.5,0) {};
\draw[decorate,->,dashed] (-0.5cm,-0.5cm) -- (-0.5cm,3.5cm) -| (c.north);
\end{tikzpicture}
\end{document}
输出如下:
我目前正在研究markings
装饰,看看如何沿着路径移动而不给出曲线上的明确坐标。希望这可以让它用于弧线。请注意,背景网格也经过了装饰 :)
答案2
pgf 手册中有一个名为“Putting it in Chains”的教程。它以一个示例开始,该示例可以完成您所需的操作。
编辑:
由于 PGF/TikZ 手册因拼写错误而出现小超链接问题,这里是相关装饰样式的示例。您可以通过调整随机方向的块并控制与主路径之间的最大距离来random steps
进一步自定义它。segment length
amplitude
random step
样本/简单示例样式:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}[pencildraw/.style={
black!75,
decorate,
decoration={random steps,segment length=0.8pt,amplitude=0.1pt}
}
]
\node[pencildraw,draw] {Node};
\draw[pencildraw] (0,1) -- (1,1) arc (0:-180:9mm and 7mm);
\end{tikzpicture}
\end{document}
答案3
这是在 Metapost 中模拟手绘曲线的另一种尝试。这在很大程度上受到了 MetaFun 宏的启发。这种方法的主要优点是您根本不需要更改绘图宏。只需input
文件和调用sketchypaths
,所有路径就会变得有点粗略。
另存为以下内容mp-sketch.mp
%D The variable \type{sketch_amount} determines the amount of randomness in the
%D drawing
numeric sketch_amount; sketch_amount := 3bp;
%D The macro \type{sketchdraw} randomized the path before drawing it. The
%D \type{expr} ... \type{text} trick is copied from the definition of
%D \type{drawarrow}
def sketchdraw expr p =
do_sketchdraw(p if (path p): randomized sketch_amount fi)
enddef;
def do_sketchdraw(expr p) text t =
normaldraw p t ;
enddef;
%D The macro \type{sketchfill} randomizes the path before filling it.
path _sketch_path_;
def sketchfill expr p =
_sketch_path_ := p randomized sketch_amount;
do_sketchfill
enddef ;
def do_sketchfill text t =
normalfill _sketch_path_ t ;
enddef ;
%D The macro \type{sketchypaths} is modeled after \type{visualizepaths} from
%D \filename{mp-tool}.
def sketchypaths =
let draw = sketchdraw ;
let fill = sketchfill ;
enddef ;
主宏是,它改变了和sketchypaths
的定义,使其变得粗略。要恢复正常行为,请使用metafun 中的宏。draw
fill
naturalizepahts
要使用这些,您还需要加载mp-tool.mkiv
。我将展示 ConTeXt 中的一个测试文件,它已经加载了 MetaFun 宏。
\startMPinclusions
input mp-sketch;
\stopMPinclusions
\starttext
\startMPpage[offset=3mm]
sketchypaths;
draw (0,0) -- (1cm,0) -- (1cm,1cm);
fill fullsquare scaled 1cm shifted (3cm,3cm) withcolor red;
drawarrow (1cm,1cm) -- (2cm,2cm);
stripe_path_a
(withcolor red)
(draw)
fullcircle xscaled 100 yscaled 40 shifted (0, 2.5cm) withcolor blue;
\stopMPpage
\stoptext
这使
由于sketchypaths
宏改变了draw
和fill
命令,因此很容易将其与现有的 MetaPost 包结合使用。例如,使用boxes.mp
:
\startMPdefinitions
input mp-sketch;
input boxes;
\stopMPdefinitions
\starttext
\startMPpage[offset=3mm]
sketchypaths;
boxit.one (btex One etex);
boxit.two (btex Two etex);
boxit.three (btex Three etex);
three.w - two.e = two.w - one.e = (1cm,0);
one.c = origin;
drawboxed (one, two, three);
drawarrow one.e -- lft two.w;
drawarrow two.e -- lft three.w;
\stopMPpage
\stoptext
上图显示没有 的输出sketchypaths
,下图显示有 的输出sketchyparts
。
以下是示例 83 的稍作修改的版本metapost 示例
在我看来,这看起来更自然的比许多其他解决方案更好。
答案4
[2018 年 8 月 13 日编辑:代码更好更短,但不幸的是现在慢了很多……]
我意识到我有点迟到了,但这是我的尝试。我尝试实现他们使用的想法来matplotlib
创建“XKCD”风格。示例代码和图像如下。
这是我第一次在 PGF 级别编写代码,所以我很高兴收到更正和/或建议。
代码需要 LuaLaTeX 字体,但如果删除字体内容,它也可以与普通 LaTeX 一起使用。
\documentclass{article}
\usepackage{fontspec}
\setmainfont{Humor Sans}
\usepackage{tikz}
\usetikzlibrary{calc,decorations,patterns,arrows,decorations.pathmorphing}
\definecolor{pltblue}{HTML}{1F77B4}
\makeatletter
\pgfset{
/pgf/decoration/randomness/.initial=2,
/pgf/decoration/wavelength/.initial=100
}
\pgfdeclaredecoration{sketch}{init}{
\state{init}[width=0pt,next state=draw,persistent precomputation={
\pgfmathsetmacro\pgf@lib@dec@sketch@t0
}]{}
\state{draw}[width=\pgfdecorationsegmentlength,
auto corner on length=\pgfdecorationsegmentlength,
persistent precomputation={
\pgfmathsetmacro\pgf@lib@dec@sketch@t{mod(\pgf@lib@dec@sketch@t+pow(\pgfkeysvalueof{/pgf/decoration/randomness},rand),\pgfkeysvalueof{/pgf/decoration/wavelength})}
}]{
\pgfmathparse{sin(2*\pgf@lib@dec@sketch@t*pi/\pgfkeysvalueof{/pgf/decoration/wavelength} r)}
\pgfpathlineto{\pgfqpoint{\pgfdecorationsegmentlength}{\pgfmathresult\pgfdecorationsegmentamplitude}}
}
\state{final}{}
}
\tikzset{xkcd/.style={decorate,decoration={sketch,segment length=0.5pt,amplitude=0.5pt}}}
\makeatother
\pgfmathsetseed{1}
\pagestyle{empty}
\begin{document}
\renewcommand{\baselinestretch}{0.85}
\begin{center}
\begin{tikzpicture}[xscale=4, yscale=0.05]
\node at (0.5,115) {\large Claims of supernatural powers};
\begin{scope}[very thick, every path/.style={xkcd}]
\fill[fill=pltblue] (0.875,1) -- ++(0,99) -- ++(0.25,0) -- +(0,-99) -- cycle;
\draw (0.875,1) -- ++(0,99) -- ++(0.25,0) -- +(0,-99);
\draw[ultra thick] (0,3) -- (0,0) node[below, text width=3cm, align=center] {confirmed by\\ experiment};
\draw[ultra thick] (1,3) -- (1,0) node[below, text width=3cm, align=center] {refuted by\\ experiment};
\draw (-0.5,0) -- (1.5,0);
\draw (-0.5,0) -- (-0.5,110);
\end{scope}
\end{tikzpicture}
\vspace{2cm}
\begin{tikzpicture}[xscale=0.08, yscale=0.15]
\node at (35,12) {\large Stove ownership};
\node[rotate=90] at (-3,-12) {My overall health};
\node[text width=4cm] (N) at (40, -8) {The day I realized\\ I could cook bacon\\ whenever I wanted};
\begin{scope}[very thick, every path/.style={xkcd}]
\draw (0,-30) -- node[below] {Time} (100,-30);
\draw (0,-30) -- (0,10);
\draw[pltblue] (1,1) -- (70,1) -- (100,-28);
\draw[->, >=stealth'] ($(N.north)+(5cm,0)$) -- (69.5,0.5);
\end{scope}
\end{tikzpicture}
\end{center}
\begin{center}
\begin{tikzpicture}
\draw[xkcd,help lines] (-2,-2) grid[step=1cm] (4,4);
\draw[xkcd,thick] (0,0) -- (0,3) -- (3,3);
\draw[xkcd,ultra thick, blue] (3,3) arc (0:-90:2cm);
\draw[xkcd,thick, pattern=north east lines] (-0.4cm,-0.8cm) rectangle (1.2,-2);
\node[xkcd, draw, inner sep=0.5cm, fill=yellow, circle] (a) at (2,0) {};
\node[xkcd,draw, inner sep=0.3cm, fill=red] (b) at (2,-2) {};
\draw[xkcd] (b) to[in=-45,out=45] (a);
\node[xkcd,draw, minimum height=2cm, minimum width=1cm] (c) at (-1.5,0) {};
\draw[xkcd,->, decoration={post=lineto, post length=5mm}, dashed] (-0.5cm,-0.5cm) -- (-0.5cm,3.5cm) -| (c.north);
\end{tikzpicture}
\vspace{2cm}
\begin{tikzpicture}[very thick, yscale=2, every path/.style={xkcd}]
\draw (-0.3,-1.2) rectangle (7.3,1.2);
\foreach \y in {-1.00,-0.75,...,1.00} {
\draw[ultra thick] (-0.3,\y) -- (-0.4,\y) node[left] {\pgfmathprintnumber[fixed,fixed zerofill,precision=2,assume math mode=true]{\y}};
}
\foreach \x in {0,...,7} {
\draw[ultra thick] (\x,-1.2) -- (\x,-1.25) node[below] {\x};
}
\draw[domain=0:7, pltblue, samples=100] plot (\x, {sin(\x r)});
\end{tikzpicture}
\end{center}
\end{document}