如果不是特别想做的话,还是在文章的开头劝退一波,因为 付出 >> 收获,不论如何,最终的反响不是特别好。

回归正题,前前后后弄了一周多的时间,期间都是高强度研究的那种,踩过了很多坑,希望大家复现的时候少踩些坑。

#

最初的时候是一篇名叫《2020,我的新年签居然是…》的推送吸引了大家的注意力,站在他们的肩(chuang)膀(yi)上,我们做了进一步的升华。

首先需要了解一下微信文章推送的定位,它是一个阉割了的网页,只保留了文本媒体样式这三种内容,而我们正常网页交互所使用的 js 则完全不能使用,甚至连 <style></style> 这样的样式标签也会被移除。一句话概括,你只能展示内容,而无法与读者互动,无法交互。

svg 是为数不多的可以用到的可定制式的交互样式,它的出身可以百度如果你感兴趣。svg 能够做到的交互我目前知道两个[1],简要概括就是:透明度/角度变化(按照固定轨迹)移动,基本上所有的交互都是这两个交互的延伸组合

透明度/角度变化:实际中用到的就是点击空白处显示文字
(按照固定轨迹)移动点击移动抽奖等。

#

抽签的本质上就是签高速的移动,可能有些人不太理解,我解释下。如果不想了解或者觉得我解释的不清楚可以跳过或者看《为什么高速顺时针旋转的车轮看起来像是缓慢的逆时针旋转?》

我们偶尔看公路上的车轮会保持静止,因为车轮速度过快,每次看到的时候车轮都保持同一个位置,这就是高速带来的静止效果。svg 有一个参数就是可以让某一秒的画面代替动画中间的间隙效果,后面会详细介绍。

#

签的所有设计工作在 Adobe illustrator 中进行,后续的修补和动画通过修改代码完成。

在所有工作开始前一定要确定的事情是你整个画布的大小,后续所有的调整和动画都是基于数值计算的,如果最后才发现开始设计得不统一,再回来修改的话,等于之前所有的工作都要重做一遍。[2]

我选取的画布大小是 640*960,后续所有的参数都是基于这个。

新建画布的时候,一定要去画布预设里把文档的出血设置成 0,出血是为了打印时四周预留足够的空间,但我们要精确计算到像素,所以必须要刨除这些不确定因素。

接下来就是画面能动起来的重中之重:图层结构

在介绍之前先了解一下 Adobe illustrator编组功能,编组功能的作用是能够让许多对象作为一个整体进行编辑等后续操作。体现在 svg 代码中则易于理解些,即众多对象被 <g></g> 标签包裹。

将图层结构与代码结构综合理解,有助于对整个动画的原理进行理解,如果觉得有些难以理解,可以跳过,只要按步骤做即可。

首先说图层结构,图层结构总体设计如下(假设16张签面):

图层结构

图1 图层结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
新年签设计
├── 前景
| ├── 签面1
| | ├── “门”字
| | ├── “门”字
| | ├── “满”字
| | ├── “绩”字
| | └── 签1背景图
| ├── 签面2
| ├── ...
| └── 签面16
├── 背景
| ├── 2020文字
| ├── 老鼠图案
| ├── ...
| └── 红色背景

接下来详细讲一下。

首先要把签上动的部分不动的部分分开,不动的部分放在背景层,只要放在背景层里,细致的结构无须考虑;动的部分放在前景层,每个签面内容都编组为一个整体,16个整体在前景层里是平行关系,处于同一层次。

每个签内容保证在编组里即可,内部的细节层次结构也都不影响。

接下来的重点是,每个签的位置摆放。16个签依次水平等间距摆放即可。

需要注意 png 格式的图片大小不能超过 100kb[3]

设计图

图2 设计图

摆放时需要满足的要求是:画布宽度中只允许出现一个签,长度为 640 的画布每个签之间的水平间距应该大于等于640

图2门门满绩相对于画布左上角的相对位置是:x:131 y:164,那么瘦十斤相对于画布左上角的位置应该是:x:131+640 y:164

等整体设计完成之后,就可以导出了。

导出选项

图3 导出选项

选择导出为 svg,然后需要注意两个参数:

  1. 样式选择为 演示文稿属性[4]
  2. 图像选择为 链接[5]

然后你就拥有了以 <svg></svg> 包裹的签代码,就可以添加动画了。


写了俩小时写不动了,歇会儿😂


#

在用文本编辑器打开 svg之后,你会看到如下的一个标签结构。

1
2
3
4
5
<svg xmlns="http://www.w3.org/2000/svg" 
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 640 96000">
...
</svg>

首先要做的是将 svg 标签属性里的 viewBox 大小设置为我们的画布大小,改为 0 0 640 960

Adobe illustrator 里的文档结构在 svg 代码里会完全反过来。

1
2
3
4
5
6
7
8
9
10
11
12
13
<svg xmlns="http://www.w3.org/2000/svg" 
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 640 9600">
<g>
// 背景层
</g>
<g>
<g>签16</g>
...
<g>签2</g>
<g>签1</g>
</g>
</svg>

添加动画的方法非常简单,在属于前景层的 <g></g> 里添加代码即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<svg xmlns="http://www.w3.org/2000/svg" 
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 640 9600">
<g>
// 背景层
</g>
<g>
<g>签16</g>
...
<g>签2</g>
<g>签1</g>
<animateTransform
attributeName="transform"
type="translate"
values="0 0;-640 0;-1280 0;...;-8960 0"
begin="0s"
dur="0.45s"
end="click"
fill="freeze"
calcMode="discrete"
repeatCount="indefinite"></animateTransform>
</g>
</svg>

需要自行修改的属性和解释的属性如下,其它没解释的就自行百度即可。

  1. type 设置为 "translate",就是移动的意思。
  2. values 设置为每个签的水平间距,值为负,即 0 0-640 0-640*2 0-640*3 0,以此类推。
  3. begin 设置为 0,动画一开始就进行。
  4. dur 为整个动画持续时间,自行设置。
  5. end 何时结束动画,点击结束,即 click
  6. fill 就是上文提到的动画间隙如何填充,就用固定的画面填充即可,即 freeze
  7. repeatCount 重复次数,在没点击之前肯定是无限次重复啦。

至此动画已经可以动起来并且点击停止了,再加一个封面图片就可以了,然后设置封面点击一次就消失。这里可以用透明度降低的动画效果,也可以用移动到画布之外的动画效果。

前面说过 svg 的标签结构和图层结构是反的,所以新加的封面放在整个文档的最下方,和前景背景同级。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<svg xmlns="http://www.w3.org/2000/svg" 
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 640 9600">
<g>
// 背景层
</g>
<g>
// 前景层
</g>
<g>
// 封面层
<rect y="1.5" fill="#b6352f" width="649" height="960"></rect>
<image width="640" height="960" href="https://mmbiz.qpic.cn/mmbiz_jpg/g84wSb3VFX7sDq8k89pwzNiaQIibwiav6P7QQrPNCfVibmRAKhlrz1868ybEGAxzKpJaZovZpUw69P15Daqsltiaic7A/0?wx_fmt=jpeg"></image>
<animatetransform
attributename="transform"
type="translate"
values="0 0;10000 0"
begin="click"
dur="0.01s"
fill="freeze"
calcmode="discrete"
repeatcount="1"></animatetransform>
</g>
</svg>

至此,抽签的 svg 功能方面已经全部完成,下面的额外工作是设计优化微信公众平台适配

#

虽然签做好了,但是有一个很让人无语的问题:只有签面的区域点击才可以,红色背景点击没有办法令签停止。

有效区域示意图

图4 有效区域示意图

我的第一个解决方法是:将签面的背景图补成整个画布的大小,周围填充透明像素

当时想出这个办法的时候我都为自己的机智而鼓掌,结果到最后一步的时候现实终于将魔爪伸向了我这只小猫咪了。微信png图片最大允许100KB,我整个人都傻了。

前面都写了画布图片大小影响到整个制作过程,所以我又从头制作了一遍,呵呵。

作为一个完美主义者,最终还是找到了一个解决方案:在每个签里加一个拉伸到整个画布大小的透明图像。这个方法亲测可以把有效区域扩大至整个画布,问题解决。这个透明图像放在签编组的任意位置都可以,反正是透明的,不会造成遮挡。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<svg xmlns="http://www.w3.org/2000/svg" 
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 640 9600">
<g>
// 背景层
</g>
<g>
// 前景层
<g data-name="门门满绩">
// 透明图像
<image width="640" height="960" href="https://mmbiz.qpic.cn/mmbiz_png/g84wSb3VFX4WIFj78My2uNfKb2aBE3j32DkhOa6UEmCy5icgPPLZibMLczvJTMVJGfO1Z3y9eWef5emxn78gb6Ww/0?wx_fmt=png"></image>
...
</g>
</g>
<g>
// 封面层
</g>
</svg>

然后把所有的图像传到微信后台然后替换一下链接即可。
这里需要注意 Adobe illustrator 导出的 image 标签里的地址属性是 xlink:href="图像地址",微信无法识别,需要改成 href="图像地址",批量替换即可。

#

前前后后忙活了好几周,踩了好多坑,也有很多本来不会对整体有影响的小错误出现,唯一促使自己坚持下来的动力就是:做都做了我有强迫症啊喂,这地方多出几个像素我受不了我是完美主义者啊,既然做了,那就做好对阅读量充满期待,万一呢?。前几个是本性,后一个是希冀。事实证明,爬得越高,摔得越惨。平平淡淡的反响,掩饰不住的失落,更别提当时网络的不畅导致二维码没有正常跳转。

但这就是生活啊,人生啊~永远对未知的结果抱有恐惧和期待。

不过在我心里,我已经做到最好了。

https://onns.xyz/s/2020q

#


  1. 可能有很多,但我只了解到两个。 ↩︎

  2. 坑1,一定要注意顺序。 ↩︎

  3. 坑2,微信后台只允许上传小于100kb的透明图片,超过的会强制转换为jpg,本来设计的效果全没了,真是个大坑。 ↩︎

  4. 把Styling选择为Presentation Attributes,这样导出的SVG就不含有style,而且元素的样式也会通过标签属性进行设置,而不使用style内联css。 ↩︎

  5. 坑2,选别的会把图片变成base64编码后直接保存到文档里,很大的文档导致层次混乱。 ↩︎