AndroidPathクラスの関数で描いたドラえもんのような何か
Android / Kotlin / Programming

Android Pathが大体わかる! – Android Path, Kotlin

Jetpack Composeで線の描画などをする際に使用するAndriod Pathクラスについて大体わかるようにまとめました。

はじめに

この記事は「Android Pathクラスが大体わかる」を目標にまとめています。
そのためにはoffset(オフセット)の考え方が必要になるかもしれないため、こちらも読んでみてください。

下記は学びやすいと思う順番に筆者が並べました。
参考程度に読んでいただければと思います。

大体わかる順

moveTo

こちらは描画を開始する点を指定する関数です。
画面に対する描画は発生しませんが、引数の値の考え方(offset)がわかりやすいと思います。


relativeMoveTo

こちらはmoveToと基本的には同じですが、offsetが異なります。
しかしこの違いがわかればここから先も大体わかると思います。


lineTo

こちらは開始点から引数で指定した点まで線を引く関数です。
特に複雑なものではなく理解しやすいと思います。


relativeLineTo

こちらはlineToとほぼ同じですが、offsetの考え方が描画開始点という違いがあります。
このように「relativeXXX」という名前のものはoffsetの考え方が違うだけで、基本部分は同じです。


close

こちらはパスの開始点まで線を引く関数です。
dbのclose関数のように呼び出し必須ではありません。


quadraticBezierTo

こちらは2次ベジェ曲線を追加する関数です。
ベジェ曲線が何かも簡単に解説しています。


relativeQuadraticBezierTo

quadraticBezierToのrelative(相対的)バージョンです。


cubicTo

こちらは3次ベジェ曲線を追加する関数です。
ベジェ曲線が何かも簡単に解説しています。


relativeCubicTo

cubicToのrelative(相対的)バージョンです。


addOval

こちらは円を追加する関数です。
半円や部分的に欠けている円などを追加したい場合は下のaddArcかaddArcRadの使用をお勧めします。


addArc

こちらは半円などの円の一部分を追加する関数です。
引数に対する値次第では完全な円も追加できます。
下のaddArcRadとの違いは、引数にしている値の単位が「度」か「ラジアン」である点です。
こちらは「度」で指定します。


addArcRad

addArcと同様に円の部分描画ができます。
こちらの指定単位はラジアンです。

おわりに

ベジェ曲線が少し難しいですが、その他についてはそこまで難しくないかもしれません。
relative系は使用頻度が高い気がするので押さえておきたいですね!

こちらで紹介している関数で大体カバーしていますが全てではないため、他の関数に関しては公式を参照してください。


アイキャッチ画像はAndroidPathクラスの関数で描いたドラえもんっぽい何かです。
コードを置いときます笑

Box(
modifier = modifier
.fillMaxSize()
.drawWithCache {
val path = Path()
val screenWidth = size.width
// eyes
// left eye pupil
val pupilRadius = 50f
val pupilOffsetY = 120f
val pupilOfLeftEye = Rect(
center = Offset(
x = screenWidth / 2 - pupilRadius - 10f,
y = pupilOffsetY
),
radius = pupilRadius
)
path.addOval(
oval = pupilOfLeftEye
)
// right eye pupil
val pupilOfRightEye = Rect(
center = Offset(
x = screenWidth / 2 + pupilRadius + 10f,
y = pupilOffsetY
),
radius = pupilRadius
)
path.addOval(
oval = pupilOfRightEye
)
// left eyeball
val eyeballRadius = 80f
val eyeballOffsetY = 100f
val leftEyeball = Rect(
center = Offset(
x = screenWidth / 2 - eyeballRadius,
y = eyeballOffsetY
),
radius = eyeballRadius
)
path.addOval(
oval = leftEyeball
)
// right eyeball
val rightEyeball = Rect(
center = Offset(
x = screenWidth / 2 + eyeballRadius,
y = eyeballOffsetY
),
radius = eyeballRadius
)
path.addOval(
oval = rightEyeball
)
// nose
val noseRadius = 40f
val noseOffsetY = 190f
val nose = Rect(
center = Offset(
x = screenWidth / 2,
y = noseOffsetY
),
radius = noseRadius
)
path.addOval(
oval = nose
)
// nose to mouth line
path.moveTo(
x = screenWidth / 2,
y = noseOffsetY + noseRadius
)
val noseToMouthLineOffsetX = 0f
val noseToMouthLineOffsetY = 160f
path.relativeLineTo(
dx = noseToMouthLineOffsetX,
dy = noseToMouthLineOffsetY
)
// mouth
path.relativeMoveTo(
dx = noseToMouthLineOffsetX - 200f,
dy = -noseToMouthLineOffsetY
)
path.relativeQuadraticBezierTo(
dx1 = 200f,
dy1 = 310f,
dx2 = 400f,
dy2 = 0f
)
// whiskers
// left whiskers
path.moveTo(
x = screenWidth / 2 - eyeballRadius,
y = 230f
)
path.relativeLineTo(
dx = -200f,
dy = -100f
)
path.moveTo(
x = screenWidth / 2 - eyeballRadius,
y = 250f
)
path.relativeLineTo(
dx = -200f,
dy = 0f
)
path.moveTo(
x = screenWidth / 2 - eyeballRadius,
y = 270f
)
path.relativeLineTo(
dx = -200f,
dy = 100f
)
// right whiskers
path.moveTo(
x = screenWidth / 2 + eyeballRadius,
y = 230f
)
path.relativeLineTo(
dx = 200f,
dy = -100f
)
path.moveTo(
x = screenWidth / 2 + eyeballRadius,
y = 250f
)
path.relativeLineTo(
dx = 200f,
dy = 0f
)
path.moveTo(
x = screenWidth / 2 + eyeballRadius,
y = 270f
)
path.relativeLineTo(
dx = 200f,
dy = 100f
)
// face line
path.addArc(
oval = Rect(
center = Offset(
x = screenWidth / 2,
y = 300f
),
radius = 250f
),
startAngleDegrees = -50f,
sweepAngleDegrees = 280f
)
path.addOval(
oval = Rect(
center = Offset(
x = screenWidth / 2,
y = 300f
),
radius = 400f
)
)
path.translate(
offset = Offset(
x = 0f,
y = size.height / 2 - 500f
)
)
onDrawWithContent {
drawContent()
drawPath(
path = path,
color = Color.Black,
style = Stroke(width = 10f)
)
}
}
)

質問等がありましたら、お気軽にコメントまでお願いします。

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です