之前在公众号上看到一些密码解锁类SVG动画案例,觉得是一种不错的交互方式,最近抽空研究了一下此类效果的实现原理,并做了一个小案例,这次就带大家剖析解锁类SVG的实现细节。

实现原理

尽管解锁类动画在结构上来讲,标签的嵌套较多,结构略显复杂,但它的原理很简单,就是通过位移动画来实现按键的隐藏和触发。

正确按键都被放在各自独立的分组中,当用户未触发正确按键前,这些分组都隐藏在屏幕之外,只有当正确按键被触发后,才会通过位移动画移动到可以被点击的可视区域,为了演示在下面动画中我用不同颜色标识了各按键分组。

animation
实现原理动画演示

结构分析

首先在PS中制作一张按键背景图,然后在AI中导入这张背景图作为参考,在背景层之上,根据背景中按钮位置绘制一组圆形,导出到代码中使用。

准备背景图片
在AI中根据背景位置制作圆形按键

导出的按键代码如下图所示,圆形已经在正确的位置上并和背景图中的按键对齐,我们只需要将这个分组复制(每一位密码都需要这样的一个分组),用位移属性调整各分组的位置,然后添加交互代码即可。

<g>
  <circle cx="374" cy="358" r="49"></circle>
  <circle cx="543" cy="358" r="49"></circle>
  <circle cx="205" cy="496" r="49"></circle>
  <circle cx="374" cy="220" r="49"></circle>
  <circle cx="205" cy="220" r="49"></circle>
  <circle cx="374" cy="220" r="49"></circle>
  <circle cx="543" cy="220" r="49"></circle>
  <circle cx="205" cy="358" r="49"></circle>
  <circle cx="543" cy="496" r="49"></circle>
</g>

先将正确的密码按键放在各自的分组中,只有当用户点击了正确的密码才会触发该分组的位移动画,位移动画会将隐藏在屏幕右侧的下个正确按钮所在分组移动到当前位置,以此类推。

如下图所示,为了演示密码解锁的过程,我将每个正确按键所在分组用不同颜色来表示,这里正确密码”中秋”只有两位,分别用绿色和桔色表示。

将正确的密码按键放在各自的分组中

当用户点击正确密码”中”字时,会触发绿色分组的位移动画,将下个正确密码”秋”字移动到正确位置,因为”秋”所在的分组是”中”字的子分组,它会随着父分组一起移动。此时再点击绿色分组的其它按键不会有任何反应,因为每个分组的位移动画只会被触发一次。

//设置restart="never"确保位移动画只被触发一次
<animateTransform 
  attributeName="transform" 
  type="translate" 
  from="0 0" 
  to="-750 0" 
  dur="0.01s" 
  begin="click+0.1s" 
  fill="freeze" 
  restart="never">
</animateTransform>
点击”中”字后的效果

密码的个数和分组个数相同,如果需要更多的位数就需要嵌套更多的分组,下图是整个解锁案例的动画演示。

密码解锁类结构动画演示

按键的点击效果

通过在每个按键上应用透明度动画实现按钮的点击效果,因为不需要过渡效果,所以设置calcMode属性为discrete。

<circle style="opacity:0;">
  <animate 
    attributeName="opacity" 
    begin="click" 
    restart="always" 
    dur="0.1s" 
    keyTimes="0;0.5;1" 
    values="0;1;0" 
    fill="freeze" 
    calcMode="discrete" />
</circle>

用事件穿透修复ios上的bug

在iPhone上测试发现点击结果页面,会出现闪屏的现象,安卓设备上一切正常。我们可以用之前学到的事件穿透来修复这个ios上的bug,事件穿透原理可以看下我之前的教程《巧用事件穿透实现动画声音同时播放》。

在父容器中设置pointer-events为none,点击区域设置pointer-events为painted或者visible,让动画只在指定svg元素上触发。

<g style="pointer-events:none;" transform="translate(750, 0)">
  <g transform="translate(-750, 0)">
    <circle style="opacity:0;pointer-events:painted;">
    </circle>
  </g>
</g>

总结

细心的同学一定发现解锁类SVG并不能做到准确的输入控制,比如用户输入中x秋依然可以触发正确结果动画,由于公众号图文环境不支持逻辑代码,很难做到用户输错后的重置,尽管有缺陷,在我看来仍然是一种不错的交互方式。

点击”阅读原文”可下载本教程的源文件,对于代码基础薄弱的同学可扫下方二维码观看视频学习。本视频已经包含在SVG零基础教程的案例部分,视频中对代码细节和在AI排版导出过程做了更详尽的解释,有问题欢迎在讨论群里提出。

qr
关注