はじめに
AndroidでCanvasにPathを描画するときに、描画に対して効果を与えることのできるPathEffectの効果についてまとめてみました。
Pathをもとに作成した線に対して一定のルールで効果を与えたいときに便利なものになっています。
特に破線や点線なんかを便利に引くことが可能になります。
各PathEffectのサブクラスの効果・挙動は、以下のようなサンプルコードで見ていきます。
private Paint mPaint;
private Path mPath;
private void init() {
// 初期化処理
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(20);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
mPath.rewind();
mPath.moveTo(100, 300);
mPath.lineTo(200, 300);
mPath.lineTo(300, 200);
mPath.lineTo(400, 200);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(mPath, mPaint);
mPath.rewind();
mPath.moveTo(500, 100);
mPath.lineTo(550, 100);
mPath.lineTo(700, 200);
mPath.lineTo(550, 300);
mPath.lineTo(500, 300);
mPath.close();
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(mPath, mPaint);
}
左側の線がPaint.Style.STROKE
での描画、右の図形がPaint.Style.FILL
となっています。
DashPathEffect
DashPathEffectは描写のON/OFFの間隔を指定することで、Pathを破線で描写することができます。
例では20px描画したあと、40pxの空白を入れたものになっています。
Paint.Style.FILL
で描画されたものには効果がありません。
mPaint.setPathEffect(new DashPathEffect(new float[]{20, 40}, 0));
PathDashPathEffect
PathDashPathEffectは、任意のPathを等間隔に描写することが可能なPathEffectです。
たとえば、Pathに円形を指定することで点線を表現することが可能です。
指定したPathは、x:0, y:0の位置を基準に効果が適用されるため、作る図形は中心をx:0, y:0になるように作成すると意図通りの動きになると思います。
setStrokeWidthで指定した太さより大きいPathを指定した場合は途切れてしまうので注意してください。
PathDashPathEffect.Styleごとの変化を見ていきます。
PathDashPathEffect.Style.TRANSLATE
PathDashPathEffect.Style.TRANSLATE
では、線の位置に指定したPathの位置を移動したようになります。PathDashPathEffectを使う上で大抵これを選んでおけば問題ないと思います。
例では、20px x 20pxの円を30px間隔で配置しています。(つまり 20-30 = 10pxの空白ができます)
Path shape = new Path(); // 丸型
shape.addOval(-10, -10, 10, 10, Path.Direction.CW);
mPaint.setPathEffect(new PathDashPathEffect(shape, 30, 0, PathDashPathEffect.Style.TRANSLATE));
PathDashPathEffect.Style.ROTATE
PathDashPathEffect.Style.ROTATE
では、線の方向にPathが回転しているような挙動になります。
Path shape = new Path(); // ◆型
shape.moveTo(-10, 0);
shape.lineTo(0, -10);
shape.lineTo(10, 0);
shape.lineTo(0, 10);
shape.close();
mPaint.setPathEffect(new PathDashPathEffect(shape, 30, 0, PathDashPathEffect.Style.ROTATE));
PathDashPathEffect.Style.MORPH
PathDashPathEffect.Style.MORPH
では、線の方向にPathが変形しているようです。
Path shape = new Path(); // ◆型
shape.moveTo(-10, 0);
shape.lineTo(0, -10);
shape.lineTo(10, 0);
shape.lineTo(0, 10);
shape.close();
mPaint.setPathEffect(new PathDashPathEffect(shape, 30, 0, PathDashPathEffect.Style.MORPH));
CornerPathEffect
CornerPathEffectは線の角を丸くする効果が加わります。
一つ特徴的なのが、Paint.Style.STROKE
での描画で線の始点と終点の角は丸くならないところです。
例ではradius: 10として作成しています。
mPaint.setPathEffect(new CornerPathEffect(10));
DiscretePathEffect
DiscretePathEffectは線をランダムに崩す効果が加わります。
例の10
の部分には崩しの長さ、5
の部分には崩すレベルを指定します。
mPaint.setPathEffect(new DiscretePathEffect(10, 5));
SumPathEffect
SumPathEffectは2つのPathEffectを同時に適用することが可能になります。
例えば、2つのPathDashPathEffectのadvance
とphase
を適切に設定することで、円形と菱形が交互に入る点線を表現することが可能です。
−−・−−・−−
のような線を書いて欲しいなどのデザイン要件が来た際に役立つと思います。
Path circleShape = new Path(); // 丸型
circleShape.addOval(-10, -10, 10, 10, Path.Direction.CW);
PathDashPathEffect first = new PathDashPathEffect(circleShape, 80, 0, PathDashPathEffect.Style.TRANSLATE);
Path rectShape = new Path(); // ◆型
rectShape.moveTo(-10, 0);
rectShape.lineTo(0, -10);
rectShape.lineTo(10, 0);
rectShape.lineTo(0, 10);
rectShape.close();
PathDashPathEffect second = new PathDashPathEffect(rectShape, 80, 40, PathDashPathEffect.Style.ROTATE);
mPaint.setPathEffect(new SumPathEffect(first, second));
ComposePathEffect
ComposePathEffectは2つのPathEffectを順番に適用することが可能になります。
outer
, inner
の2つのPathEffectを用意します。最初にinner
の効果が適用されてから、その適用された図形に対してouter
の効果が適用されるような挙動になります。
例では、まず最初にinner
として指定したPathDashPathEffect
の効果が適用されてから、その効果が適用された図形に対してouter
として指定したCornerPathEffect
の効果が加わり、菱形の角も含めて丸くなっていることが分かります。
Path shape = new Path(); // ◆型
shape.moveTo(-10, 0);
shape.lineTo(0, -10);
shape.lineTo(10, 0);
shape.lineTo(0, 10);
shape.close();
PathDashPathEffect inner = new PathDashPathEffect(shape, 30, 0, PathDashPathEffect.Style.TRANSLATE);
CornerPathEffect outer = new CornerPathEffect(5);
mPaint.setPathEffect(new ComposePathEffect(outer, inner));