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行文字,是利用蒙版或渐变实现的效果。分别对应:
- 单色(白色)渐变,也就是没有颜色的变化,但是有透明度变化。即透明度渐变。使用mask蒙版应用到元素上
- 多色渐变,即颜色透明度渐变,通过蒙版应用到元素上
- 文本元素使用渐变填充,同时通过蒙版将透明度渐变应用到元素上
- 文本元素使用渐变填充。未使用蒙版
<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);
};
复制代码
蒙版和渐变的几点总结
- 使用蒙版mask并不会改变图形元素的颜色。颜色有fill属性确定。
- 蒙版mask会将透明度应用到元素上。这也是和剪切路径的最大区别。
fill
属性颜色填充,可以使用url引用其他元素,比如渐变元素,实现颜色的渐变。如fill="url(#gradient)"
gradientTransform
是渐变元素(如linearGradient
)的特有属性,在css中无法使用。gradientTransform="skewX(20) translate(-35, 0) rotate(0)"
,translateX
无法使用。