Canvas APIの詳細説明(前編)
このセクションの概要:
13 のセクションを費やして、Android の Paint クラスの一般的に使用される API のほとんどを詳細に説明しました。 Canvas (描画ボード) のいくつかの一般的な API では、
- 8.3.1 で呼び出すことができるメソッドの一部をリストしています
- 3 つの描画ツール クラスの詳細な説明
- では、それらを次のカテゴリに分類しています。 drawXxxメソッドファミリー: 現在の描画領域に特定の座標値で絵を描画すると、レイヤーが重ね合わされます。 つまり、後でペイントするレイヤーが、先にペイントしたレイヤーを覆います。
- clipXXX メソッドファミリー: 現在の描画領域内の新しい描画領域をトリミング (クリップ) します。 描画領域は、キャンバスオブジェクトの現在の描画領域です。例:clipRect(new Rect())、 すると、長方形の領域がキャンバスの現在の描画領域になります
- getXxxメソッドファミリー:幅、高さ、画面密度など、キャンバスに関連するいくつかの値を取得します。
- save()、restore()、saveLayer()、restoreToCount()、およびレイヤーを保存および復元するその他のメソッド
- translate(pan)、scale(zoom)、回転(回転)、斜め(傾き)
もちろん、他にも散在するメソッドがあります。まあ、このセクションから始めて、学ぶべき興味深いAPIをいくつか選びます~
そして、このセクションは最初に説明しますtranslate(移動)、scale(ズーム)、rotate(回転)、skew(傾き)をもたらします。 そしてsave()、restore()について詳しく解説!
公式 API ドキュメント: Canvas
さらに、最初に Canvas の X 軸と Y 軸の方向を明確にする必要があります:
1. translation (translation)
メソッド: translate(float dx, float dy)
分析: 移動、キャンバスの座標原点をxで左右に、yで上下に移動します。キャンバスのデフォルトの位置は(0)です。 ,0)
パラメータ:dxは水平方向の移動距離、dyは垂直方向の移動距離
使用例:
for(int i=0; i < 5; i++) { canvas.drawCircle(50, 50, 50, mPaint); canvas.translate(100, 100); }ランニング効果:
2.回転(回転)
メソッド:rotate(float度) / rotate(float度、float px、float py)
分析: 座標の原点を中心に度を回転します。値は正の時計回りです。
パラメータ: 度は回転角度、pxとpyを指定 回転中心点座標(px, py)
使用例:
Rect rect = new Rect(50,0,150,50); canvas.translate(200, 200); for(int i = 0; i < 36;i++){ canvas.rotate(10); canvas.drawRect(rect, mPaint); }
ランニングエフェクト:
コード分析:
ここでは、まずtranslate(200, 200)を呼び出してキャンバスの座標原点を(200,200)に移動させ、また絵を描くので、 描画結果をキャンバス上に完全に表示することができます。回転を(10,200,200)に設定すると、次のようになります。 結果:
何か質問はありますか? これには、後で説明する Canvas の複数のレイヤーの概念が含まれます~
3.scale(zooming)
skewmethod: scale( float sx, float sy) / scale(float sx, float sy, float px, float py)
分析: キャンバスを拡大縮小します
パラメータ: sx は水平方向のスケーリング比、sy は垂直方向のスケーリングです比率はわかりません。 tilt) メソッド
:
(float sx, float sy)
分析: 傾斜、ベベル、ツイストとしても翻訳可能
パラメータ: sx は、対応する傾斜角度です。 x 軸方向、sy は y 軸方向の対応する傾斜角、両方の値は Tan 値です。 それらはすべて日焼け値です。それらはすべて日焼け値です。たとえば、X 軸方向に 60 度傾ける場合、10 進数値は次のようになります。tan 60 = 平方根 3 = 1.732!
使用例
:Canvas を Canvas と呼びます。子供用の靴は常に Canvas を単なる画用紙だと思っています。 Canvasを使ってマルチレイヤーアニメーションはどのように完成するのかお聞きしたいのですが?上記の翻訳の例では、なぜでしょうか? drawCircle(50, 50, 50, mPaint); 基準座標は常に (50,50) ですが、なぜこのような効果が発生するのでしょうか? 混乱している子供たちは、画面の概念とキャンバスの概念を混同しているかもしれません。以下で元に戻してみましょう。 翻訳が呼ばれた犯罪現場:canvas.drawBitmap(bmp,0,0,mPaint); canvas.scale(0.8f, 0.8f); canvas.drawBitmap(bmp, 0, 0, mPaint); canvas.scale(0.8f, 0.8f); canvas.drawBitmap(bmp,0,0,mPaint);ランニングエフェクト:
5. Canvasレイヤーの概念とsave()とrestore()の詳細な説明
図に示すように、キャンバス座標の原点は x 軸と y 軸上で 100 ずつ移動し、(0,0) に戻りたい場合は、 さまざまな時点で新しいグラフィックを描画する場合はどうすればよいでしょうか?これを破るには、translate(-100,-100) をゆっくりと元に戻しますか?あまり 混乱しています...
さて、それについては話さないようにしましょう。実際、Canvas は変換変換を行う前に現在のキャンバスの状態を保存できます。 私たちはレイヤーのサポートを提供しており、これらのレイヤーは「スタック構造」に従って管理されます
save()メソッドを呼び出すと、現在のキャンバスの状態が保存され、追加されたLayer(レイヤー)として使用されます。 Canvas スタックに、 また、この Layer は特定のクラスではなく、単なる概念的なものです。
そしてrestore()メソッドを呼び出すと、以前のCanvasの状態が復元され、この時点でCanvasレイヤースタックが復元されます。 スタックの一番上のレイヤーがポップアップし、次のレイヤーがスタックの一番上に来ます。このとき、キャンバスはスタックの一番上に保存されていたキャンバスの状態に戻ります。
簡単に言うと : save() はレイヤーをスタックにプッシュし、restore() はスタックの一番上にレイヤーをポップアップします。このレイヤーはキャンバスを表します。 州! つまり、save() を複数回実行することも、restore() を複数回実行することもできますが、復元呼び出しの数 は save を超えることはできません そうしないと、エラーがスローされます。ネットではそう言われていますが、実際のテストでは復元してもそのような問題は発生しませんでした。 回数は保存よりも多く、エラーはありません〜 目視検査では、システムが変更されたことを確認します。次のテストで皆さんにお見せします〜 さあ、保存と機能を検証するサンプルを書いてください。復元する!
例を書きます:
サンプルコード:
canvas.drawBitmap(bmp,0,0,mPaint); canvas.translate(200, 200); canvas.skew(0.2f,-0.8f); canvas.drawBitmap(bmp,0,0,mPaint);
実行結果:
言うまでもなく、コードと結果はすでにすべてを説明しています。もう少し複雑にしてみましょう。 複数のsave()とrestore()!
サンプルコード:
canvas.save(); //保存当前canvas的状态 canvas.translate(100, 100); canvas.drawCircle(50, 50, 50, mPaint); canvas.restore(); //恢复保存的Canvas的状态 canvas.drawCircle(50, 50, 50, mPaint);
実行結果:
結果分析:
最初に(300,300)を変換して描画し、次に45度回転して描画し、次に45度回転して描画し、次に ( 0,200) を翻訳します。 この間、描画前に毎回 save() が実行されます。これを見ると、最後の移動が 200 ではないという疑問が生じるかもしれません。 では、なぜ左に曲がったのでしょうか?へー、rotate() は座標軸全体を回転させるって言っておきますね?座標軸 変更点:
それでは、rotate() について理解しましたね?それでは、復元してみましょう~最終的な描画の前にいます。 2つのrestore()を追加してください!
canvas.save(); canvas.translate(300, 300); canvas.drawBitmap(bmp, 0, 0, mPaint); canvas.save(); canvas.rotate(45); canvas.drawBitmap(bmp, 0, 0, mPaint); canvas.save(); canvas.rotate(45); canvas.drawBitmap(bmp, 0, 0, mPaint); canvas.save(); canvas.translate(0, 200); canvas.drawBitmap(bmp, 0, 0, mPaint);
操作結果:
何も言うことはありません、自分で体験して、さらにrestore()を追加してください!
ちょっと面白いので、restore()を続けてみましょう
restoreは4回しか保存できていないみたいですね。インターネットの情報によると、 これはエラーを報告しますが、本当にそうなのでしょうか?ここでは、Canvas によって提供されるものを呼び出して、現在のスタックを取得します。 Layer メソッドはいくつありますか: getSaveCount()、save() とrestore() の前後 スタック内のレイヤーの数を出力するためのログを追加します。
結局のところ、実践することで真の知識が得られるのは非常に嬉しいことです。Canvas が変更されているか、その他の理由がある可能性があります。 時間の制約により、ソース コードを確認する必要がありますが、ここでは復元の数が保存の数よりも多くなる可能性があることがわかります。 ただし、不要な問題を避けるために、保存よりも復元の頻度を低くすることをお勧めします。 スタックに出入りするプロセスについては、私が実際に描いたものなので説明しませんが、非常にわかりやすいです。
6.saveLayer()とrestoreToCount()の説明
実際、これら2つのメソッドはsaveとrestoreに似ていますが、後者に基づいてさらにいくつかの点があります。 たとえば、saveLayer() には次のオーバーロードされたメソッドがあります:
save() メソッドは Canvas 全体 を保存し、saveLayer() は特定の領域の状態を選択的に保存できることが理解できます。 さらに、食事と宿泊施設に int saveFlags があることがわかります。これは、保存するオブジェクトを変更するための設定です。オプションの値は次のとおりです:
タグ | 説明 |
---|---|
ALL_SAVE_FLAG | すべてのステータスを保存 |
CLIP_SAVE_FLAG | 切り抜いた領域の状態を保存する |
CLIP_TO_LAYER_SAVE_FLAG | 状態を保存するプリセット範囲内 |
FULL_COLOR_LAYER_SAVE_FLAG | カラーコーティングを保存 |
HAS_ALPHA_LAYER_SAVE_FLAG | 不透明レイヤーを保存 |
MATRIX_SAVE_FLAG | 行列情報(平行移動、回転、拡大縮小、傾斜)の状態保存 |
追記:上記の説明には何か間違っているところがあり、作者の英語レベルが低いので間違っているかもしれません、もし何かご存知の場合は必ず修正してください、ありがとうございます〜
ここに例を書きます。検証します。 : CLIP_TO_LAYER_SAVE_FLAG モードを選択して例を作成します
実装コード:
canvas.restore(); canvas.restore(); canvas.translate(0, 200); canvas.drawBitmap(bmp, 0, 0, mPaint);
実行結果:
後でsaveLayer()を使用して詳しく調べます~ここにあります大まかなアイデア~
次に、この restoreToCount(int) に進みます。これはより簡単で、復元するレイヤーの数を直接渡すだけです。 対応するレイヤーに直接ジャンプし、同時にそのレイヤーより上のすべてのレイヤーをスタックからキックして、レイヤーが スタックのトップになろう~!複数のrestore()~
を記述するよりもはるかに便利で高速です。 7. このセクションのコードサンプルをダウンロードしてください:
まあ、コードはテスト用に書かれているので、ここに来るのはあまり面白くありませんが、おそらく読者はまだそれが欲しいなら、リンクを投稿するだけです!
コードのダウンロード: CanvasDemo.zipおそらくこれがあなたが望む画像です!笑~
このセクションの概要:
このセクションを書くのに数日かかりました。これは、著者が最初に Canvas レイヤーの概念をあまり明確にしていなかったためです。 今日は午後に仕事を終えて、夕方残業して考えを巡らせて、ようやくこの記事を書きました。 誰もが Canvas をより明確に理解できるようになり、高度なカスタム コントロールを使用するときに混乱することはなくなります。ふふ、このセクションはここまでです。 間違いがあればご指摘ください、よろしくお願いします〜