我企图用 PorterDuffXfermode 来裁切一个圆,但是失败了,有人帮忙看下问题出在哪里吗?

2019-02-27 22:48:39 +08:00
 maninfog

代码如下:

   
   // 初始一下
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.FILL);
    mRectF.left = 0;
    mRectF.top = 0;
    mRectF.right = getWidth();
    mRectF.bottom = getHeight();
    
    // 先做了离屏缓存
    int count = canvas.saveLayer(mRectF,null,Canvas.ALL_SAVE_FLAG);
    
    canvas.drawRect(mRectF,mPaint); // 画了红色一个正方形
    mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    mPaint.setXfermode(mXfermode); // 设置 xfermode 为 DST_IN
    canvas.drawCircle(dp2Px(100),dp2Px(100),dp2Px(100),mPaint);//画了一个圆形与正方形相切
    
    canvas.restoreToCount(count); // 恢复画布的状态

预想的结果: 因为使用了 DST_IN 的模式进行裁切,所以应该显示下层交集,于是应该显示一个红色的圆。 实际显示:红色正方形。

尝试将 MODE 改为:PorterDuff.Mode.DST_OUT,显示效果与预期是一致的,显示的是去除了中心圆的正方形。

我去 github 看了很多前辈的实现思路,发现也是类似的代码,但是我写出来却不能达到预期的效果,很是苦恼,烦请各位大佬帮我看一下。

同时:对于这种实现方式,我还有一个疑问,PorterDuffXfermode 原理是将颜色混合,那么如果我们画了一个圆,paint 应该只能对这个圆范围内的颜色进行处理?为什么还能处理圆以外的像素呢?

9457 次点击
所在节点    Android
20 条回复
Cabana
2019-02-28 11:12:05 +08:00
mPaint 在每次用完后有 把 Xfermode 置 null 吗?
maninfog
2019-02-28 11:20:07 +08:00
@Cabana #1 这里 onDraw 只执行了一次,没有重绘,所以应该不是 paint 的问题,并且试了一下置空,还是异常
enkechan
2019-02-28 12:50:38 +08:00
哪有人说自己“企图”做某件事的,听起来像要干坏事哈哈
maninfog
2019-02-28 13:04:45 +08:00
@enkechan 主要是想将自己的意图明显表达出来,这里用这个词的确不太合适,应该用意图
Cabana
2019-02-28 14:25:51 +08:00
@maninfog
mRectF 大小对吗?
Cabana
2019-02-28 14:27:26 +08:00
是不是 dp2px 最后的值已经大于 mRectF 的范围了?
jamessky
2019-02-28 15:22:32 +08:00
问问
maninfog
2019-02-28 15:37:56 +08:00
@Cabana #5 mRect 的大小是对的,就是取的宽高;然后 dp2px 这个值也是对的,不然 DST_OUT 的效果也会是错的。硬件加速也关闭了。
NaiveSimpleYoung
2019-02-28 17:07:24 +08:00
“试图”比较合适
Cabana
2019-02-28 18:31:43 +08:00
@maninfog 貌似,最后被 Draw 下来的那一方,不管是 SRC 还是 DST 必须是 Bitmap 才可以。
SRC_开头的 需要 SRC 是 Bitmap,DST 开头的需要 DST 是 Bitmap
Cabana
2019-02-28 18:34:31 +08:00
@Cabana 直接在 canvas 上 draw SRC_的一系列 Xfermode,会生效是应为 canvas 本身自带一个 Bitmap
Cabana
2019-02-28 18:40:55 +08:00
另外,裁剪难道不应该用 SRC_IN 吗?为啥会用 DST_IN ? SRC_才是保留原图,DST_是保留后贴上去的图形呀
maninfog
2019-02-28 18:43:52 +08:00
@Cabana #12 1.应该用 DST_IN , 你应该是理解反了。因为 dst 才是先放上去的。2.你看我 append 的代码,使用 drawPath 就能行。
Cabana
2019-02-28 18:45:49 +08:00
pps:PorterDuffXfermode 并不是简单的将颜色混合而已,如果将 SRC 和 DST 看做集合的话,在合成模式下它能够做交集,并集,差集;在混合模式下,才是你说的颜色混合

https://developer.android.com/reference/android/graphics/PorterDuff.Mode
Cabana
2019-02-28 18:47:54 +08:00
@maninfog
SRC--->Source
DST--->Destination
Cabana
2019-02-28 19:12:09 +08:00
傻逼了,再去看了下 google 的文档,是又记反了🥶
maninfog
2019-02-28 20:32:55 +08:00
@Cabana #14 也没有设置模式的 API 啊
fyyz
2019-02-28 21:28:14 +08:00
还好没有用“妄图”
wsxyeah
2019-03-02 18:20:54 +08:00
至少贴下对应的实际效果截图吧
maninfog
2019-03-04 03:50:07 +08:00
@Cabana #15 感谢帮忙分析,目前已经能达到预期效果了,具体请看我最新的 append。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/539428

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX