# Compose 中的圖形

## 使用修飾符和 `DrawScope` 的基本繪圖

```Spacer(
modifier = Modifier
.fillMaxSize()
.drawBehind {
// this = DrawScope
}
)CanvasSnippets.kt```

```Canvas(modifier = Modifier.fillMaxSize()) {
val canvasQuadrantSize = size / 2F
drawRect(
color = Color.Magenta,
)
}CanvasSnippets.kt```

## 座標系統

```Canvas(modifier = Modifier.fillMaxSize()) {
val canvasWidth = size.width
val canvasHeight = size.height
drawLine(
start = Offset(x = canvasWidth, y = 0f),
end = Offset(x = 0f, y = canvasHeight),
color = Color.Blue
)
}CanvasSnippets.kt```

## 基本轉換

`DrawScope` 能處理改變繪圖指令執行位置或方式的轉換作業。

### 縮放

```Canvas(modifier = Modifier.fillMaxSize()) {
scale(scaleX = 10f, scaleY = 15f) {
drawCircle(Color.Blue, radius = 20.dp.toPx())
}
}CanvasSnippets.kt```

### 平移

```Canvas(modifier = Modifier.fillMaxSize()) {
translate(left = 100f, top = -300f) {
drawCircle(Color.Blue, radius = 200.dp.toPx())
}
}CanvasSnippets.kt```

### 旋轉

```Canvas(modifier = Modifier.fillMaxSize()) {
rotate(degrees = 45F) {
drawRect(
color = Color.Gray,
topLeft = Offset(x = size.width / 3F, y = size.height / 3F),
size = size / 3F
)
}
}CanvasSnippets.kt```

### 插邊

```Canvas(modifier = Modifier.fillMaxSize()) {
val canvasQuadrantSize = size / 2F
inset(horizontal = 50f, vertical = 30f) {
drawRect(color = Color.Green, size = canvasQuadrantSize)
}
}CanvasSnippets.kt```

### 多重轉換

```Canvas(modifier = Modifier.fillMaxSize()) {
withTransform({
translate(left = size.width / 5F)
rotate(degrees = 45F)
}) {
drawRect(
color = Color.Gray,
topLeft = Offset(x = size.width / 3F, y = size.height / 3F),
size = size / 3F
)
}
}CanvasSnippets.kt```

## 常見的繪圖作業

### 繪製文字

```val textMeasurer = rememberTextMeasurer()

Canvas(modifier = Modifier.fillMaxSize()) {
drawText(textMeasurer, "Hello")
}CanvasSnippets.kt```

#### 測量文字

```val textMeasurer = rememberTextMeasurer()

Spacer(
modifier = Modifier
.drawWithCache {
val measuredText =
textMeasurer.measure(
AnnotatedString(longTextSample),
constraints = Constraints.fixedWidth((size.width * 2f / 3f).toInt()),
style = TextStyle(fontSize = 18.sp)
)

onDrawBehind {
drawRect(pinkColor, size = measuredText.size.toSize())
drawText(measuredText)
}
}
.fillMaxSize()
)CanvasSnippets.kt```

```val textMeasurer = rememberTextMeasurer()

Spacer(
modifier = Modifier
.drawWithCache {
val measuredText =
textMeasurer.measure(
AnnotatedString(longTextSample),
constraints = Constraints.fixed(
width = (size.width / 3f).toInt(),
height = (size.height / 3f).toInt()
),
overflow = TextOverflow.Ellipsis,
style = TextStyle(fontSize = 18.sp)
)

onDrawBehind {
drawRect(pinkColor, size = measuredText.size.toSize())
drawText(measuredText)
}
}
.fillMaxSize()
)CanvasSnippets.kt```

### 繪製圖片

```val dogImage = ImageBitmap.imageResource(id = R.drawable.dog)

Canvas(modifier = Modifier.fillMaxSize(), onDraw = {
drawImage(dogImage)
})CanvasSnippets.kt```

### 繪製基本形狀

`DrawScope` 有很多用來繪製形狀的函式。如要繪製形狀，請使用一個預先定義的繪圖函式，例如 `drawCircle`

```val purpleColor = Color(0xFFBA68C8)
Canvas(
modifier = Modifier
.fillMaxSize()
onDraw = {
drawCircle(purpleColor)
}
)CanvasSnippets.kt```

 API 輸出 `drawCircle()` `drawRect()` `drawRoundedRect()` `drawLine()` `drawOval()` `drawArc()` `drawPoints()`

### 繪製路徑

```Spacer(
modifier = Modifier
.drawWithCache {
val path = Path()
path.moveTo(0f, 0f)
path.lineTo(size.width / 2f, size.height / 2f)
path.lineTo(size.width, 0f)
path.close()
onDrawBehind {
drawPath(path, Color.Magenta, style = Stroke(width = 10f))
}
}
.fillMaxSize()
)CanvasSnippets.kt```

## 存取 `Canvas` 物件

```val drawable = ShapeDrawable(OvalShape())
Spacer(
modifier = Modifier
.drawWithContent {
drawIntoCanvas { canvas ->
drawable.setBounds(0, 0, size.width.toInt(), size.height.toInt())
drawable.draw(canvas.nativeCanvas)
}
}
.fillMaxSize()
)CanvasSnippets.kt```

[]
[]