この部分で
[変換、
歌
アニメーション
ピクセル操作]
変換
いくつかのメソッドを思い出してください
最初に、最後の章で言及した2つの方法を思い出す必要があります。
save-現在の状態をスタックの一番上に保存します
restore-スタックの先頭から状態を設定します
状態とは、変換マトリックス、描画領域、および次のプロパティ:strokeStyle、fillStyle、globalAlpha、lineWidth、lineCap、lineJoin、miterLimit、shadowOffsetX、shadowOffsetY、shadowBlur、shadowColor、globalCompositeOperation、font、textAlign、textBaselineです。
移動しましょう
translate(float x, float y)
-原点の現在位置を前の位置からxおよびyだけシフトします。
次の例を考えてみましょう。
ctx.save() // ctx.translate(100,100) // ctx.textBaseline = 'top' ctx.font = "bold italic 30px sans-serif" ctx.strokeText(" ",0,0) // (0;0), ctx.restore() // , ,
回しましょう
rotate(float angle)
-横座標と縦座標を角度角度で回します。角度をラジアンで測定することも忘れないでください。角度を度からラジアンに変換するには、度をPiで乗算し、180で除算する必要があります:rad = deg * Math.PI // 180
たとえば、ctx.translate(100,100)の後に次の行を追加します。ctx.rotate(45 * Math.PI / 180)
減少/増加
scale(float x, float y)
-x軸とy軸に新しいスケールを適用します。
たとえば、ctx.rotate(45 * Math.PI / 180)をctx.scale(0.65,1.5)に置き換えます
行列を掛ける
transform(float m11, float m12, float m21, float m22, float dx , float dy)
-古い行列に新しい行列を掛けます。
マトリックスを適用
setTransform(float m11, float m12, float m21, float m22, float dx , float dy)
-新しいマトリックスを適用します。たとえば、次のコードを見てください。
var img = new Image(); img.onload = function(){ ctx.save() ctx.setTransform(1,0.5,0,1,1,1) ctx.drawImage(img,0,0,78,50) ctx.restore() } img.src = 'brick.jpg';
私はレンガの壁の写真を使用し、変形をせん断しました 。
さらに、 Nutochkaのトピックで変換について詳しく読むことができます。
歌
作曲操作の種類
globalCompositeOperationプロパティは、合成操作のタイプを担当します。可能な値をすべてペイントできますが、 キャンバスのチートシートがあり、そこから画像の一部を表示する方が良いでしょう。 。
GlobalAlphaプロパティ
globalAlphaプロパティ-実際、0 <= globalAlpha <= 1の場合にのみ、各画像の透明度に乗算される係数です。たとえば、次のコードを考えます。
ctx.globalAlpha = 0.6; ctx.fillRect(0,0,100,100) ctx.fillRect(50,50,100,100)
アニメーション
requestAnimationFrame
以前のタイマーがアニメーションに使用されていた場合、特別なrequestAnimationFrame関数が表示され、トピックは既に説明されているため、azproductionから翻訳を読むことをお勧めします。
アニメーションの基本原理
アニメーションの基本原則は、古いフレームを消去して新しいフレームを描画することです。 古いフレームを消去する最も簡単な方法は、clearRect関数を使用することです。 たとえば、次のコードを考えて、最初にrequestAnimationFrame定義をコードに追加します。
var x = 400, y = 300; (function loop(){ ctx.clearRect(0,0,800,600); ctx.beginPath(); ctx.arc(x++,y++,50,0,Math.PI*2,false); ctx.fill() requestAnimFrame(loop); })();
また、 トピックのアニメーションについては、 triciiから読むことができます。
1ゲーム!= 1キャンバス
キャンバスアクセラレーションに関するプレゼンテーションでこのルールを見て、これが最も単純なルールであることに気付きました。
各フレームで複雑な画像を描画する代わりに、この画像を仮想キャンバスに保存してからすべてのフレームで描画することができますが、すべてを仮想キャンバスに押し込む必要はなく、描画するために本当に複雑な形状(たとえば、テキストやグラデーション)を押し込むだけです) 例えば、私はjsperf.comで小さなテストを行いましたが 、理想的ではありませんが、意味は明確だと思います。
ピクセルを操作する
キャンバスでは、高レベルのメソッドに加えて、ピクセルへの完全なアクセスもあります。これにより、すばらしいこと(フィルターなどを意味します)を実行でき、簡単なことを非常に迅速に描画できます。 ピクセルを操作するための特別なタイプのImageDataがあり、3つのプロパティwidth、height(説明する必要はないと思います)およびdata-rの配列、g、b、各ピクセルの値があります。
ピクセルデータの保存方法
前述のように、ピクセルデータは配列に格納されますが、配列内の要素の数はピクセル数x 4に等しくなります。すべての要素は0〜255の範囲の値を取ります。
アルファチャネルを含めると、0..255の値に保存されます。 この図は、4つの値r、g、bがセグメントを形成し、そのセグメントが1つのピクセルのパラメーターを格納する単一の分割不可能なセルであることを示しています。
空のImageDataを作成する
ImageData = context.createImageData(int w, int h)
-幅がw、高さがhの空のImageDataを作成します。
-送信されたimageDataの幅と高さで空のImageDataを作成します。注:データはコピーされません。ImageData = context.createImageData(imageData)
ImageDataを使用する
context.putImageData(imageData imgd, int x, int y)
-xyポイントからimageDataの幅と高さで領域内のキャンバスのピクセル配列を変更します。
簡単な例
しかし、十分な理論、ビジネスに取り掛かって、平滑化せずに関数y = x * xのグラフを描いてみましょう:
var imgd = ctx.createImageData(800, 600); var x,y,segment,xround,yround; for (x=-40 ; x<=40 ; x+=0.01) { y = x*x; xround = ~~(x+0.5); yround = ~~(y+0.5); segment = ((-yround+400)*imgd.width + xround + 40)*4; imgd.data[segment+3] = 255; } ctx.putImageData(imgd, 0, 0);
パフォーマンスを比較するために、同様にjsperfでfillRectを使用して同様のコードを作成しましたが、 1つのポイントを描画するには、fillRectを使用する方が良いです。
ピクセル操作
ImageData = context.createImageData(int x, int y, int w, int h)
-左上の頂点が(x; y)で、幅、高さw、hの長方形領域のキャンバスからのデータを含むimageDataオブジェクトを返します。 たとえば、写真の白い部分をハイライトしてみましょう。
var img = new Image(); img.src = 'test.jpg'; // img.onload = function(){ //netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); -- FireFox ctx.drawImage(img, 0, 0, 160, 120); var imgd = ctx.getImageData(0, 0, 160, 120); // imageData for (var i=0 ; i<imgd.data.length ; i+=4) { imgd.data[i] = imgd.data[i+1] = imgd.data[i+2] = imgd.data[i] < 200 && imgd.data[i+1] < 200 && imgd.data[i+2] < 200 ? 0 : 255; // } ctx.putImageData(imgd, 0, 0); //, , }