
我正在嘗試繪製形狀中的文字(使用縮放和路徑)。我希望文字顯示如下:
我嘗試了很多不同的方法,但我在這樣做時遇到了困難。我可以使用這樣的東西來接近它:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\begin{document}
\pagenumbering{gobble}
\begin{tikzpicture}
\node (One) at (-15,0) {.};
\node (Two) at (15,0) {.};
\draw [decorate,decoration={text effects along path,
text={TTTTTTTTTTTTTTTT},
text align=center,
text effects/.cd,
path from text,
character count=\i, character total=\n,
characters= {text along path, scale=(2 + abs(\i - (\n / 2) - 0.5) * 1 )}}] (One) to (Two);
\end{tikzpicture}
\end{document}
結果是:
我希望文本的頂部像所示的示例一樣彎曲。
答案1
\outline
我只是為了好玩而加入了巨集(需要 pdflatex)。
這些\outline
內容在序言中,而頸縮代碼在主文檔中。我最初\outline
從 Malipivo竊取了組成的程式碼TikZ:文字周圍有光環?
我所做的是創建一個\mytext
帶有文字的框 ( )(稍微填充,以便隨後不會剪切任何內容),然後連續應用\clipbox
垂直切片文字框的\cuts
次數。在每次切割中,我應用 a\scalebox
來收縮文本,作為切割次數和 的函數\dip
,它表示最大頸縮分數。我在這裡選擇的函數是拋物線函數,儘管也可以開發其他函數。
\documentclass{article}
\usepackage{ifthen,trimclip,calc,fp,graphicx,xcolor}
%%%%% FOR TEXT OUTLINING
\input pdf-trans
\newbox\qbox
\def\usecolor#1{\csname\string\color@#1\endcsname\space}
\newcommand\bordercolor[1]{\colsplit{1}{#1}}
\newcommand\fillcolor[1]{\colsplit{0}{#1}}
\newcommand\outline[1]{\leavevmode%
\def\maltext{#1}%
\setbox\qbox=\hbox{\maltext}%
\boxgs{Q q 2 Tr \thickness\space w \fillcol\space \bordercol\space}{}%
\copy\qbox%
}
\newcommand\colsplit[2]{\colorlet{tmpcolor}{#2}\edef\tmp{\usecolor{tmpcolor}}%
\def\tmpB{}\expandafter\colsplithelp\tmp\relax%
\ifnum0=#1\relax\edef\fillcol{\tmpB}\else\edef\bordercol{\tmpC}\fi}
\def\colsplithelp#1#2 #3\relax{%
\edef\tmpB{\tmpB#1#2 }%
\ifnum `#1>`9\relax\def\tmpC{#3}\else\colsplithelp#3\relax\fi
}
\bordercolor{blue}
\fillcolor{yellow}
\def\thickness{.5}
%%%%%
\begin{document}
\Huge
\edef\dip{.5}% percent to depress the amplitude
\def\cuts{200}% Number of cuts
\newsavebox\mytext
\savebox{\mytext}{\kern.3pt\textbf{\textsf{\outline{Valley Text}}}\kern.3pt}% TEXT
\newlength\clipsize
\FPeval{\myprod}{1/cuts}
\clipsize=\myprod\wd\mytext\relax
\newcounter{mycount}
\whiledo{\value{mycount}<\cuts}{%
\stepcounter{mycount}%
\edef\NA{\themycount}%
\edef\NB{\the\numexpr\cuts-\themycount\relax}%
\FPeval{\myprod}{1 - \dip*\NA*\NB*4/\cuts/\cuts}%
\clipbox{%
\value{mycount}\clipsize\relax{} %
-1pt %
\wd\mytext-\value{mycount}\clipsize-\clipsize\relax{} %
-1pt%
}{\scalebox{1}[\myprod]{\usebox{\mytext}}}%
}
\end{document}
沒有\outline
程式碼,程式碼更易於管理。 (已編輯)在這裡,我將其轉換為宏,\parabtext[<mode>]{<lift>}{<neck>}{<cuts>}{<content>}
並添加了上面的一些內容:
<mode>
0表示中間窄,1表示兩端窄;
<lift>
是轉換期間基線的最大提升分數
<neck>
是頸部總高度的減少分數;
<cuts>
是應用於盒子的垂直切片數量(太小,看起來會呈現階梯狀)
<content>
是放入盒子並進行變形的東西。
\documentclass{article}
\usepackage{ifthen,trimclip,calc,fp,graphicx,xcolor}
\newsavebox\mytext
\newcounter{mycount}
\newlength\clipsize
\newcommand\parabtext[5][0]{%
\edef\neck{#3}% percent to depress the amplitude
\def\cuts{#4}% Number of cuts
\savebox{\mytext}{\kern.2pt#5\kern.2pt}% TEXT
\FPeval{\myprod}{1/cuts}%
\clipsize=\myprod\wd\mytext\relax%
\setcounter{mycount}{0}%
\whiledo{\value{mycount}<\cuts}{%
\stepcounter{mycount}%
\edef\NA{\themycount}%
\edef\NB{\the\numexpr\cuts-\themycount\relax}%
\FPeval{\myprod}{\NA*\NB*4/\cuts/\cuts}%
\ifnum0#1=0\relax%
\FPeval{\myprod}{1 - \neck*(\myprod)}%
\else%
\FPeval{\myprod}{1 - \neck*(1-\myprod)}%
\fi%
\clipbox{%
\value{mycount}\clipsize\relax{} %
-1pt %
\wd\mytext-\value{mycount}\clipsize-\clipsize\relax{} %
-1pt%
}{\raisebox{#2\dimexpr\ht\mytext-\myprod\ht\mytext}{%
\scalebox{1}[\myprod]{\usebox{\mytext}}}}%
}%
}
\begin{document}
\Huge\centering\def\X{\textbf{XXX}}%
\parabtext{0}{.7}{200}{\textbf{\textcolor{brown}{Valley Text}}}\par
\X\parabtext{0}{.7}{200}{\X}\parabtext[1]{0}{.7}{200}{\X}\X\par
\X\parabtext{1}{.7}{200}{\X}\parabtext[1]{1}{.7}{200}{\X}\X\par
\X\parabtext{.425}{.7}{200}{\X}\parabtext[1]{.425}{.7}{200}{\X}\X
\end{document}
最近編輯的選項<mode>
,更改了變換的形函數。在兩種模式下,都會評估函數
\FPeval{\myprod}{\NA*\NB*4/\cuts/\cuts}%
這是一條拋物線,盒子兩端的值為 1,盒子中間的值為 0。那麼,如果眾數為0,則變換為
\FPeval{\myprod}{1 - \neck*(\myprod)}%
而如果不為零,則變換為
\FPeval{\myprod}{1 - \neck*(1-\myprod)}%
這個簡單的差異將分別產生頸縮和桶形版本。
提議的方法
此方法的計算量有些大,但它的目的是在 Wow! 中謹慎使用。影響。
首先,我將展示一個稍微修改過的程式碼,該程式碼實際上將其從前向差異變為中心差異,儘管它可能會花費更多的計算成本。
但我認為最有效的方法是將使用者定義變數中的切片數量設定為較低的數字,並\def\slices{5}
在此基礎上開發文件。在最終編譯時,當所有內容都在最終佈局中設定完畢後,然後重新設定\def\slices
為所需的數字,例如{200}
,並重新編譯最後一次。
\documentclass{article}
\usepackage{ifthen,trimclip,calc,fp,graphicx,xcolor}
\newsavebox\mytext
\newcounter{mycount}
\newlength\clipsize
\newcommand\parabtext[5][0]{%
\edef\neck{#3}% percent to depress the amplitude
\def\cuts{#4}% Number of cuts
\savebox{\mytext}{\kern.2pt#5\kern.2pt}% TEXT
\FPeval{\myprod}{1/cuts}%
\clipsize=\myprod\wd\mytext\relax%
\setcounter{mycount}{0}%
\whiledo{\value{mycount}<\cuts}{%
\stepcounter{mycount}%
\edef\NA{\themycount}%
\edef\NB{\the\numexpr\cuts-\themycount\relax}%
\FPeval{\myprod}{(\NA-.5)*(\NB+.5)*4/\cuts/\cuts}%
\ifnum0#1=0\relax%
\FPeval{\myprod}{1 - \neck*(\myprod)}%
\else%
\FPeval{\myprod}{1 - \neck*(1-\myprod)}%
\fi%
\clipbox{%
\value{mycount}\clipsize-\clipsize\relax{} %
-1pt %
\wd\mytext-\value{mycount}\clipsize\relax{} %
-1pt%
}{\raisebox{#2\dimexpr\ht\mytext-\myprod\ht\mytext}{%
\scalebox{1}[\myprod]{\usebox{\mytext}}}}%
}%
}
\begin{document}
\def\slices{200}
\Huge\centering\def\X{\textbf{XXX}}%
\parabtext{0}{.7}{\slices}{\textbf{\textcolor{brown}{Valley Text}}}\par
\X\parabtext{0}{.7}{\slices}{\X}\parabtext[1]{0}{.7}{\slices}{\X}\X\par
\X\parabtext{1}{.7}{\slices}{\X}\parabtext[1]{1}{.7}{\slices}{\X}\X\par
\X\parabtext{.425}{.7}{\slices}{\X}\parabtext[1]{.425}{.7}{\slices}{\X}\X
\end{document}
\slices
例如,以下是設定5
為低解析度編譯的輸出:
XeLaTeX 使用者註意事項
OP 指出這種方法在 XeLaTeX 中不起作用。經過一番研究,我將問題歸結為trimclip
包中的錯誤(\scalebox 的 \clipbox 在 xelatex 中無法正常運作)。當在 XeLaTeX 中運行時,Joseph Wright 非常友善地診斷了問題並提供了程式碼補丁trimclip
。
\makeatletter
\ifdefined\XeTeXversion
\def\@cliptoboxdim#1{%
\setbox #1=\hbox{%
\Gin@defaultbp\WIDTH{\wd #1}%
\Gin@defaultbp \DEPTH {\dp #1}%
\@tempdima \ht #1%
\advance\@tempdima\dp#1%
\Gin@defaultbp \TOTALHEIGHT {\@tempdima }%
\special{pdf:literal q}%
\special{pdf:literal 0 -\DEPTH \space \WIDTH \space \TOTALHEIGHT \space re W n }%
\rlap{\copy #1}%
\special {pdf:literal Q}%
\hskip\wd#1%
}%
}
\fi
\makeatother
答案2
更新
使用三角網格,我們可以近似任何連續變換。
\documentclass[border=9,tikz]{standalone}
\begin{document}
\pgfmathdeclarefunction{fx}{2}{\pgfmathparse{#1*(3+cos(#2*20))/3}}
\pgfmathdeclarefunction{fy}{2}{\pgfmathparse{#2*(3-cos(#1*20))/3}}
\pgfmathdeclarefunction{fxx}{2}{\pgfmathparse{fx(#1+1,#2)-fx(#1,#2)}}
\pgfmathdeclarefunction{fxy}{2}{\pgfmathparse{fy(#1+1,#2)-fy(#1,#2)}}
\pgfmathdeclarefunction{fyx}{2}{\pgfmathparse{fx(#1,#2+1)-fx(#1,#2)}}
\pgfmathdeclarefunction{fyy}{2}{\pgfmathparse{fy(#1,#2+1)-fy(#1,#2)}}
\tikz{
\path(-15,-15)(15,15);
\foreach\i in{-10,...,9}{
\foreach\j in{-10,...,9}{
\pgfmathsetmacro\aa{fxx(\i,\j)}
\pgfmathsetmacro\ab{fxy(\i,\j)}
\pgfmathsetmacro\ba{fyx(\i,\j)}
\pgfmathsetmacro\bb{fyy(\i,\j)}
\pgfmathsetmacro\xx{fx (\i,\j)}
\pgfmathsetmacro\yy{fy (\i,\j)}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\fill[black!10](1,0)--(0,0)--(0,1);
\clip(1,0)--(0,0)--(0,1)--cycle;
\tikzset{shift={(-\i,-\j)}}
\path(0,0)node{\includegraphics[width=20cm]{lena.png}};
}
\pgfmathsetmacro\aa{fxx(\i ,\j+1)}
\pgfmathsetmacro\ab{fxy(\i ,\j+1)}
\pgfmathsetmacro\ba{fyx(\i+1,\j )}
\pgfmathsetmacro\bb{fyy(\i+1,\j )}
\pgfmathsetmacro\xx{fx (\i+1,\j+1)}
\pgfmathsetmacro\yy{fy (\i+1,\j+1)}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\clip(0,0)--(-1,0)--(0,-1)--cycle;
\tikzset{shift={(-\i-1,-\j-1)}}
\path(0,0)node{\includegraphics[width=20cm]{lena.png}};
}
}
}
}
\end{document}
舊答案
只是複製 @Steven B. Segletes 的想法,只是網格是 2D 的,並且是在 PGF/Ti 中完成的kZ。
% !TEX program = XeLaTeX
% !TEX encoding = UTF-8 Unicode
\documentclass[border=9,tikz]{standalone}
\usepackage{fontspec}\setmainfont{Arial Unicode MS}
\begin{document}
\pgfmathdeclarefunction{fxx}{1}{\pgfmathparse{#1}}
\pgfmathdeclarefunction{fxy}{1}{\pgfmathparse{sin(222+30*#1)}}
\pgfmathdeclarefunction{fyx}{1}{\pgfmathparse{sin(20*#1)}}
\pgfmathdeclarefunction{fyy}{1}{\pgfmathparse{#1}}
\pgfmathdeclarefunction{gxx}{1}{\pgfmathparse{fxx(#1+1)-fxx(#1)}}
\pgfmathdeclarefunction{gxy}{1}{\pgfmathparse{fxy(#1+1)-fxy(#1)}}
\pgfmathdeclarefunction{gyx}{1}{\pgfmathparse{fyx(#1+1)-fyx(#1)}}
\pgfmathdeclarefunction{gyy}{1}{\pgfmathparse{fyy(#1+1)-fyy(#1)}}
\tikz{
\path(-2,-2)(103,23);
\foreach\i in{0,...,100}{
\foreach\j in{0,...,20}{
{
\pgfmathsetmacro\aa{gxx(\i)}
\pgfmathsetmacro\ab{gxy(\i)}
\pgfmathsetmacro\ba{gyx(\j)}
\pgfmathsetmacro\bb{gyy(\j)}
\pgfmathsetmacro\xx{fxx(\i)+fyx(\j)}
\pgfmathsetmacro\yy{fxy(\i)+fyy(\j)}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\clip(0,0)--(1,0)--(1,1)--(0,1)--cycle;
\draw[gray](1,0)--(0,0)--(0,1);
\path(-\i,-\j)+(50,10)node{\fontsize{500pt}{0}\selectfont Valley Text};
}
}
}
}
}
\end{document}
一些數學
在我的程式碼中,轉換定義為
(x,y) |--> ( fxx(x)+fyx(y) , fxy(x)+fyy(y) )
其中 fxx、fyx、fxy、fyy 是好的功能。這樣的變換會將一個正方形變成一個平行四邊形。巧合的是,PDF 支援仿射變換,也可以將正方形變換為平行四邊形。因此我可以使用分段仿射變換來近似原始變換。結果是任何曲線都會保留連接的,儘管不可微分。