SVG动画开发实例四:SVG剪切路径和蒙版动画|小册免费学

SVG中的蒙版(mask)也可以叫遮罩裁剪路径(clip-path)可以简称裁剪。两者实现的效果是类似的,因此其动画效果可以统称为蒙版动画。

裁剪和蒙版

  • 共同点

蒙版或者裁剪定义的区域内是可见的,区域外不可见。共同点都是通过显示元素的一部分、隐藏另一部分实现的。

  • 区别

蒙版使用对象是图像裁剪使用对象是路径

裁剪路径和蒙版的一个重要区别就是:裁剪路径内的对象是可见的(可见部分完全显示,无法设置透明度),位于裁剪路径外部的部分不可见。而蒙版可以指定不同位置的透明度,可以使用渐变等属性,位于蒙版外的部分不可见。

通过下面的两个实例来对比两者的不同:

裁剪路径实例

使用clipPath元素表示裁剪路径。应用剪切路径时,使用clip-path属性引用clipPath元素即可。

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="">
    <defs>
        <clipPath id="cut-off-rect">
            <rect x="0" y="0" width="200" height="100" />
        </clipPath>
        <clipPath id="cut-off-circle">
            <circle cx="100" cy="260" r="100" />
        </clipPath>
    </defs>
    <circle cx="100" cy="100" r="100" clip-path="url(#cut-off-rect)" />
    <rect x="0" y="210" width="200" height="100" clip-path="url(#cut-off-circle)" />
</svg>
复制代码
body{
    width: 100%;
    height: 100vh;
}
svg{
    height: 500px;
}
复制代码

在上面代码中,在circle(半径为100的圆形)中使用clip-path属性定义了一个宽为200,高为100的rect元素矩形。这样,只有圆中被剪切路径覆盖的部分(上半圆)显示出来。

第二个图形同理,正方形中引用一个圆做剪切路径,只有剪切路径覆盖的部分显示出来。即剪切路径剪切出来。

clipPath元素通常放在defs元素内。

蒙版实例

使用mask元素来表示蒙版。蒙版可以指定不同位置的透明度,使用渐变等属性。

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
    <defs>
        <linearGradient id="Gradient">
            <stop offset="0" stop-color="white" stop-opacity="0" />
            <stop offset="1" stop-color="white" stop-opacity="1" />
        </linearGradient>
        <mask id="Mask">
            <circle cx="100" cy="100" r="50" fill="url(#Gradient)" />
        </mask>
    </defs>
        <rect x="0" y="0" width="200" height="200" fill="red" stroke="black" mask="url(#Mask)" />
</svg>
复制代码

如上,我们定义了一个mask元素,其内是一个圆circle,它填充了一个透明到白色的渐变。使用红色矩形rect应用蒙版,只有蒙版部分显示出来(渐变形式)

裁剪动画示例

动态扩展显示图片

实现一个如下的效果:

实现的原理为:svg中引入一个图片,然后图片通过clip-path`属性应用一个圆形剪切,这样就会显示最开始的一个小圆部分的图片。然后增大圆的半径,逐渐覆盖整个图像,使图像显示出来。

如下,是初始图片应用小圆剪切路径。

<svg viewBox="0 0 700 400">
    <title>Animated clip-path SVG</title>
    <defs>
        <clipPath id="cd-image-1">
            <circle id="cd-circle-1" cx="80" cy="160" r="30"></circle>
        </clipPath>
    </defs>        
    <image height="400px" width="700px" clip-path="url(#cd-image-1)"
        xlink:href="http://ue.qzone.qq.com/janilydemo/mask/clippath/img.jpg"></image>
</svg>
复制代码

然后,动态改变clipPath元素中circle元素半径的值,即r的值。使用css动画实现

.visible #cd-image-1 circle { 
    animation: visible-clippath 1s linear forwards; 
}
@keyframes visible-clippath {
    to {
        r:1364;
    }
} 
复制代码

点击图片添加visible类,实现动画效果

document.querySelector('svg').addEventListener('click',()=>{
    document.querySelector('svg').classList.toggle("visible");
});
复制代码

蒙版动画示例

文字渐变动画

实现一个如下的效果:

这4行文字,是利用蒙版或渐变实现的效果。分别对应:

  1. 单色(白色)渐变,也就是没有颜色的变化,但是有透明度变化。即透明度渐变。使用mask蒙版应用到元素上
  2. 多色渐变,即颜色透明度渐变,通过蒙版应用到元素上
  3. 文本元素使用渐变填充,同时通过蒙版将透明度渐变应用到元素上
  4. 文本元素使用渐变填充。未使用蒙版
<svg id="object" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 800 800" version="1.1">
     <defs>
         <linearGradient id="gradient-1" gradientUnits="userSpaceOnUse" gradientTransform="rotate(0)" x2="800" y2="0">
             <stop offset="0" stop-color="#FFFFFF" stop-opacity="0" />
             <stop offset="0.25" stop-color="#FFFFFF" stop-opacity="0.25" />
             <stop offset="1" stop-color="#FFFFFF" stop-opacity="1" />
         </linearGradient>
         <linearGradient id="gradient" gradientUnits="userSpaceOnUse" gradientTransform="rotate(0)" x1="0" x2="100%" y1="0" y2="0">
             <stop offset="0" stop-color="#000000" stop-opacity="0.5" />
             <stop offset="0.25" stop-color="#FF0000" stop-opacity="0.8" />
             <stop offset="0.5" stop-color="#00ff00" stop-opacity="0.3" />
             <stop offset="0.7" stop-color="#0000FF" stop-opacity="0.8" />
             <stop offset="0.7" stop-color="#0816e4" />
             <stop offset="1" stop-color="#FF5B99" stop-opacity=".5" />
         </linearGradient>
         <mask id="mask-1" maskUnits="userSpaceOnUse">
             <rect width="800" height="300" fill="url(#gradient-1)" />
         </mask>
         <mask id="mask" maskUnits="userSpaceOnUse">
             <rect width="800" height="300" fill="url(#gradient)" />
         </mask>
         <text id="txt" x="400" y="150" font-family="Arial Black" font-size="60" text-anchor="middle">SVG AWESOME</text>
     </defs>
     <!-- 透明度渐变,mask并不改变原图形的颜色 但是可以将透明度应用到元素上 -->
     <use xlink:href="#txt" fill="#FFDD00" mask="url(#mask-1)" />
     <!-- mask未改变图形的颜色 应用了透明度 -->
     <use xlink:href="#txt" y="120" fill="#FFDD00" mask="url(#mask)" />
     <!-- fill颜色填充可以使用url引用渐变等元素,使颜色更加多彩。同时加上了mask的透明度 -->
     <use xlink:href="#txt" y="240" fill="url(#gradient)" mask="url(#mask-1)" />
     <!-- fill颜色填充使用url,使颜色更加多彩。 -->
     <use xlink:href="#txt" y="360" fill="url(#gradient)"  />
 </svg>
复制代码

如下,为该svg的样式:

添加动画,如下,在浏览器提供的动画API requestAnimationFrame中,改变透明度渐变的角度(旋转是以[0,0]为圆心);改变颜色透明度渐变的X位移;

window.onload = function () {
   let i=0;
   let gradi_motion= () => {
       //i = i % 90;
       if(i>200){
           i=0;
       }
       let gradient = document.getElementById("gradient");
       let gradient1 = document.getElementById("gradient-1");
       gradient1.setAttribute('gradientTransform', `rotate(-${i})`);
       gradient.setAttribute('gradientTransform', `translate(${i*4},0)`);
       i++;
       requestAnimationFrame(gradi_motion);
   }
   window.requestAnimationFrame(gradi_motion);
};
复制代码

蒙版和渐变的几点总结

  1. 使用蒙版mask并不会改变图形元素的颜色。颜色有fill属性确定。
  2. 蒙版mask会将透明度应用到元素上。这也是和剪切路径的最大区别。
  3. fill属性颜色填充,可以使用url引用其他元素,比如渐变元素,实现颜色的渐变。如fill="url(#gradient)"
  4. gradientTransform是渐变元素(如linearGradient)的特有属性,在css中无法使用。gradientTransform="skewX(20) translate(-35, 0) rotate(0)"translateX无法使用。

本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享