马黑黑 发表于 2024-10-27 11:55

svg之mask遮罩

本帖最后由 马黑黑 于 2024-10-27 12:00 编辑 <br /><br /><style>
svg { outline: 1px solid gray; }
.wrap { font: normal 18px/24px sans-serif; }
.wrap > p { margin: 10px 0; }
</style>

<div class="wrap">
        <p>svg遮罩通过mask标签实现,该标签将创建一个遮罩层,层内建立由svg元素或渐变或其他合法的内容单独或多个组合而成的形状或形态,用以遮罩目标元素。例如,mask标签创建一个圆形图案得到的遮罩层就是一个圆,这个圆形遮罩层拿去作用于宽高大于等于圆的直径的矩形,矩形将不再是矩形,它只呈现出圆形的图案,该图案就是遮罩层的形状,颜色也可能发生变化——一切依据遮罩层的形状、色彩等状况。关于遮罩层的颜色,有一条重要的规则需要特别留意:白色被视为全不透明,黑色被视为全透明;用不透明(即白色)的遮罩层去遮罩目标对象,目标对象将呈现遮罩层的形状,反之,用透明(即黑色)去作用于目标对象,目标对象将不能呈现,而黑白之间的颜色通通视为中间色,中间色遮罩层作用下的目标对象会呈现但自身颜色会被改变。</p>
        <p>下面的效果,左边的圆和矩形中心重叠,圆的直径和矩形宽高相等。右边原本是左边图案的克隆,但使用了mask遮罩:圆放在mask遮罩层里做遮罩形状,矩形是被遮罩的对象:</p>
        <svg id="svg1" width="600" height="300"></svg>
        <p>参考代码:</p>
        <div class="hE"><pre id="pre1"></pre></div>
        <p>可以看到:右边的矩形因为使用了遮罩,其形状和颜色都发生了变化。</p>
        <p>mask标签除了必须的id属性,还有其他几个常规属性,x、y、width、height。不同于多数其他标签的相同属性,mask标签使用这些属性时一般用百分比,其中x、y缺省值各为 -10%,width、height缺省值各为 120%,这个知识点鲜为人知。下例我们依然使用圆形图案做遮罩层,作用在矩形上,请注意比对mask标签的x、y、width、height对被遮罩矩形的影响(绿色边框是只有描边的同尺寸矩形,做参照用):</p>
        <svg id="svg2" width="600" height="300"></svg>
        <p>参考代码:</p>
        <div class="hE"><pre id="pre2"></pre></div>
        <p>此外,mask标签还有 ① maskUnits 用来指定坐标系,缺省默认值是 objectBoundingBox 即svg默认坐标系,可选值 userSpaceOnUse 即用户空间坐标系;② maskContentUnits 属性的规范和可选值和 maskUnits 一样,不同的是所设定的坐标系基于即作用于mask标签内部元素。</p>
        <p>mask定义的遮罩层支持复用,但需要做一些目标对象位置的处理,例如目标对象应设置好能够受用遮罩层的位置,然后再用位移方式移开一定距离。最后给出的示例用来演示遮罩层的复用方法:我们在svg中设计一个用图片做的蒙版,然后分别应用于svg的两个矩形,第一个矩形用绿色填充,第二个矩形用红色填充,位置与绿色矩形一样,但随后使用了 transform 属性平移(translate)到右半部:</p>
        <svg id="svg3" width="400" height="200"></svg>
        <p>参考代码:</p>
        <div class="hE"><pre id="pre3"></pre></div>
        <p>(注:本文的svg绘制均由 svgdr 插件实时实现,参考代码的生成也由插件实时输出)</p>
</div>

<script>
loadJs = (file, callback) => {
        var sc = document.createElement('script');
        sc.charset = 'utf-8';
        sc.src = file;
        document.body.appendChild(sc);
        return sc;
};

var drFile = 'https://638183.freep.cn/638183/web/js/svgdr.js', hlFile = 'https://638183.freep.cn/638183/web/js2024/helight.js';
let res1 = loadJs(drFile), res2 = loadJs(hlFile);

res1.onload = () => {
        var dr1 = _dr(svg1);
        dr1.rect(50, 50, 200, 200, 'tomato');
        dr1.circle(150, 150, 100, 'gray');
        dr1.mask('mask1');
        dr1.circle(450, 150, 100, 'gray').addTo('mask1');
        dr1.rect(350, 50, 200, 200, 'tomato').set('mask', 'url(#mask1)');
        pre1.textContent = dr1.code(svg1);

        var dr2 = _dr(svg2);
        dr2.mask('mask2', '-50%', '-50%');
        dr2.circle(150, 150, 100, 'gray').addTo('mask2');
        dr2.rect(50, 50, 200, 200, 'skyblue').set('mask', 'url(#mask2)');
        dr2.rect(50, 50, 200, 200, 'none', 'green', 2);
        dr2.mask('mask2-1', '15%', '40%', '80%', '50%');
        dr2.circle(450, 150, 100, 'gray').addTo('mask2-1');
        dr2.rect(350, 50, 200, 200, 'skyblue').set('mask', 'url(#mask2-1)');
        dr2.rect(350, 50, 200, 200, 'none', 'green');
        pre2.textContent = dr2.code(svg2);

        var dr3 = _dr(svg3);
        dr3.mask('mask3');
        dr3.image('https://638183.freep.cn/638183/2-0.gif', 0, 0, 200, 200).addTo('mask3');
        dr3.rect(0, 0, 200, 200, 'green').set('mask', 'url(#mask3)');
        dr3.rect(0, 0, 200, 200, 'red').set('mask', 'url(#mask3)').transform('translate(200)');
        pre3.textContent = dr3.code(svg3);
};
</script>

花飞飞 发表于 2024-10-27 12:52

mask遮罩与PS里的知识点完美契合。。
白色被视为全不透明,黑色被视为全透明;这是常用的蒙板原理。在蒙板上黑画笔擦除,白画笔擦回
用图片做的蒙版,然后分别应用于两个不同颜色的矩形,这个就是剪贴蒙板。。


用PS常用的工具蒙板和剪贴蒙板来理解这个遮罩还是很有帮助滴。{:4_199:}

花飞飞 发表于 2024-10-27 12:54

其中x、y缺省值各为 -10%,width、height缺省值各为 120%,这个缺省值的设置很人性化的,好象蒙板要比元素图片大一些,四周围各大出10%,确保被罩住的感觉。。{:4_170:}

花飞飞 发表于 2024-10-27 12:57

注:本文的svg绘制均由 svgdr 插件实时实现,参考代码的生成也由插件实时输出。。
插件真是好用,涵盖好多代码和工作量,老师又辛苦啦。。

红影 发表于 2024-10-27 13:17

一点点学习,“白色被视为全不透明,黑色被视为全透明;”白色的就直接得到遮罩后的底图,黑色的就给整没了,这样比较好记。其他颜色的就得到了遮罩和底图的混合色。

红影 发表于 2024-10-27 13:21

第一块比较好理解,第二部分内容的<mask x="15%" y="40%" width="80%" height="50%"
遮罩自身设置位置和宽度挺难理解的,这个还得仔细琢磨一下。

红影 发表于 2024-10-27 13:23

最后那部分用动图做演示的,也是得到的混色呗。
这个遮罩自己有图片颜色,最多设置底板颜色跟它混合。

马黑黑 发表于 2024-10-27 16:49

红影 发表于 2024-10-27 13:23
最后那部分用动图做演示的,也是得到的混色呗。
这个遮罩自己有图片颜色,最多设置底板颜色跟它混合。

蒙层效果,不是blend模式

马黑黑 发表于 2024-10-27 16:52

红影 发表于 2024-10-27 13:21
第一块比较好理解,第二部分内容的

用过PS应该都能理解:蒙层有覆盖被遮罩对象,首先默认值是负数开始,都是 -10%,表示左边、上边都往左、往上10%,然后宽高120%,表示往右、往下也多拉开了10%。

而我这里的演示,是为了说明x,y,width,height 不同设置得到的效果。

马黑黑 发表于 2024-10-27 16:53

红影 发表于 2024-10-27 13:17
一点点学习,“白色被视为全不透明,黑色被视为全透明;”白色的就直接得到遮罩后的底图,黑色的就给整没了 ...

聪明,应该是吃过鱼了,或是最近吃了玉米

马黑黑 发表于 2024-10-27 16:53

花飞飞 发表于 2024-10-27 12:54
其中x、y缺省值各为 -10%,width、height缺省值各为 120%,这个缺省值的设置很人性化的,好象蒙板要比元素 ...

理解正确

马黑黑 发表于 2024-10-27 16:54

花飞飞 发表于 2024-10-27 12:52
mask遮罩与PS里的知识点完美契合。。
白色被视为全不透明,黑色被视为全透明;这是常用的蒙板原理。在蒙板 ...

原理其实都一样,可能存在的问题是一些细节的处理方式方法算法可能不尽相同

马黑黑 发表于 2024-10-27 16:55

花飞飞 发表于 2024-10-27 12:57
注:本文的svg绘制均由 svgdr 插件实时实现,参考代码的生成也由插件实时输出。。
插件真是好用,涵盖好多 ...

一点一点做吧,先不太管问题,先做出样纸来

花飞飞 发表于 2024-10-27 21:56

马黑黑 发表于 2024-10-27 16:53
理解正确

{:4_170:}这个比函数好懂啊。。

花飞飞 发表于 2024-10-27 21:58

马黑黑 发表于 2024-10-27 16:54
原理其实都一样,可能存在的问题是一些细节的处理方式方法算法可能不尽相同

原理一样就好办。。。细节处理还没感觉到,计算方法更是没有体会。。
反正么,我看着这个用PS的直观来理解,就好办得多。。{:4_170:}

花飞飞 发表于 2024-10-27 21:59

马黑黑 发表于 2024-10-27 16:55
一点一点做吧,先不太管问题,先做出样纸来

总是要一点一点完善的。。这个归纳处理挺细心的要。。
{:4_187:}

红影 发表于 2024-10-27 22:43

马黑黑 发表于 2024-10-27 16:49
蒙层效果,不是blend模式

嗯,两者还是有区别的。

红影 发表于 2024-10-27 22:45

马黑黑 发表于 2024-10-27 16:52
用过PS应该都能理解:蒙层有覆盖被遮罩对象,首先默认值是负数开始,都是 -10%,表示左边、上边都往左、 ...

就是这个不同位置有点想不出来移动的方向。

红影 发表于 2024-10-27 22:45

马黑黑 发表于 2024-10-27 16:53
聪明,应该是吃过鱼了,或是最近吃了玉米

哈哈,玉米也有功效啊{:4_173:}

马黑黑 发表于 2024-10-27 22:48

红影 发表于 2024-10-27 22:45
哈哈,玉米也有功效啊

玉米仅次于鱼。玉米本来叫鱼米。
页: [1] 2 3 4 5 6 7
查看完整版本: svg之mask遮罩