Skip to content

Instantly share code, notes, and snippets.

@j796160836
Last active December 11, 2022 13:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save j796160836/fa48ad587c318d689d848a6346015a8e to your computer and use it in GitHub Desktop.
Save j796160836/fa48ad587c318d689d848a6346015a8e to your computer and use it in GitHub Desktop.
Tree.kt
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun Tree(modifier: Modifier) {
Canvas(modifier = modifier, onDraw = {
drawTree()
})
}
private fun DrawScope.drawTree() {
// 樹幹
val topTranslate = 250.dp.toPx()
withTransform({
translate(size.width / 2, topTranslate)
}, {
drawTrunk(50, 133)
})
var topTreeTranslate = 50.dp.toPx()
topTreeTranslate = 235.dp.toPx()
withTransform({
scale(1.1f, 1.1f)
translate(size.width / 2, topTreeTranslate)
}) {
drawTriangle(100)
}
topTreeTranslate = 166.dp.toPx()
withTransform({
scale(1f, 1f)
translate(size.width / 2, topTreeTranslate)
}) {
drawTriangle(100)
}
topTreeTranslate = 50.dp.toPx()
withTransform({
scale(0.8f, 0.8f)
translate(size.width / 2, topTreeTranslate)
}) {
drawTriangle(100)
}
withTransform({
translate(size.width / 2, 200f)
}) {
drawStar(80)
}
withTransform({
scale(0.55f, 0.55f)
translate(size.width / 2 + 400f, 750f)
}) {
drawPresent(100, Color(0xFF00E6B8), Color(0xFF0E8A6D), Color(0xFFDAD8D2))
}
drawDecorator(160, 150, 70, listOf(Color(0xFF7AF0D8), Color(0xFF71ECD0)))
drawDecorator(200, 200, 70, listOf(Color(0xFFF593D1), Color(0xFF492E3F)))
drawDecorator(220, 250, 70, listOf(Color(0xFF9ED0F7), Color(0xFF5463B9)))
drawDecorator(160, 230, 70, listOf(Color(0xFFE8F1B2), Color(0xFFF8DF93)))
}
private fun DrawScope.drawDecorator(x: Int, y: Int, size: Int, colors: List<Color>) {
drawOval(
brush = Brush.linearGradient(colors),
topLeft = Offset(x.dp.toPx(), y.dp.toPx()),
size = Size(size.toFloat(), size.toFloat())
)
}
private fun DrawScope.drawRibbon(width: Int, height: Int, strokeWidth: Int, color: Color) {
val ribbonWidth = strokeWidth.dp.toPx()
val rectWidth = width.dp.toPx()
val rectHeight = height.dp.toPx()
val ribbonPath = Path()
ribbonPath.moveTo(-rectWidth / 2, rectHeight)
ribbonPath.quadraticBezierTo(
x1 = 0f, y1 = 0f, x2 = rectWidth / 2, y2 = rectHeight
)
ribbonPath.lineTo(rectWidth / 2, rectHeight + ribbonWidth)
ribbonPath.quadraticBezierTo(
x1 = 0f, y1 = ribbonWidth, x2 = -rectWidth / 2, y2 = rectHeight + ribbonWidth
)
ribbonPath.lineTo(-rectWidth / 2, rectHeight)
drawPath(
path = ribbonPath, color = color
)
}
private fun DrawScope.drawTriangle(width: Int) {
val trianglePath = Path()
trianglePath.lineTo(width.dp.toPx(), width.dp.toPx())
trianglePath.lineTo(-width.dp.toPx(), width.dp.toPx())
drawPath(
brush = Brush.linearGradient(
colors = listOf(Color(0xFF8FEC56), Color(0xFF379B1C)),
start = Offset(0f, 0f),
end = Offset(0f, width.dp.toPx())
),
path = trianglePath,
)
}
private fun DrawScope.drawStar(size: Int) {
val starPath = Path()
starPath.moveTo((size * -0.5f).dp.toPx(), (size * 0.34f).dp.toPx())
starPath.lineTo((size * 0.5f).dp.toPx(), (size * 0.34f).dp.toPx())
starPath.lineTo((-size * 0.32f).dp.toPx(), (size * 0.95f).dp.toPx())
starPath.lineTo(0f, 0f)
starPath.lineTo((size * 0.32f).dp.toPx(), (size * 0.95f).dp.toPx())
starPath.lineTo((size * -0.5f).dp.toPx(), (size * 0.34f).dp.toPx())
drawPath(
brush = Brush.radialGradient(
colors = listOf(Color(0xFFFFE91E), Color(0xFFFF9800)),
center = Offset(size.dp.toPx() / 2, size.dp.toPx() / 2),
),
path = starPath
)
}
fun DrawScope.drawTrunk(width: Int, height: Int) {
drawRect(
brush = Brush.linearGradient(
colors = listOf(Color(0xFFCF6635), Color(0xFF964F2E)),
start = Offset(0f, 0f),
end = Offset(0f, height.dp.toPx())
),
topLeft = Offset(-(width / 2).dp.toPx(), 0f),
size = Size(width.dp.toPx(), height.dp.toPx())
)
}
private fun DrawScope.drawPresent(
size: Int,
backgroundColor1: Color,
backgroundColor2: Color,
color: Color
) {
drawRect(
brush = Brush.linearGradient(
colors = listOf(backgroundColor1, backgroundColor2),
start = Offset(0f, 0f),
end = Offset(0f, size.dp.toPx())
),
topLeft = Offset(-(size / 2).dp.toPx(), 0f),
size = Size(size.dp.toPx(), size.dp.toPx())
)
// Vertical line
drawRect(
color = color,
topLeft = Offset(-(size / 10).dp.toPx(), 0f),
size = Size((size / 5).dp.toPx(), size.dp.toPx())
)
// Horizontal line
drawRect(
color = color,
topLeft = Offset(-(size / 2).dp.toPx(), (size / 5 * 2).dp.toPx()),
size = Size(size.dp.toPx(), (size / 5).dp.toPx())
)
}
@Preview(showBackground = true)
@Composable
fun TreePreview() {
Tree(modifier = Modifier.size(1000.dp, 1000.dp))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment