4

このコードはonDraw()にあります。

radius = drawGmpImage(this.gmpImage, canvas);
canvas.drawCircle(kHorizontalOffset, kScreenVerticalOffset, radius , maskPaint);

drawGmpImageは、多くの線が描かれた円である複雑なグラフィックを作成します。変更できないライブラリ関数です。線は多角形であり、円の円周を超えて延びることができます。

必要なのは、円の外側に描かれたすべてのものを「空白にする」ことです。

これはiOSからの移植であり、元の開発者向けソリューションは、リソースとして保存された単純なビットマップマスクを使用し、描画された円のサイズに一致する透明な円を使用することです。描画された円の上にビットマップを描画するだけで目的の効果が得られますが、可能なすべての解像度と比率をサポートする必要があるため、Androidではオプションではありません。

したがって、canvas.drawCircle()呼び出しは、円の外側のすべてをマスクする試みの始まりです。塗りつぶされた円が私の描かれた円の上に描かれるので、残っているのは描かれた円の円周の外側の多角形の線だけであるという点でうまく機能します。半径は、描画された円の半径です。

どうすればこれを反転して、円の内容を残すことができますか?

4

2 に答える 2

7

何時間もかけて何かに取り組み、あきらめ、質問をし、20分後に答えに出くわすことができるのはなぜですか?人生の喜び。

Path path = new Path();
path.addCircle(kHorizontalOffset, kScreenVerticalOffset, radius, Path.Direction.CW);
canvas.clipPath(path);

任意のパスを取得してクリッピング領域として使用するclipPathメソッドを見逃していました。パスにマスキングサークルを追加すると、必要な処理が正確に実行されます。

[編集]

これはうまく機能しますが、問題があります。ハードウェアアクセラレーションがオンになっている場合は機能しません。加速をオフにすることはできますが、それでは複雑な残りのドローで多くのパフォーマンスが失われます。

これが私が最終的にそれを解決した方法です:

onSizeChanged()、ビットマップマスクを作成します。このペイントを使用して、ビットマップの適切な場所に透明な円を描きます。の鍵は、を使用することPorterDuffXfermodeです。

 maskPaint = new Paint();
 maskPaint.setColor(Color.TRANSPARENT);
 maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
 maskPaint.setStyle(Paint.Style.FILL);

次に、ビットマップを作成します

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {

    super.onSizeChanged(w, h, oldw, oldh);

    createMask(w,h,this.radius);

}

private void createMask(int w,int h, int radius){

    if (mask!=null){mask.recycle();}

    mask = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    Canvas maskCanvas = new Canvas(mask);
    maskCanvas.drawCircle(w, h, radius, maskPaint);

}

次に、onDraw()で、ビュー全体にマスクを描画します。

@Override
protected void onDraw(Canvas canvas){

    // draw the image();
    setRadius(drawGmpImage(this.gmpImage, canvas));
    canvas.drawCircle(kHorizontalOffset, kScreenVerticalOffset, radius , maskPaint);

    // overlay the mask bitmap
    if (mask != null) {
        canvas.drawBitmap(mask, 0f, 0f, bitmapPaint);
    }

半径が変更されると、マスクが再作成されます。

 private void setRadius(int radius){

     this.radius = radius;
     createMask(kHorizontalOffset, kScreenVerticalOffset, radius);

 }
于 2013-01-28T23:02:30.233 に答える
1

マスクを使用してこれを実現する方法がわからないため、別のアプローチ:

半径を特定の色、たとえば黒で描くことができます。

コーナーの1つからのFloodfillより。それほど難しくない前に、Floodfillアルゴリズムを作成しました。左上隅から開始し、そのピクセルを目的のコロに設定します。次に、隣接するピクセルを確認します。黒の場合はその方向で停止し、そうでない場合は色を変更して隣接するピクセルをもう一度確認します。

幸運を

于 2013-01-28T22:21:15.033 に答える