Compose Canvas 的 'rotate' 转换造成的混淆行为

Confusing behaviour by the 'rotate' transformation of Compose Canvas

我有一个简单的可组合项 Canvas,它在不同位置多次绘制一个形状,我希望根据特定算法对形状的每次迭代应用旋转。但是,我无法完全控制 canvas 中形状的定位,因为 rotate 转换似乎应用了它自己的 translation 转换。这是我的

    @Preview
    @Composable
    fun CanvasCollosum() {
        val painter = rememberVectorPainter(image = ImageVector.vectorResource(id = R.drawable.tick))
        Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center){
            Canvas(modifier = Modifier.height(200.dp).aspectRatio(1f)) {
                with(painter) {
                    repeat(12) {
                        (it * 30f).let { angle ->
                            translate(
                                top = 0f, // Some translation is still applied by 'rotate'
                                left = 0f
                            ) {
                                rotate(angle) {
                                    draw(
                                        Size(100f, 100f),
                                        colorFilter = ColorFilter.tint(Color.White)
                                    )
                                }
                            }
                        }
                    }
                }
            }
        }
    }

因此,由于某种原因,这里所有形状的定位(一共12个)都呈现为圆形,这与我的预期完全不同。我可以假设它与旋转的 'pivot' 有关。但是,它默认设置为 Canvas 的中心,这似乎很合适。形状远离枢轴呈现,这似乎导致平移效果作为副作用发生,所以问题是 - 如何以固定旋转渲染我的所有形状,并使用特定的(x , y) 线,因为我有一个算法可以将它们相对于 Canvas?

的中心定位

作为参考,这里有一些输出,显示单一形状,唯一的变化 属性 是旋转角度

0f 度

90f 度

180f 度

270f 度

360f 与 0f 相同

这似乎不应该发生在这里,但确实如此。

方形是 Box 可组合项,白色的小东西是相关形状。

它没有应用平移,而是围绕一个枢轴旋转,该枢轴设置为 Box

rotate 有一个名为 pivot 的参数可以解决您的问题:

@Composable
fun Rotation() {
    val painter = rememberVectorPainter(image = Icons.Default.ThumbUp)
    Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Canvas(
            modifier = Modifier
                .height(200.dp)
                .background(color = Color.Red)
                .aspectRatio(1f)
        ) {
            with(painter) {
                repeat(4) {
                    rotate(
                        degrees = (it * 90f),
                        pivot = Offset(
                            painter.intrinsicSize.width * 2,
                            painter.intrinsicSize.height * 2
                        )
                    ) {
                        draw(
                            Size(100f, 100f),
                            colorFilter = ColorFilter.tint(Color.White)
                        )
                    }
                }
            }
        }
    }
}

上面的代码产生了这个结果:

为了改变完成旋转的点,简单地改变pivot参数中的坐标。