Canvas绘制两条重叠线条时如何保持原有alpha透明度不叠加
Canvas半透明线条交叉alpha不叠加的实现方案
该问题的本质是Canvas默认使用SRC_OVER混合模式,绘制半透明内容时重叠区域的alpha值会自动累加,以下是3种可直接落地的解决方法:
方案1:合并Path一次性绘制
把所有需要绘制的线段都添加到同一个Path实例中,最终调用drawPath方法一次性完成绘制。同个Path内部的重叠描边区域不会触发alpha叠加,直接使用你设置的0.3f透明度即可。
示例代码(Android Kotlin):val linePath = Path() // 添加第一条线段 linePath.moveTo(100f, 100f) linePath.lineTo(500f, 500f) // 添加第二条线段 linePath.moveTo(100f, 500f) linePath.lineTo(500f, 100f) // 其余线段依次添加即可 val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.STROKE strokeWidth = 8f color = Color.parseColor("#FF0000") alpha = (0.3f * 255).toInt() // 统一设置透明度 } canvas.drawPath(linePath, paint)方案2:离屏缓冲分层绘制
先创建和绘制区域等大的离屏Bitmap缓冲,用不透明的画笔把所有线条绘制到缓冲上,最后把整个缓冲用alpha=0.3f的画笔一次性绘制到目标Canvas。这种方案适合需要保留Canvas原有底层内容的场景。
示例代码:// 初始化离屏缓冲,仅在尺寸变化时初始化一次即可 val offscreenBitmap = Bitmap.createBitmap(canvas.width, canvas.height, Bitmap.Config.ARGB_8888) val offscreenCanvas = Canvas(offscreenBitmap) val opaquePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.STROKE strokeWidth = 8f color = Color.parseColor("#FF0000") // 不设置透明度,默认完全不透明 } // 绘制所有线段到离屏缓冲 offscreenCanvas.drawLines(linePoints1, opaquePaint) offscreenCanvas.drawLines(linePoints2, opaquePaint) // 整体绘制到目标Canvas,统一应用透明度 val alphaPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { alpha = (0.3f * 255).toInt() } canvas.drawBitmap(offscreenBitmap, 0f, 0f, alphaPaint) // 频繁绘制场景注意及时回收无用Bitmap避免内存溢出方案3:修改混合模式为SRC
如果不需要保留绘制区域的原有底层内容,可以直接将画笔的混合模式设置为PorterDuff.Mode.SRC,新绘制的像素会直接覆盖已有像素,不会做alpha混合,重叠区域自然不会出现alpha叠加。
示例代码:val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.STROKE strokeWidth = 8f color = Color.parseColor("#FF0000") alpha = (0.3f * 255).toInt() xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC) } // 直接依次绘制所有线段即可 canvas.drawLines(linePoints1, paint) canvas.drawLines(linePoints2, paint)
内容的提问来源于stack exchange,提问作者Barrufet
相关产品推荐
相关产品推荐

