我正在尝试写一种针对年轻读者的搞笑风格的文章。在某些时候,我希望一些单词能够根据每个角色的位置产生“波浪”效果。
我已经找到了使用 pgf/TikZ 模拟艺术字的文章,但我希望不用 pgf 就能做到这一点。
因此,我们的想法应该是能够写出类似这样的内容
I can write a \bubbletext{bubble-like} wavy text.
到目前为止,基于此例子,我至少能够得到随机效果。我的问题在于我想要更一致的东西。
\ExplSyntaxOn
\NewDocumentCommand{\bubblechar}{ O{0.25} m }
{
\group_begin:
\tl_set:Nn \l_tmpa_tl { #2 }
\tl_replace_all:Nnn \l_tmpa_tl { ~ } { \c_space_tl }
\tl_map_inline:Nn \l_tmpa_tl {
\int_case:nnF { \int_mod:nn {\int_rand:nn{0}{400}} {4} }
{
{1} {\raisebox { #1 ex} { ##1 } }
{3} {\raisebox {-#1 ex} { ##1 } }
}
{##1}
}
\group_end:
}
\ExplSyntaxOff
为了实现这一点,我必须用\int_rand:nn{0}{400}
我目前在列表中的实际位置替换,但我不知道如何达到这个值。所以基本上,我想要的效果将与我写下这行代码的效果类似
I can write a b\raisebox{-0.25ex}ub\raisebox{0.25ex}bl\raisebox{-.25ex}e-\raisebox{0.25ex}li\raisebox{-0.25ex}ke wavy text.
使用 400 时,我有时会很幸运,但情况并非总是如此(远非如此)。(在下面的例子中,它非常接近/几乎完美,但大多数时候,效果几乎不可见。)
提前致谢。
答案1
以下方法不是随机化移位,而是使用整数来跟踪应应用于标记列表中每个元素的偏移量。我还在基线和顶部/底部对齐之间添加了一个步骤,其位移为 0.707 倍(大致如此cos(pi/4)
,可能会根据您的喜好进行更改)。
\documentclass{article}
\ExplSyntaxOn
\keys_define:nn { wavychars }
{
displace .tl_set:N = \l__wavychars_displace_tl
,displace .initial:n = 0.25ex
,halfstep .fp_set:N = \l__wavychars_halfstep_fp
,halfstep .initial:n = 0.707
,no-halfstep .bool_set:N = \l__wavychars_no_halfstep_bool
,unknown .code:n =
\tl_set:Nx \l__wavychars_displace_tl { \l_keys_key_str }
}
\tl_new:N \l__wavychars_input_tl
\int_new:N \l__wavychars_state_int
\cs_new:Npn \__wavychars_halfstep:
{ \fp_eval:n { \l__wavychars_displace_tl * \l__wavychars_halfstep_fp } pt }
\cs_new_protected:Npn \__wavychars_with_halfstep:n #1
{
\tl_if_eq:nnTF { \c_space_tl } {#1}
{ \c_space_tl }
{
\int_incr:N \l__wavychars_state_int
\int_case:nn \l__wavychars_state_int
{
1 {#1}
2 { \raisebox { \__wavychars_halfstep: } {#1} }
3 { \raisebox { \l__wavychars_displace_tl } {#1} }
4 { \raisebox { \__wavychars_halfstep: } {#1} }
5 {#1}
6 { \raisebox { -\__wavychars_halfstep: } {#1} }
7 { \raisebox { -\l__wavychars_displace_tl } {#1} }
8 {
\raisebox { -\__wavychars_halfstep: } {#1}
\int_zero:N \l__wavychars_state_int
}
}
}
}
\cs_new_protected:Npn \__wavychars_no_halfstep:n #1
{
\tl_if_eq:nnTF { \c_space_tl } {#1}
{ \c_space_tl }
{
\int_incr:N \l__wavychars_state_int
\int_case:nn \l__wavychars_state_int
{
1 {#1}
2 { \raisebox { \l__wavychars_displace_tl } {#1} }
3 {#1}
4 {
\raisebox { -\l__wavychars_displace_tl } {#1}
\int_zero:N \l__wavychars_state_int
}
}
}
}
\cs_new_protected:Npn \wavychars:nn #1#2
{
\group_begin:
\keys_set:nn { wavychars } {#1}
% though \text_expand:n should be preferred for user input, the following
% loop wouldn't work anyway with input containing argument grabbing macros
\tl_set:Nx \l__wavychars_input_tl { #2 }
\tl_replace_all:Nnn \l__wavychars_input_tl { ~ } { \c_space_tl }
\int_zero:N \l__wavychars_state_int
\bool_if:NTF \l__wavychars_no_halfstep_bool
{
\tl_map_function:NN \l__wavychars_input_tl \__wavychars_no_halfstep:n
}
{
\tl_map_function:NN \l__wavychars_input_tl
\__wavychars_with_halfstep:n
}
\group_end:
}
\NewDocumentCommand \wavychars { O{} m } { \wavychars:nn {#1} {#2} }
\ExplSyntaxOff
\begin{document}
\wavychars{This is in wavy style} and this is normal style.
\wavychars[halfstep=0.5]{This is in wavy style} and this is normal style.
% short syntax for displacement
\wavychars[1ex]{This is in wavy style} and this is normal style.
% short syntax doesn't work if displacement contains a macro
\newcommand*\mydisplacement{1ex}
\wavychars[displace=\mydisplacement]{This is in wavy style} and this is normal style.
\wavychars[no-halfstep]{This is in wavy style} and this is normal style.
\end{document}