动效给的效果是一个头耳朵话筒胳膊都在动的摇摆效果,这个不能传视频,大体图片展示如下image.png

紧靠前端css实现这种动效比较难,因此决定采用Lottie实现。

后面才了解到,产品希望小猴子的脸是孩子的头像图片,于是修改了Lottie的json文件,将动效里面的头像换成自己的,但是实现效果如下

image.png

看了很多关于lottie的文章,查找每一个属性的作用,找到一个 tm(剪裁路径) 的属性,但是都仅仅是提到这个属性,具体怎么用完全不知道,看一下里面的json结构,想去实现剪裁效果简直一脸蒙。

image.png

只能另辟蹊径,有什么办法获取头像之后把它变成圆的呢?

  • 后端处理返回圆形头像
  • 前端剪裁头像,然后替换

后端处理的话,也不太现实,还要后端实现,而且会占用服务器处理。

前端处理,忽然想到之前用canvas生成海报图,那是否可以绘制圆形图片呢?搜了一下果然可以,大喜过望。

关键在于是clip()API,这个API,可以用你指定的形状在画布上裁剪一部分出来,然后,接下来你在画布上的操作只有在该形状区域内可见,如果还有后续还有对画布的其他地方有操作,可以使用restore()接口恢复,但是必须在使用clip接口前用 save() 接口保存canvas的状态。

实现圆角方案核心代码如下

<canvas id="canvas" style="border: 1px solid;"></canvas>
<script>
  function circleImg(ctx, img, x, y, r) {
    ctx.save();
    var d =2 * r;
    var cx = x + r;
    var cy = y + r;
    ctx.arc(cx, cy, r, 0, 2 * Math.PI); // 绘制圆形
    ctx.clip(); // 从画布上剪裁圆形
    ctx.drawImage(img, x, y, d, d);
    ctx.restore();
  }

  var img = new Image();
  img.src = 'xxx';
  var canvas = document.querySelector("#canvas");
  var context = canvas.getContext("2d");
  circleImg(context, img, 100, 20, 50);
</script>

使用canvas的道路总是曲折的,刚准备运行看效果,就提示 Cannot read property 'getContext' of null"

大意就是canvas获取不到 getContext属性,所以只能等html加载完成后执行js代码,写在window.onload里即可。

绘制完成后,还需要将canvas转成图片,

canvas.toDataURL("image/png")

然而,又是一口老血... 控制台红红的提示,

**Uncaught DOMExc****eption: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
**

经google 发现原来是受限于 CORS 策略,会存在跨域问题,虽然可以使用图像(比如append到页面上)但是绘制到画布上会污染画布,一旦一个画布被污染,就无法提取画布的数据,比如无法使用使用画布toBlob(),toDataURL(),或getImageData()方法;当使用这些方法的时候 会抛出一个安全错误

这就简单了,给图片添加crossOrigin属性,

img.setAttribute("crossOrigin",'Anonymous')

然后将demo迁移到项目里运行,咦,其它图片路径怎么找不到了,多页面服务,根路径好像对不上

image.png

难道只能把所有图片上传到oss,然后替换成网络图片?这样维护起来就比较费劲了。

前端的魅力是无穷的,解析不了json文件路径,但是可以解析js路径啊,最后把整个json文件改成js,里面的图片都用require引入,最后export 出来,完美解决!

最终实现效果,so cool!

image.png

参考文章:https://www.jianshu.com/p/9a6...


旅图灬
905 声望43 粉丝

任何事物都有它的正反面,研究技术要全面