はじめに
Wear OSウォッチフェイスのプロトタイプをHTML5 Canvas + JavaScriptで組んでいたのですが、これをAndroid Canvas + Kotlinに移植しようとしたら微妙につまずいたので調査してメモ。
そもそもこの開発フローが間違っている気がしなくもない。
対比表
HTML5 Canvas (JavaScript) |
Android Canvas (Kotlin) |
---|---|
ctx.clearRect(x,y,width,height); | cnv.clipOutRect(x,y,x+width,y+height) |
ctx.lineWidth=width; ctx.strokeStyle="rgba(r,g,b,a)"; ctx.strokeRect(x,y,width,height); |
paint.setStrokeWidth(width) paint.setStyle(Paint.Style.STROKE) paint.setColor(Color.argb(a,r,g,b)) cnv.drawRect(x,y,x+width,y+height,paint) |
ctx.fillStyle="rgba(r,g,b,a)"; ctx.fillText(text,x,y); |
paint.setStrokeWidth(0.0f) paint.setColor(Color.argb(a,r,g,b)) cnv.drawText(text,x,y,paint) |
ctx.lineWidth=width; ctx.strokeStyle="rgba(r,g,b,a)"; ctx.strokeText(text,x,y); |
paint.setStrokeWidth(width) paint.setStyle(Paint.Style.STROKE) paint.setColor(Color.argb(a,r,g,b)) cnv.drawText(text,x,y,paint) |
text_metrics=ctx.measureText(text); | rect=Rect() paint.getTextBounds(text,0,text.length(),rect) |
ctx.lineWidth=width; | paint.setStrokeWidth(0.0f) |
ctx.lineCap=style_str; | paint.setStrokeCap(Paint.Cap) |
ctx.lineJoin=style_str; | paint.setStrokeJoin(Paint.Join) |
ctx.miterLimit=limit_num; | paint.setStrokeMiter(limit_num) |
ctx.getLineDash(); | paint.getPathEffect() |
ctx.setLineDash(array); ctx.lineDashOffset=offset; |
effect=DashPathEffect(array,offset) paint.setPathEffect(effect) |
ctx.font=font_str; | paint.typeface=typeface |
ctx.textAlign=style_str; | paint.setTextAlign(Paint.Align) |
ctx.textBaseline=style_str; |
直接的にはない ※計算して配置をずらす必要がある |
ctx.direction=style_str; ctx.fillText(text,x,y); |
cnv.drawTextRun (text,s,e,cStart,cEnd,x,y,isRtl,paint) |
ctx.fillStyle=style_str; | paint.setStyle(Paint.Style.FILL) paint.setColor(Color.argb(a,r,g,b)) |
ctx.strokeStyle=style_str; | paint.setStyle(Paint.Style.STROKE) paint.setColor(Color.argb(a,r,g,b)) |
grad=ctx.createConicGradient(start_angle,x,y); grad.addColorStop(step,color); grad.addColorStop(step,color); ... |
SweepGradient (x,y,colors,positions) |
ctx.createLinearGradient(x0,y0,x1,y1) grad.addColorStop(step,color1) grad.addColorStop(step,color2) |
LinearGradient (x0,y0,x1,y1,color0,color1,Shader.TileMode) |
ctx.createRadialGradient(x0,y0,r0,x1,y1,r1); grad.addColorStop(step,color); grad.addColorStop(step,color); ... |
RadialGradient (cX,cY,radius,colors,stops,Shader.TileMode) |
ctx.createPattern(image,repetition); | BitmapShader (bitmap,Shader.TileMode,Shader.TileMode) |
ctx.shadowBlur=rad; ctx.shadowOffsetX=x; ctx.shadowOffsetY=y; ctx.shadowColor="rgba(r,g,b,a)"; |
paint.setShadowLayer (rad,x,y,argb(a,r,g,b)) |
ctx.beginPath(); ctx.closePath(); |
path=Path() path.rewind() path.close() |
ctx.moveTo(x,y); | path.moveTo(x,y) |
ctx.lineTo(x,y); | path.lineTo(x,y); |
ctx.bezierCurveTo(x1,y1,x2,y2,x3,y3); | path.cubicTo(x1,y1,x2,y2,x3,y3) |
ctx.quadraticCurveTo(x1,y1,x2,y2); | quadTo(x1,y1,x2,y2) |
ctx.arcTo(x1,y1,x2,y2,rad); | addArc(x1,y1,x2,y2,0,rad) |
ctx.rect(x,y,width,height); | addRect (x,y,x+width,y+height,Path.Direction) |
ctx.fill(); | paint.setStyle(Paint.Style.FILL) cnv.drawPath(path,paint) |
ctx.stroke(); | paint.setStyle(Paint.Style.STROKE) cnv.drawPath(path,paint) |
ctx.drawFocusIfNeeded(element); | 直接的にはなさそう? |
ctx.scrollPathIntoView(); | 直接的にはなさそう? |
ctx.clip(); | cnv.clipOutPath(path) |
ctx.isPointInPath(x,y); | 直接的にはなさそう? |
ctx.isPointInStroke(x,y); | 直接的にはなさそう? |
ctx.getTransform(); | cnv.getMatrix() |
ctx.rotate(rad); | cnv.rotate(deg) ※角度単位違い |
ctx.scale(x,y); | cnv.scale(x,y) |
ctx.translate(x,y); | cnv.translate(x,y) |
ctx.transform(a,b,c,d,e,f); | matrix=Matrix() matrix.mapVectors([a,b,c,d,e,f]) |
ctx.setTransform(a,b,c,d,e,f); | matrix=Matrix() matrix.mapVectors([a,b,c,d,e,f]) cnv.setMatrix(matrix) |
ctx.resetTransform(); | cnv.restore() ※Transform以外も戻る |
ctx.globalAlpha=alpha; | canvas.saveLayerAlpha (0,0,cnv.getWidth(),cnv.getHeight(),alpha) ※設定はグローバル単位ではない |
ctx.globalCompositeOperation=type_str; | paint.setBlendMode(BlendMode) ※設定はPaintオブジェクト単位 |
ctx.drawImage(image,x,y); | cnv.drawBitmap(bitmap,x,y,null) |
ctx.createImageData(width,height); | createBitmap (width,height, Bitmap.Config,true,ColorSpace) |
ctx.getImageData(sx,sy,sw,sh); |
直接的にはない ※CanvasからBitmapを生成する手法がある → 画面に配置せずにViewからBitmapを生成する |
ctx.putImageData(imageData,dx,dy); | cnv.drawBitmap(bitmap,x,y,null) |
ctx.imageSmoothingEnabled=bool; | paint.setAntiAlias(bool) |
ctx.imageSmoothingQuality=quality_str; | なさそう? |
ctx.save(); | cnv.save() |
ctx.restore(); | cnv.restore() |
ctx.getContextAttributes(); | 一括では取れない? |
ctx.filter=filter_func; | cnv.setDrawFilter(DrawFilter) |
※ ctx
は CanvasRenderingContext2D
のオブジェクトです。
※ cnv
は android.graphics.Canvas
のオブジェクトです。
※ paint
は android.graphics.Paint
のオブジェクトです。
間違い、またはもっといい方法があればぜひコメント欄にてお知らせください。
参考資料
CanvasRenderingContext2D
android.graphics.Canvas
android.graphics.Paint
さいごに
楽をしようとしたら、余計に手間がかかりました。(などと)