2016-05-13 11 views
2

O'Reillyの書籍「HTML5 Canvas」の作業を開始しました。私は第2章にあります。例の1つは、よく説明されていないコードを示しています。例2-5:キャンバスクリッピング領域とキャンバススタック

  1. はブラックボックス
  2. 押し状態上部に
  3. 設定小さい切り出し領域が左
  4. 描画円
  5. ポップ状態
  6. 設定大きいクリッピング領域
  7. を描きます別の円を描く

しかし、私はトラブルのいくつかのことを理解したよ:

context.fillStyle = 'black'; 
context.fillRect(10, 10, 200, 200); 

context.save(); 

context.beginPath(); 
context.rect(0, 0, 50, 50); 
context.clip(); 

context.beginPath(); 
context.strokeStyle = 'red'; 
context.lineWidth = 5; 
context.arc(100, 100, 100, 0, 2*Math.PI, false); 
context.stroke(); 
context.closePath(); 

context.restore(); 

context.beginPath(); 
context.rect(0, 0, 500, 500); 
context.clip(); 

context.beginPath(); 
context.strokeStyle = 'blue'; 
context.lineWidth = 5; 
context.arc(100, 100, 50, 0, 2*Math.PI, false); 
context.stroke(); 
context.closePath(); 

私の質問:

まず、context.clip()は暗黙的にコンテキストパスを( "context.closePath()")閉じていますか? context.beginPath()の前に別のcontext.beginPath()が続きます。このように:

context.beginPath(); 
context.rect(0, 0, 50, 50); 
context.clip(); 
context.beginPath(); 

第2に、なぜコンテキスト状態をプッシュする必要がありますか?なぜクリッピング領域を変更できないのですか?それは状態を押すことなく動作しないので必要と思われる。私が状態を押して復元しなければ、大きな青い円は現れず、なぜ私は理解しません。

+1

beginPathは完全な新しいパスを開始し、古いパスをダンプします。 closePathはbeginPathとは関係ありません。 ClosePathは現在の位置から最後のmoveTo位置までlineToを作成します。あなたは好きなだけ多くのclosePathを持つことができます。レンダリング出力ごとに1つのbeginPathを持つことができます(stroke()、fill())。クリップは累積されており、前のクリップでクリップされたクリップを追加するたびに、各クリップ領域が小さくなります。復元するには、保存と復元を使用する必要があります。 – Blindman67

答えて

3

はcontext.clip()暗黙的にコンテキストパスを閉じていますか?...
それは))(context.beginPathが先行し、そして別のcontext.beginPath(が続いています。このように:[...]

はい、これはclosePath()が(クリップと呼ばれていない場合ので、クリッピングのために必要とされる近い形状を作成するための唯一の方法である)内部でパスを閉じます。クリッピング領域を計算するとき

specification states:

オープンサブパスが暗黙のうちに、実際のサブパスに影響を与えずに、閉じていなければなりません。

beginPath()は、現在のメインパスとそのすべてのサブパスをクリアします。クリッピングはまだ有効ですが、ラスタライズ時にクリップ領域の影響を受ける他のパス操作を実行できるようになりました。

なぜコンテキスト状態をプッシュする必要がありますか?

は、提案および検討されたが(そこ標準でresetClip()あるが、まだ広くサポートされていない)クリップ領域をリセットする方法はありません。Calling clip()数回 -

クリップ()現在のクリッピング領域の交点を計算することによって、新たなクリッピング領域を作成する必要があります方法[...]すなわち

、それができませんこれは、描画面全体のクリップ領域を定義した場合に置き換えられます。

クリップを削除できる唯一の方法は、状態を保存し、クリップを設定して復元して復元することです。

+1

良い説明!キャンバス要素のサイズを変更するとクリッピングもクリアされます。キャンバス要素のサイズを変更すると、すべてのコンテキスト状態がリセットされるからです。 – markE