混合模式在 Jetpack Compose 中无法按预期工作

问题描述 投票:0回答:1

我正在尝试实现一个带有点(如圆圈)的折线图。但无论我使用哪种混合模式,圆圈都会显示线条的交点。这是实际结果的图片:

enter image description here

我希望我的圆圈是纯色的。 这是我的实现:

path.apply {
            data.forEach { value ->

                val textResult = textMeasurer.measure(value.toString())
                val textOffsetX = -20f - textResult.firstBaseline

                yCursor = graphDepth - ((value - data.min()) * oneDegree)
                val textOffsetY = yCursor - textResult.lastBaseline / 2

                drawText(textResult, color = graphStyle.textColor, topLeft = Offset(textOffsetX, textOffsetY))
                drawLine(
                    Color.Gray,
                    start = Offset(0f, yCursor),
                    end = Offset(xCursor, yCursor),
                    strokeWidth = 3f,
                    pathEffect = PathEffect.dashPathEffect(
                        intervals = floatArrayOf(
                            10f,
                            5.dp.toPx()
                        )
                    )
                )
                moveTo(xCursor, yCursor)
                xCursor += oneInterval
            }
            xCursor = 0f
            yCursor = graphDepth - ((data.first() - data.min()) * oneDegree)
        }

        path.apply {
            moveTo(0f, yCursor)
            data.forEach { value ->

                yCursor = graphDepth - ((value - data.min()) * oneDegree)
                lineTo(xCursor, yCursor)
                drawLine(Color.Gray, start = Offset(xCursor, 0f), end = Offset(xCursor, graphDepth))
                moveTo(xCursor, yCursor)
                xCursor += oneInterval
            }
            xCursor = 0f
            yCursor = graphDepth - ((data.first() - data.min()) * oneDegree)
        }

        val circlePath = Path().apply {
            moveTo(0f, yCursor)
            data.forEach { value ->

                yCursor = graphDepth - ((value - data.min()) * oneDegree)
                drawCircle(
                    color = graphStyle.jointColor,
                    radius = graphStyle.jointRadius,
                    center = Offset(xCursor, yCursor),
                )
                moveTo(xCursor, yCursor)
                xCursor += oneInterval
            }
        }

        drawPath(
            path,
            color = graphStyle.lineColor.copy(alpha = 0.5f),
            style = Stroke(width = graphStyle.lineStroke),
            blendMode = BlendMode.Clear
        )

        drawPath(
            circlePath,
            color = graphStyle.jointColor,
        )


我在哪一部分缺少什么?你能帮我吗?

提前致谢。

canvas path android-jetpack-compose android-canvas linechart
1个回答
0
投票

要使混合模式在 Jetpack Compose 中工作,您需要绘制一个离屏缓冲区。

这可以通过三种方式完成。通过将 alpha 设置为小于 1f,

Modifier.graphicsLayer{compositingStrategy = CompositingStrategy.Offscreen }

或者使用

保存和恢复图层
private fun DrawScope.drawWithLayer(block: DrawScope.() -> Unit) {
    with(drawContext.canvas.nativeCanvas) {
        val checkPoint = saveLayer(null, null)
        block()
        restoreToCount(checkPoint)
    }
}

此解决方案的好处是您可以设置要应用混合模式的部分或哪些绘图将受到混合模式的影响,而其他 2 种方法使您的可组合项完全使用混合模式绘制。

@Preview
@Composable
fun BlendModeSample() {
    Canvas(
        modifier = Modifier.fillMaxSize().background(Color.DarkGray)
            .graphicsLayer {
                compositingStrategy = CompositingStrategy.Offscreen
            }

    ) {
        drawWithLayer {
            drawLine(
                color = Color.White,
                start = Offset(100f, 100f),
                end = Offset(300f, 100f),
                strokeWidth = 10f
            )

            drawLine(
                color = Color.White,
                start = Offset(340f, 100f),
                end = Offset(540f, 100f),
                strokeWidth = 10f
            )

            drawCircle(
                color = Color.Red,
                center = Offset(320f, 100f),
                blendMode = BlendMode.Clear,
                radius = 50f
            )
        }

        drawCircle(
            color = Color.Red,
            center = Offset(320f, 100f),
            radius = 50f,
            style = Stroke(10f)
        )

    }
}

通过应用 BlendMode.Clear 内部图层,您可以删除圆内的任何线条部分,同时您可以在相同位置绘制带有描边的圆,而无需应用任何混合模式

使用路径时的另一个选项是使用clipPath(pathToClip) {}来剪辑此路径内的任何内容或

androidx.compose.ui.graphics.Path().op()

© www.soinside.com 2019 - 2024. All rights reserved.