如何在 2 条线与 Canvas 重叠时保持相同的颜色 alpha

How to keep the same color alpha when 2 lines are being overlapped with Canvas

我正在使用 Canvas 方法 drawLines(...) 并且我有 2 行 crossing/overlapping 彼此,这些行的颜色 alpha 为 0.3f。

问题是,当彼此交叉时,此 alpha 会累积,将它们的 crosspoint 转换为颜色 alpha 0.6f

有什么办法即使交叉也能保持原来的alpha值?

没有。这是不可能的,因为我们必须修改可组合项特定“部分”的 alpha 值,这不是一件容易实现的事情。你需要改变你的方法。

第 1 步。根据起点、终点和笔画宽度创建 Path

fun linePath(start: Offset, end: Offset, strokeWidth: Float) =
    Path().apply {
        // calculations from 
        val size = end - start
        val perpendicular = Offset(size.y, -size.x)
        val length = hypot(size.x, size.y)
        val normalized = Offset(perpendicular.x / length, perpendicular.y / length)
        val points = listOf(
            end + normalized * strokeWidth / 2f,
            start + normalized * strokeWidth / 2f,
            start - normalized * strokeWidth / 2f,
            end - normalized * strokeWidth / 2f,
        )
        moveTo(points.last())
        points.forEach(::lineTo)
    }

fun Path.moveTo(offset: Offset) =
    moveTo(offset.x, offset.y)

fun Path.lineTo(offset: Offset) =
    lineTo(offset.x, offset.y)

第 2 步。使用 clipPath 绘制需要的部分线:

Canvas(Modifier.fillMaxSize()) {
    val rect = Rect(Offset.Zero, size)
    val firstLinePath = linePath(
        start = rect.topLeft,
        end = rect.bottomRight,
        strokeWidth = 20f,
    )
    val firstLineColor = Color.Red
    val secondLinePath = linePath(
        start = rect.topRight,
        end = rect.bottomLeft,
        strokeWidth = 20f,
    )
    val secondLineColor = Color.Green
    val sharedAlpha = 0.5f

    // draw first line without intersection part 
    clipPath(secondLinePath, clipOp = ClipOp.Difference) {
        drawPath(firstLinePath, color = firstLineColor.copy(sharedAlpha))
    }
    // draw second line without intersection part
    clipPath(firstLinePath, clipOp = ClipOp.Difference) {
        drawPath(secondLinePath, color = secondLineColor.copy(sharedAlpha))
    }
    // draw intersection part with mixed color
    clipPath(secondLinePath) {
        val blendedColor = Color(
            ColorUtils.blendARGB(
                firstLineColor.toArgb(),
                secondLineColor.toArgb(),
                0.5f
            )
        )

        drawPath(firstLinePath, color = blendedColor.copy(sharedAlpha))
    }
}

结果: