Egret社区
本帖最后由 fightingcat 于 2016-7-22 14:32 编辑

看官方文档可以知道,DisplayObject有个blendMode属性,可以设置混合模式:
官方示例:http://edn.egret.com/cn/docs/page/586
但是这个混合模式是作用于整个舞台的,例如,如果设置了ERASE模式,这个DisplayObject之下的所有东西都会被擦除。但很多时候我们只是需要擦除特定对象的内容,这时候我们可以使用RenderTexture。先来看一下演示(就拿dom开涮吧,对,就是群里的dom
):

GIF.gif
在线演示:https://fightingcat.github.io/egret/ReverseMaskDemo/index.html
源码:https://github.com/fightingcat/EgretReverseMaskDemo

原理就是先用Sprite创建一个黑底模板,然后把遮罩图加进去(Sprite继承自DisplayObjectContainer),设置遮罩图的blendMode为Erase模式,然后把Sprite渲染到RenderTexture,最后用这个RenderTexture创建一个位图,这个位图就是最终的反遮罩图了。

这个例子只是演示原理,虽然也可以用PS另创建一个遮罩图,但是也存在一些需要动态擦除的情景。例如用Graphics做画图板,需要实现橡皮擦时。另外需要注意的是,用RenderTexture创建的位图会随RenderTexture内容改变,所以如果有动态绘制的需求就不必反复创建啦。

有兴趣的可以继续探索实现更多的效果,也可以封装一些易用的功能。

更新:
群里的J.C( @jcyuan )指出当启用cacheAsBitmap时会创建独立的RenderBuffer,此时blendMode就不会影响其他节点了。对于大部分静态的情景,这个方法更简单。这个方法和本文RenderTexture的方法的区别是,cacheAsBitmap是被动渲染,RenderTexture是主动渲染。当cacheAsBitmap的显示对象的内容变化时,只是标记了显示列表变脏,要等待显示列表渲染时才会绘制,所以参与遮罩的对象都要加到显示列表中。RenderTexture则是在主动调用drawToTexture时绘制,而且不需要加入显示列表中(当然最终生成的结果还是要加入显示列表的)。

结论:使用cacheAsBitmap更简单,使用RenderTexture则可以主动控制渲染的时机,可以根据需要自行选择。
分享到 :
6 人收藏

7 个回复

倒序浏览
奋发向上的岩哥  斑竹 | 2016-7-21 14:11:50
_Syri  登堂入室 | 2017-6-19 11:18:59
如何运用到动态橡皮擦上去呢?
撒旦娃娃  登堂入室 | 2017-7-14 18:14:34
貌似遮罩只能用egret.Bitmap  或者 sprite的矢量绘图。。用其他的比如sprite位图 eui.Image  eui.Rect等显示对象做反向遮罩都有问题。。
根木换心  登堂入室 | 2018-4-17 17:57:35
很强    已实现
alexbest  初窥堂奥 | 2018-9-6 16:09:13
橡皮擦真心不好弄  设置了ERASE后会把其底部的所有都给擦掉  
zhangyuantao  登堂入室 | 2018-9-10 16:22:36
本帖最后由 zhangyuantao 于 2018-9-10 16:47 编辑

把自身的blendMode也设置擦除就不会一擦到底了,我也是误打误撞试出来的,求官方解释:
private onAddToStage(e){
                this.width = this.stage.stageWidth;
                this.height = this.stage.stageHeight;
                this.graphics.beginFill(0, 0.8);
                this.graphics.drawRect(0, 0, this.width, this.height);
                this.graphics.endFill();

                // 自身擦除模式加上镂空circle区域就不会一擦到底,什么原理?但是周围是一擦到底,但是this.graphics.beginFill(0, 0.8);设透明度后也不会一擦到底
                // 如果如果0.8透明度,可以看到舞台的半透明黄色底色。
                this.blendMode = egret.BlendMode.ERASE;

                let circle = new egret.Shape();
                circle.blendMode = egret.BlendMode.ERASE;
                circle.graphics.beginFill(0xffffff);
                circle.graphics.drawCircle(0, 0, 100);
                circle.graphics.endFill();
                circle.x = 100;
                circle.y = 100;
                this.addChild(circle);
        }
如果是bug官方发现会不会改了
QQ截图20180910164808.png
zhangyuantao  登堂入室 | 2018-9-10 16:23:42
zhangyuantao 发表于 2018-9-10 16:22
把自身的blendMode也设置擦除就不会一擦到底了,我也是误打误撞试出来的,求官方解释:
private onAddToSta ...

我去年在一个项目已经这样用了 哈哈
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|京网文[2014]0791-191号|京ICP证150115号|Egret社区 ( 京ICP备14025619号 )

Powered by Discuz! X3.4 © 2001-2019 Comsenz Inc.

返回顶部