分析するGraphics


createjsを長期にわたって使用する過程で、私はずっとこのような経験を持っています:“beginFilldrawXXXの前に呼び出さなければなりません.そうしないとbeginFillは無視されます(はい、間違いを報告しません).しかし、なぜそうなったのか、実は深く研究していない.今日はGraphicsがどのように働いているのか知りたいです.
の原因となる
createjs.Graphics上の描画グラフィックAPIは、最終的には元のcanvas文に変換されます.まず原生canvasの表現を見てみましょう.
コード1 var ctx=canvas.getContext("2d");
ctx.rect(0, 0, 100, 100);
ctx.fillStyle = "#ff0000"; 
ctx.fill(); 

最終的な状況は次のとおりです.
コード2 var ctx=canvas.getContext("2d");
ctx.fillStyle = "#ff0000"; 
ctx.fill();
ctx.rect(0, 0, 100, 100); 

最終的な状況は次のとおりです.
どうしてコード2に赤い矩形が見えないのですか?photoshopに塗りつぶし色も線の色もない図形を描くと、描き終わったらこの図形は見えません.この理屈もcanvasに適用されます.fillというAPIは、色を塗りつぶすために使用されます.
canvasの場合、グラフィックを描画してから塗りつぶし(fill)またはストローク(stroke)を行うには、最終的にグラフィックがキャンバスにレンダリングされます.塗りつぶしまたは線を引いてからグラフィックを描くと、グラフィックはレンダリングされません.
比喩的に言えば
まず穴を掘ってから水を注ぐ==水を入れる;まず水を注いでから穴を掘る==穴を1つ掘る
原生canvasの充填または線引き方法は4つあり、以下の通りです.
  • fill
  • stroke
  • fillRect
  • strokeRect

  • 分析するGraphicsのソース
    createjs.Graphicsのソースアドレス:http://www.createjs.com/docs/...
    私は前の説明で「すべてのGraphics上のグラフィックAPIが最終的にオリジナルcanvas文に変換される」と言ったことがありますが、createjsのソースコードを見ても確かにそうです.APIが多すぎるため、Graphics.prototype.drawRectから先に切り込むしかありません.
    まず研究したソースコードはGraphics構造関数であり、以下の図である.
    次に、GはGraphics構造関数そのものを表し、pはGraphicsを表す.prototype、以下の通りです.
    第三にGraphics.prototype.drawRectはGraphicsを指す.prototype.rect、次のようにします.
    第四にGraphics.prototype.rectはthis.appendに直接戻り、G.Rectメソッドを同時に呼び出します.以下のようにします.
    第五に、まずG.Rectが何をしたかを見てみましょう.以下のようにします.
    ここにはexecが出てきて何をしているのか分かりませんが、execdrawRectをオリジナルのcanvasコードに変換しているのが見えます!!!
    第六に、Graphics.prototype.append を振り返ってみると、以下のようになっています.
    ここで得られる情報は、new G.Rect(x, y, w, h) pushを配列_activeInstructionsに入れることである.私が欲しいものはないようですが、上を見ると以下の注釈があります.
    // TODO: deprecated.
    /**
     * Removed in favour of using custom command objects with {{#crossLink "Graphics/append"}}{{/crossLink}}.
     * @method inject
     * @deprecated
     **/
    
    /**
     * Appends a graphics command object to the graphics queue. Command objects expose an "exec" method
     * that accepts two parameters: the Context2D to operate on, and an arbitrary data object passed into
     * {{#crossLink "Graphics/draw"}}{{/crossLink}}. The latter will usually be the Shape instance that called draw.
     *
     * This method is used internally by Graphics methods, such as drawCircle, but can also be used directly to insert
     * built-in or custom graphics commands. For example:
     *
     *         // attach data to our shape, so we can access it during the draw:
     *         myShape.color = "red";
     *
     *         // append a Circle command object:
     *         myShape.graphics.append(new createjs.Graphics.Circle(50, 50, 30));
     *
     *         // append a custom command object with an exec method that sets the fill style
     *         // based on the shape's data, and then fills the circle.
     *         myShape.graphics.append({exec:function(ctx, shape) {
     *             ctx.fillStyle = shape.color;
     *             ctx.fill();
     *         }});
     *
     * @method append
     * @param {Object} command A graphics command object exposing an "exec" method.
     * @param {boolean} clean The clean param is primarily for internal use. A value of true indicates that a command does not generate a path that should be stroked or filled.
     * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
     * @chainable
     **/
    

    ここでの情報は重要すぎる:p.appendの役割は「コマンドオブジェクト(command object)」を「画像キュー(graphics queue)」にプッシュすることである.「グラフィックインスタンス(Shape instance)」がdrawメソッドを呼び出すと、「コマンドオブジェクト」が「画像キュー(graphics queue)」から取り出され、そのインスタンスの様子が描かれます.
    ステップ7、p.drawを参照してください.以下のようにします.
    ここでは、drawが実行されると、配列_instructionsに対してキュー操作が行われることが一目瞭然である.しかし、6番目のステップで述べた配列は_activeInstructionsであるが、_instructions_activeInstructionsとはどのような関係があるのだろうか.上の図にはthis._updateInstructions()という答えがあるかもしれません.
    手順8:_updateInstructionsの方法を参照してください.
    上図コードから分かるように、_activeInstructions_instructionsの一部である.さらに深く分析すると、上図コードの次のthis._fillthis._strokeが表示されます.
    私から見ればcreatejsはGraphicsの方法を2種類3種類に分けている.
    第1クラス
    グラフィックの描画
    描画方法;例えば、rect/moveTo/lineToなど
    第2クラス
    グラフィックのレンダリング
    充填方法(fill);ストローク方法(stroke);
    現在の分析のdrawRectが第1クラスである.第2のクラスを分析する必要があります.
    ステップ9、分析beginFill:beginFillthis.appendではなくthis._setFillであることがわかる.
    ステップ10、p._setFillを参照してください.以下のようにします.
    第2のクラスメソッドは、this._updateInstructions(true)を直接呼び出し、第2のクラスメソッドが生成したコマンドも_activeInstructions配列に格納されなくなった(実際には_activeInstructions配列は、第1のクラスメソッドが生成したコマンドの配列である).
    1615行のthis.command = this._fill = fillは、実は重要です.ステップ8の_updateInstructionsを振り返ると、第2のクラスのメソッドは、_updateInstructionsを内部的に呼び出し、boolean値trueに入力し、_activeInstructions配列をクリアする役割を果たす(1602行参照).「1577行~1606行」のコードを解析すると、この20行のコードの役割は、第2の方法で生成されたコマンドを_instructions配列に追従することであることがわかる.ここには論理トラップがあります.現在の第2のコマンドをinstructions配列に追加します.
    どうして陥没井戸なの?1614~1615行を振り返ると、this._fill_updateInstructionsを呼び出した後に付与される.これは、第2のクラスのメソッドによって生成されたコマンドが、次の呼び出し_updateInstructions_instructions配列に追加されることを意味する._updateInstructionsに呼び出されるアクションはどれですか?第2の方法はp.drawである.
    これは、第2のクラスのメソッドが生成したコマンドがキューの位置にあるのは、次の第2のクラスのメソッドが存在するチェーンの位置であることを意味します(第2のクラスのメソッドが1つしかない場合、チェーンの最後にあります).しかし、上記の結論は、本文書が投げ出した知識点を解決するものではありません.「beginFillはdrawXXXの前に置かなければなりません.そうしないと、beginFillは無視されます」.
    1577行の判定文:if (this._dirty && active.length) に戻ります.実際には、第2のクラスのメソッドが_updateInstructionsメソッドを呼び出すと、_activeInstructions配列が空になります(すなわち、active.length === 0).またp.draw_activeInstructions配列を空にしないが、これを空にする.dirtyはfalseに設定されます(行:1599参照).これは、Graphicsのチェーン末尾が第2の方法であり、これらの方法で生成されたコマンドが_instructions配列に追加されない(すなわち、実行されない)ことを意味する.var rect=new createjs.Shape(); rect.graphics.drawRect(0, 0, 100, 100).beginFill("#ff0000").setStrokeStyle("#000000").beginStroke(4);stage.addChild(rect);上のコードは実行後空白です.
    PS:第2クラスのコマンドのすべての方法--beginFill,beginStroke,setStrokeStyle,setStrokeDash.機能的にはbeginFillは形式的に全く同じなので、beginFillを分析するだけでよい.次のようになります.
    マルチグラフィックインスタンス
    createjs.Graphicsは、var instance=new createjsのようなマルチグラフィックインスタンスを作成することができる.Shape(); instance.graphics
    .beginFill("#ff0000").drawRect(0, 0, 100, 100) //   
    .beginFill("#ffff00").drawCircle(150, 150, 50) //   
    

    実は私が想像していたのは、Shapeインスタンスが1つのグラフィックしか作成できないということですが、実際にはShapeインスタンスが複数のグラフィックを作成できるということです.原生canvasからマルチグラフィックがどのように描かれているかを説明します.
    var ctx = canvas.getContext("2d");
    ctx.beginPath(); 
    ctx.rect(0, 0, 100, 100); 
    ctx.fillStyle = "#ff0000"; 
    ctx.fill(); 
    ctx.closePath(); 
    ctx.beginPath(); 
    ctx.arc(150, 150, 50, 150, 100 * Math.PI * 2); 
    ctx.fillStyle = "#ffff00"; 
    ctx.fill(); 
    ctx.closePath();

    厳密には、オリジナルcanvasのグラフィックの描画とレンダリングはbeginPath()から始まり、closePath()から終わります.実際には、beginPath()は、前の図形の終了および次の図形の開始を表す.
    コードはvar ctx=canvasと簡単にできます.getContext("2d");
    ctx.rect(0, 0, 100, 100); 
    ctx.fillStyle = "#ff0000"; 
    ctx.fill();
    ctx.beginPath(); 
    ctx.arc(150, 150, 50, 150, 100 * Math.PI * 2); 
    ctx.fillStyle = "#ffff00"; 
    ctx.fill();
    

    矩形と円形の中間のbeginPath()がなくなったらどうなりますか?var ctx = canvas.getContext("2d");
    ctx.rect(0, 0, 100, 100); 
    ctx.fillStyle = "#ff0000"; 
    ctx.fill(); 
    ctx.arc(150, 150, 50, 150, 100 * Math.PI * 2); 
    ctx.fillStyle = "#ffff00"; 
    ctx.fill();
    

    この場合、矩形と円形は同じ図形に属するので、fillは最後の色を塗りつぶします.
    振り返るとcreatejs.Graphicsp._updateInstructions:
    別の結論を簡単に得ることができます.第2の方法は、チェーン上の位置にbeginPathのコマンドを挿入して、前のグラフィックの終了と次のグラフィックの開始をマークします.1つの図形を研究対象とする場合、Graphicsが1つの図形を描画する言語:第2の方法()を難しくしない.[.第2の方法()...].第一類の方法()[.第一類の方法()...]
    上の式は簡単に書くことができる:第2類の方法グループ.第1のメソッドグループ.次に、メソッドを対応するオリジナルコマンドに変換すると、これらのコマンドの実行順序は、第1のメソッドで生成されたコマンド->第2のメソッドで生成されたコマンドです.ちょうど語式の左右と入れ替わる.
    まとめ
    本文はGraphicsソースコードを解析した後、以下の結論を出した.
  • 第2のクラスメソッドが生成するコマンドは、キューの位置にある次の第2のクラスメソッドが存在するチェーン位置である(第2のクラスメソッドが1つしかない場合はチェーンの最後にある)
  • .
  • Graphicsのチェーン末尾が第2のクラスのメソッドである場合、これらのメソッドが生成するコマンドは_instructions配列に追加されない(すなわち実行されない)
  • .
  • 第2のクラスの方法は、チェーンの位置フラグの前のグラフィックの終了と次のグラフィックの開始
  • である.
    3つの結論があるが、記憶されにくい.
    もっと価値があるのは図形を描く語式であるべきです:“第2類の方法グループ.第1類の方法グループ”しかし実用価値についてまだ冒頭のあの文です:beginFilldrawXXXの前に呼び出さなければならなくて、さもなくばbeginFillは無視されます(はい間違いを報告しません)