关于控制SVG描边属性缩放的神句vector-effect: non-scaling-stroke

3,407 阅读4分钟

在这篇文章不炫技,SVG+CSS3 旋转动画属性就能实现的梦幻效果的黄金螺旋效果中,曾经留下过一个小尾巴,就是关于描边属性随着缩放动效transform:scale()等比例缩放的问题,当时用尽了各种方法,也没有解决,尝试多定义一层,然后描边属性写在外层,依然不能奏效,描边依旧我行我素,这在做动效的时候,是个棘手的问题,最近准备写一篇关于“2018草莓音乐节”宣传视频的动画用SVG+CSS3来实现的文章,再一次遇到了这个问题,如果不能解决的话,效果完全不是需要的。举个例子说明:

描边粗细不变的放大效果
需要的效果是一个描边的素材,从中心放大,直到扩展到整个画布,缩放动效是很简单的,按照常规的定义方式,只需要定义transform:scale()属性的变化

@keyframes enlarge{
0%{opacity:0; transform:scale(1); transform-origin:center center}
100%{transform:scale(13); transform-origin:center center}
}
#heart{animation:enlarge 3s ease}

<path id="heart" d="" /> <!--心形对应的路径-->

这里顺便插播一个关于AI导出SVG描边形状的注意事项。设计师小伙伴们都知道,在AI中,描边是有三种类型的,内描边,外描边和居中描边。只有使用居中描边导出的路径才能在SVG中作为stroke描边属性。 还拿这个案例说明,心形对应的CSS属性是这样的

   stroke: #000;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-width: 8px;

但如果把描边改成内描边来看一下,心形图案会导出两个路径

<g>
<path d=""/> <!--心形形状对应的路径-->
<path d=""/> <!--黑色描边对应的路径-->
</g>

换句话说,默认给做了一个AI做了一个“轮廓化描边”也就是描边转路径的处理。所以在AI导出SVG时,除了特殊效果,尽量使用居中描边。可以有效简化代码量,增加代码的可读性。当然,还有最重要的一点,可以控制描边的缩放属性,下面继续。 加了缩放变形的动效来看一下效果

缩放动效

这等比例放大的描边,尤其在真实案例中,因为底图都是描边的元素,而且描边粗细是相等的,所以这种效果可以直接被pass掉了。怎么办?度娘了一下,似乎没有人提过类似的问题,更不要提解决方法了。(由此可见,SVG+CSS3动画不火啊)仗着一手蹩脚的英文重新搜了一下,然后在codepen上看到有人解决这个问题,试了一下,咣咣啋,就是我要的属性啊。下面隆重出场的就是

vector-effect: non-scaling-stroke

字面直译矢量效果:描边不缩放!! 所以,我只要把这句属性扔到图形的CSS属性中

    #heart{
    vector-effect: non-scaling-stroke;
    animation:enlarge 3s ease;
    }

然后看一下效果

完美解决问题,描边属性丝毫不受缩放影响! 这里写成内联CSS样式也是可以的,比如

  <path d="" vector-effect="non-scaling-stroke"/>\

当然了,作为好学的我,肯定要查一查还有没有其他相关的设置,然后在W3C中查到了如下的解释(而且是2013年的标准):
Sometimes it is of interest to let the outline of an object keep its original width no matter which transforms are applied to it. For example, in a map with a 2px wide line representing roads it is of interest to keep the roads 2px wide even when the user zooms into the map. To achieve this, SVG Tiny 1.2 introduces the 'vector-effect' property. Future versions of the SVG language will allow for more powerful vector effects through this property but this version restricts it to being able to specify the non-scaling stroke behavior.

'vector-effect'
Value: non-scaling-stroke | none | inherit
Initial: none
Applies to: graphics elements
Inherited: no
Percentages: N/A
Media: visual
Animatable: yes
Computed value: Specified value, except inherit

好吧,废话太多,简而言之,没啥用,要么不缩放,要么不定义,默认缩放。各位看官手下留情莫要打人。

最后结尾,以上仅限chrome浏览器测试效果~~

过一段时间会更新一篇文章关于草莓音乐节宣传视频的,里面会大量的用到这个属性定义。