LibCanvasの基礎-理論





こんにちは LibCanvasについての最も一般的な質問の1つは、「どこから始めますか?」です。 このライブラリを入力するためのしきい値は、より単純なキャンバスライブラリよりもわずかに高いことに同意します。したがって、このトピックでは、LibCanvasの基本-基本概念と原理、プリミティブフィギュア、マウスイベント、キーボード、アニメーション、拡張コンテキスト、動作を描画します。 このすべてを、多くの例と最もアクセスしやすい言語で説明しようとします。



この記事がLibCanvasとは何ですか? なぜ必要なのか、その利点は何ですか? どこから始めますか?



この記事は理論に過ぎず、この知識を実際に適用する方法については、次の記事で説明します。



一般的な情報



LibCanvasは、Canvasおよび関連技術を使用するためのフレームワークであり、ゲームやその他のインタラクティブアプリケーションの開発に使用できます。



これは、 AtomJSに基づいています。これは、MooToolsやjQueryにやや似た軽量のJavaScriptフレームワークです。 非常に優れた英語のAtomJSドキュメントがあり、以前にMooToolsを使用したことがある場合は、AtomJSを正当化するのに十分です。



LibCanvasの最新バージョンはリポジトリから入手できます。GitHubには、非常に単純なものから非常に複雑なものまで、関連する例が多数あります 。 これらの例を見ると、多くの原則を理解できます。 ロシアのドキュメントがありますが、LibCanvasの多くの部分はまだカバーされていません。 時間が経つにつれて、それはいっぱいになり、拡大します。 誰かが英語への翻訳を手伝ってくれることを願っています)



コア



すべてのコードはLibCanvas名前空間に保存されます。 ライブラリがグローバル名前空間を乱雑にしないため、これは良いことです。 ただし、欠点があります-最後に冗長な構文で十分です:

var circle = new LibCanvas.Shapes.Circle( 100, 100, 50 ); var circle = new LibCanvas.Shapes.Circle( 222, 222, 22 );
      
      







これは、静的なLibCanvas.extract()メソッドを使用して修正できます。 アプリケーションで短いクラス名を使用できるように、LibCanvas自体をグローバル化します。

 LibCanvas.extract(); var circle = new Circle( 100, 100, 50 ); var circle = new Circle( 222, 222, 22 );
      
      







別の方法はエイリアスを使用することです:

 var Circle = LibCanvas.Shapes.Circle; var circle1 = new Circle( 100, 100, 50 ); var circle2 = new Circle( 222, 222, 22 );
      
      







LibCanvas.Context2D



組み込みのLibCanvasコンテキストがあります。 呼び出すのは非常に簡単です:

 var context = document.getElementsByTagName('canvas')[0].getContext('2d-libcanvas'); // or: var context = atom.dom('canvas').first.getContext('2d-libcanvas');
      
      







元の「2d」コンテキストは引き続きアクセス可能で影響を受けないため、アプリケーションで安全に使用できることに注意してください。

 var context = atom.dom('canvas').first.getContext('2d');
      
      







「2d-libcanvas」コンテキストは元のコンテキストと下位互換性があります(「2d」コンテキスト用に記述されたすべてのコードは「2d-libcanvas」コンテキストで動作します)が、次の利点があります。

1.チェーン可能-すべてのメソッドをチェーンと呼ぶことができます。 このメソッドは、jQueryの出現で特に人気がありました。

 context .set({ fillStyle: 'black', strokeStyle: 'red' }) . fillRect(20, 20, 40, 40) .strokeRect(50, 50, 100, 100);
      
      







2. 名前付き引数 -文字セットだけでなく、ハッシュも渡すことができます。

 context.drawImage(img, 10, 15, 40, 45, 20, 25, 50, 55); // vs context.drawImage({ image: img, crop : [10, 15, 40, 45], draw : [20, 25, 50, 50] });
      
      







3. 図形 -数字ではなく図形を転送できます。 これは、オブジェクトが作成された大規模なアプリケーションがある場合に特に便利です。

 //  : context.drawImage( image, rect.from.x, rect.from.y, rect.width, rect.height ); // vs context.drawImage( image, rect ); //      : context.save(); context.fillStyle = 'red'; context.fillRect( rect.from.x, rect.from.y, rect.width, rect.height ) context.restore(); // vs: context.fill( rect, 'red' );
      
      







4. 拡張API-ここに一連のアメニティがあります。 まず、パス、テキスト、画像、変換などを使用したより便利な作業:

 //      ,   : // original ctx: context.save(); context.translate(this.position.x, this.position.y); context.rotate(this.angle); context.translate(-this.image.width/2, -this.image.height/2); context.drawImage(this.image, 0, 0); context.restore(); // vs context.drawImage({ image : this.image, center: this.position, angle : this.angle }); // : context.text({ text: 'Test string \n with line breaks \n is here' padding: [ 30, 50 ], size: 20, align: 'center' }) //    : context.translate( point.x, point.y); context.rotate(angle); context.translate(-point.x, -point.y); // vs: context.rotate( angle, point ); //   context.beginPath( ); context.moveTo( mt.x, mt.y ); context.lineTo( lt.x, lt.y ); context.bezierCurveTo( bc1.x, bc1.y, bc2.x, bc2.y, bc.x, bc.y ); context.quadraticCurveTo( qc1.x, qc1.y, qc.x, qc.y ); context.closePath(); // vs context .beginPath( mt ) .lineTo( lt ); .curveTo( bc, bc1, bc2 ) .curveTo( qc, qc1 ) .closePath(); //  : var circle = new Circle( 130, 120, 50 ); context.beginPath(); context.arc( circle.center.x, circle.center.y, circle.radius, 0, Math.PI * 2 ); context.closePath(); context.clip(); // vs: context.clip( circle ); //   : context.clear( 0, 0, canvas.width, canvas.height ); // vs context.clearAll();
      
      







などなど。 組み込みのコンテキストの便利さをご自身で理解されていると思います。



LibCanvasオブジェクト



LibCanvasを構築すると、LibCanvas.Canvas2Dオブジェクトが作成されます。 最初の引数には、必要なキャンバス要素(css-selector、dom-objectなど)へのリンクを渡す必要があります。 追加の設定を秒-fps制限、再描画前のクリーニング、画像のプリロードなどに転送できます。

 var libcanvas = new LibCanvas('#my-canvas'); libcanvas instanceof LibCanvas; // true libcanvas instanceof LibCanvas.Canvas2D; // true //      : libcanvas.ctx instanceof LibCanvas.Context2D; // true
      
      







各フレームは2つのステージで構成されています。 1つ目はデータのレンダリングです。 毎回実行され、数学的な操作(オブジェクトの移動、衝突など)のみに責任を負います。 このレイヤーには再描画はありません。 2番目の段階はレンダリングです。 これには、画面のコンテンツの再描画を担当する部分が含まれており、画面上の変更があった場合にのみ実行されます。 これは、レンダリングの段階でlibcanvas.update()



メソッドを呼び出すことで報告できます。



libcanvas.addRender()



メソッドを使用してレンダリングステージに関数を追加できますlibcanvas.addRender()



メソッドを使用してレンダリングステージに関数を追加できます。 また、レンダリングの段階で、転送されたオブジェクトの描画メソッドが呼び出されます。 おおよそのコードは次のようになります。



 libcanvas .addFunc(function () { scene.recount(); if (scene.somethingChanged()) { libcanvas.update(); } }) .addRender(function () { //      libcanvas.update(); scene.drawAll(); });
      
      







多くのアプリケーション-ほとんどの場合静的であり、ユーザーのアクションの瞬間にのみ再描画されます。 これにより、プロセッサの無意味な負荷を大幅に削減できます。



実際には、 addRender



はほとんど使用されません。 draw()



を使用してオブジェクトをdraw()



することは非常に便利です(詳細は以下を参照)。



変更がある場合にのみ、常に画面に何かを再描画します。 多くのアプリケーションでは、このような基本的なメカニズムでは十分ではありませんが、何もしないよりはましです。



ポイント



LibCanvas.Point



は、基本オブジェクトの1つです。 それは非常に頻繁に使用され、すべての図のコンポーネントであり、それらの外で使用するのに非常に便利です 。 2つのポイント間の距離、角度、ポイントの乗算、およびすべての隣接ポイントの取得方法があります。



 //   A  60    B: var A = new Point(10, 10), B = new Point(20, 20); A.rotate( (60).degree(), B ); //        : var sum = 0 + matrix[py-1][px-1] + matrix[py-1][px] + matrix[py-1][p.x+1] + matrix[py ][px-1] + matrix[py ][p.x+1] + matrix[p.y+1][px-1] + matrix[p.y+1][px] + matrix[p.y+1][p.x+1] ; // vs var sum = point.neighbours.reduce(function(value, p) { return value + matrix[py][px]; }, 0);
      
      







フィギュア



LibCanvas.Shapes.*



LibCanvas.Shapes.*



含まれてLibCanvas.Shapes.*



あり、短いエイリアスにグローバル化されています。 最も有名な人物は、 Rectangle



Circle



Line



です。 LibCanvasを使用する場合-図形自体には外観がなく、外観を持つことはできないことに注意する必要があります-色または影。 LibCanvas.Ui.Shaperなど、図を使用するオブジェクトは外観を担当しますが、図自体には数学的な操作(パス、交差点、ポイントが図の中にあるかどうかなど)のみが含まれます。 彼らはアストラルですが、肉体ではありません。



これにより、外観と動作を分離できます。 たとえば、アルカノイドのボードがあります。 実際にはこれは絵ですが、単純な図のようにすべてのアクションを実行できます。



 var Unit = atom.Class({ initialize: function (rectangle, image) { this.shape = rectangle; this.image = image; }, collision: function (anotherUnit) { return this.shape.intersect( anotherUnit.shape ); }, draw: function () { this.libcanvas.ctx.drawImage( this.image, this.shape ); } });
      
      







Rectangle



は最も重要な数字です。 長方形の描画や基本的な数学演算だけでなく、LibCanvasの多くのメソッドでも使用されます。 たとえば、context.drawImageメソッドを使用できます。このメソッドは、各要素が小さなRectangleである、カットまたは描画の引数を持つ長方形またはタイルエンジンを取ります。



メソッドがRectangleのような引数を必要とする場合、メソッドは長方形のように見える任意の引数を受け入れることができます。 例:

 context.drawImage({ image: image, crop: { from: { x: 15, y: 10 }, size: { width: 50, height: 100 } }, draw: [10,20,100,200] });
      
      







この場合、トリミングと描画は内部的にRectangle(または別の必要な図)に削減されますが、パフォーマンスの観点から(キャンバスの複数の再描画を伴う)、アプリケーションアーキテクチャの観点から-最も有益な方法は、初期化中にすべてのオブジェクトを作成することですアプリケーション。 この決定は、特に優れたアーキテクチャを促進するために行われました。



 var Item = atom.Class({ initialize: function (image) { this.image = image; this.cropRect = new Rectangle(15, 10, 50, 100); this.drawRect = new Rectangle(10, 20, 100, 200); }, draw: function () { context.drawImage({ image: this.image, crop : this.cropRect, draw : this.drawRect }); } });
      
      







他の形状も同様に使用されます。

 // : context.arc({ circle: new Circle( 100, 100, 50 ), angle : [ (45).degree(), (135).degree() ] }); //  : context.stroke( new Line([13, 13], [42, 42]), 'red' );
      
      







行動



次の部分はLibCanvas.Behaviors.*



。 これらはそれぞれ、特定の機能または動作をクラスに追加する単なる混合物です。 たとえば、 animate



可能なメソッドを使用すると、オブジェクトのプロパティをスムーズに変更できるanimate



メソッドが追加され、Drawableでは、レンダリングのためにLibCanvasオブジェクトにクラスのオブジェクトを追加できます。



ちなみに、LibCanvasでのレンダリングの基本はDrawableです。 DrawableとShapesの混合*キャンバス上に任意の図形を描画でき、他のビヘイビアを追加すると、この図形に追加機能が追加されます。

 var Item = atom.Class({ Implements: [ Drawable, Draggable ], initialize: function (shape) { this.shape = shape; }, draw: function () { this.libcanvas.ctx.stroke( this.shape, 'red' ); } }); libcanvas.addElement( new Item( new Rectangle(50, 50, 100, 100) ).draggable() );
      
      







実際、 Ui.Shaper



は既に実装されているため、図形を描画するための同様のパターンを非常に頻繁に作成する必要がありました。



 libcanvas.createShaper({ shape : new Rectangle(50, 50, 100, 100), stroke: 'red' }).draggable();
      
      







キーボードとマウス



キーボードの操作は非常に簡単です。 アプリケーションの初期化時にlibcanvas.listenKeyboard()



メソッドを呼び出すだけで十分です。必要に応じてlibcanvas.getKey( keyName )



メソッドを使用して、キーの状態を確認できます。



 update: function () { if( this.libcanvas.getKey('aup') ) { this.move(); } }
      
      







マウスを使った作業には価値があります。 まず、アプリケーションでマウスを使用する場合は、 libcanvas.listenMouse()



メソッドを呼び出してlibcanvas.listenMouse()



。 最適化するために、マウスを必要としないアプリケーションがあるため、マウスイベントは呼び出されるまで分析されません。 その後、Mouseオブジェクトに要素を追加することで、マウスイベントを簡単にサブスクライブできます。

 this.libcanvas.mouse.subscribe( element );
      
      







要素のshapeプロパティの値が形状( LibCanvas.Shapes.*



)、zIndexプロパティの1つであり、 atom.Class.Events



クラスを実装することがatom.Class.Events



です。 実際には、これらはすべてビヘイビアーの背後に隠されており、たとえばdraggable()



Draggable



draggable()



メソッドをDraggable



と、オブジェクトはマウスイベントに自動的にサブスクライブします。 マウスイベントのみをリッスンする必要がある場合は、 MouseListener



動作を実装listenMouse



、要素でlistenMouse



メソッドを呼び出します。 それにもかかわらず、主要な点は依然として残っています-要素には、内部に何らかの形状を持つShape



プロパティが必要です。 オブジェクトでのマウスイベントがリッスンされると、次のイベントのいずれかをサブスクライブできます。



 /* - click - mouseover - mousemove - mouseout - mouseup - mousedown - away:mouseover - away:mousemove - away:mouseout - away:mouseup - away:mousedown */ // : element .listenMouse() .addEvent('click', function () { alert('element clicked'); });
      
      







おわりに



ここでは、LibCanvasの開発の理論的な部分の基本について説明しました。 多くの興味深い機会や原則を明らかにするものではありませんが、その目的はイデオロギーを説明し、読者にどこから始めればよいかを示すことです。



次の記事のトピックは、 LibCanvasの開発実際的な部分です



All Articles