0 结论
图片动画的 begin 参数值应设置 大于 0 的值,如 1s
具体可参考SVG SMIL动画的begin,end属性详解
1 问题代码分析
1.1 实现代码
首先看一个由SVG遮罩动画实现的骰子滚动动画,代码如下:
<svg viewBox="0 0 99 114">
<!--轮播动画-->
<g>
<!--第1组图片-->
<foreignObject x="0" y="0" height="100%" width="100%">
<svg style="margin: 0px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/qicPQRG4YVIE4ib3icibS1JL2kPoCHWphEShk5pI15RXtIDe5h1jYUDIqHuqwqQYtpY6GujicWRGicjwsw1ibqy9XZhEw/0?wx_fmt=png");background-size: 100%;" viewBox="0 0 99 114"></svg>
</foreignObject>
<!--第2组图片-->
<foreignObject x="100" y="0" height="100%" width="100%">
<svg style="margin: 0px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/qicPQRG4YVIE4ib3icibS1JL2kPoCHWphEShBbto0SE9libibDa8yOCTBQsBH6Vc9EtAEBzjWnGpM5lOdCwtqJRTFEew/0?wx_fmt=png");background-size: 100%;" viewBox="0 0 99 114"></svg>
</foreignObject>
<!--第3组图片-->
<foreignObject x="200" y="0" height="100%" width="100%">
<svg style="margin: 0px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/qicPQRG4YVIE4ib3icibS1JL2kPoCHWphEShlmDc5uofMjodb18DonTNtHF7hWKCXFFK3oABWcibd8icYguaICPkIiaEw/0?wx_fmt=png");background-size: 100%;" viewBox="0 0 99 114"></svg>
</foreignObject>
<!--第4组图片-->
<foreignObject x="300" y="0" height="100%" width="100%">
<svg style="margin: 0px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/qicPQRG4YVIE4ib3icibS1JL2kPoCHWphESh9d0iauOwlJlMdCVLbnGwLP5ZE3CsL91CeLuJ3K4N4ZDpKNGBQKruIuw/0?wx_fmt=png");background-size: 100%;" viewBox="0 0 99 114"></svg>
</foreignObject>
<!--第5组图片-->
<foreignObject x="400" y="0" height="100%" width="100%">
<svg style="margin: 0px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/qicPQRG4YVIE4ib3icibS1JL2kPoCHWphEShWonkbHPTE1Kpl2AbvxIO9xmzBGib2JMktSyN3vKUeSKKhFjlOQfGQEQ/0?wx_fmt=png");background-size: 100%;" viewBox="0 0 99 114"></svg>
</foreignObject>
<!--第6组图片-->
<foreignObject x="500" y="0" height="100%" width="100%">
<svg style="margin: 0px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/qicPQRG4YVIE4ib3icibS1JL2kPoCHWphEShokNjcvBpyMLorrTR8sp376M49fmicnfqTOMqY6fibeODUqgxNmgZdusw/0?wx_fmt=png");background-size: 100%;" viewBox="0 0 99 114"></svg>
</foreignObject>
<!--动画设置-->
<animateTransform attributeName="transform" type="translate" values="0 0;-200 0;-500 0;-300 0;-100 0;-400 0;" repeatCount="indefinite" fill="freeze" begin="0s" end="touchend" dur="3s" calcMode="discrete"></animateTransform>
</g>
<!--遮罩层-->
<g>
<foreignObject y="0" x="0" height="100%" width="100%">
<svg style="margin: 0px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/qicPQRG4YVIE4ib3icibS1JL2kPoCHWphEShk5pI15RXtIDe5h1jYUDIqHuqwqQYtpY6GujicWRGicjwsw1ibqy9XZhEw/0?wx_fmt=png");background-size: 100%;" viewBox="0 0 99 114"></svg></foreignObject>
<animateTransform attributeName="transform" type="translate" values="0 0;-100 0;" fill="freeze" begin="touchstart" dur="0.0001s" calcMode="discrete" restart="never"></animateTransform>
</g>
</svg>
1.2 原理阐释
既然定位为遮罩动画,那该动画必然由图片层与遮罩层组成,上述代码中的3-27行,链接了6张骰子的图片,由其左上角坐标值的变化
x="0" y="0";
x="100" y="0";
x="200" y="0";
x="300" y="0";
x="400" y="0";
x="500" y="0";
不难看出,底层图片排列方式为横向依此排列的,示意图如下
排列好图片后,需要设置图片动画,此处设置为 translate 即平移动画,按上述图片坐标依此设置平移终点。
<!--动画设置-->
<animateTransform attributeName="transform" type="translate" values="0 0;-200 0;-500 0;-300 0;-100 0;-400 0;"
repeatCount="indefinite" fill="freeze" begin="0s" end="touchend" dur="3s" calcMode="discrete"></animateTransform>
最后设置遮罩
<animateTransform attributeName="transform" type="translate" values="0 0;-100 0;" fill="freeze" begin="touchstart" dur="0.0001s" calcMode="discrete" restart="never"></animateTransform>
其中 values 参数指定了可显示的区域,即一个骰子面图片的范围,其余部分被遮挡不予显示
由以上几部分组成了一个完整的SVG遮罩动画。
2 问题分析
在手机端运行上述代码可知,不管用户在哪一刻点击骰子,都会定格在5点,原因是:
begin值为 0,没有偏移量,用户点击后,动画执行完毕,定格在最后一帧图片上,由上述代码可知,平移坐标内设置的最后一帧,正是5点对应的图片坐标。
而 begin 值设置设置为大于0的数之后,有了偏移量,故动画不会在结束后退回最后一帧,而是保留在了用户点击对应的图片处。
具体可参考SVG SMIL动画的begin,end属性详解
所以最后将上述代码更改为
<animateTransform attributeName="transform" type="translate" values="0 0;-200 0;-500 0;-300 0;-500 0;-300 0;-500 0;-300 0;-100 0;-400 0;-500 0;-100 0;-400 0;-300 0;"
repeatCount="indefinite" fill="freeze"
begin="1s" dur="3s" calcMode="discrete" end="click">
</animateTransform>
完美解决跳帧问题