近期开发的时候遇到一个这么简单的问题:svg的clipPath与移动动画一起使用,元素移动时会在其所在组(g标签)的clipPath外面出现一个1px的边框,非常难看,如图:

过程

如是来还原这个bug,首先创建一个很简单的svg,中间放一个圆作为动画元素、一个菱形作为修剪路径(clip-path)。这里还添加了一个一模一样菱形作为背景以展示修剪路径

1
2
3
4
5
6
7
8
9
<svg class="svg-root" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<clipPath id="cp">
<polygon points="14,50,50,23,86,50,50,77"></polygon>
</clipPath>
<polygon fill="#000" points="14,50,50,23,86,50,50,77"></polygon>
<g class="center-group" clip-path="url(#cp)">
<circle class="center-circle" fill="orange" cx="50" cy="50" r="20"></circle>
</g>
</svg>

首先仅仅让圆发生简单的平移,可以发现其与修剪路径没有任何不兼容。

1
2
3
.center-circle {
transform: translate(-20px, -20px);
}

然后让中间的圆动起来,选择一个简单的css平移动画即可

1
2
3
4
5
6
7
8
9
10
11
@keyframes centerAnimation {
from {
transform: translate(-20px,-20px);
}
to {
transform: translate(20px,20px);
}
}
.center-circle {
animation: centerAnimation .8s linear infinite alternate-reverse;
}

这时便可发现,在修剪路径外,出现了1px的元素漏影

解决

※:如果在动画的元素上也加上clip-path,则可以解决

原因未知,怀疑是计算动画和计算clipPath的位置有偏差,当修剪区域是正方形或者倾斜45°的正方形时不会有这样的问题,当放缩SVG或者SVG有一定的大小时也不会有这样的问题

加上了内部元素的 clip-path 后,两层clip path的计算让这样的偏差消失了(猜的)

1
<circle clip-path="url(#cp)" class="center-circle" fill="orange" cx="50" cy="50" r="20"></circle>

局限

但是实际上,只有当元素一开始就全部在修剪路径内时,这样做才是OK的。

当圆初始时有部分处于修剪路径外时,圆自然已被裁切,因此在动画中显示的也是裁切后的部分,故而不能用这样的方法来解决

demo

clippath与动画的bug演示