1

オブジェクト システムとウィジェット ツールキットに qooxdoo を使用し、描画バックエンドとして RaphaelJS を使用して、HTML5 ダイアグラム アプリケーションを作成しています。ダイアグラムのデータ モデルには、Item、Line などの高レベル オブジェクトが含まれています。これらは、位置、寸法、色、その他のデータのプロパティを持つ qooxdoo クラスとして実装されます。各クラスは、たとえば render() メソッドを使用して、そのインスタンスを Raphael 紙にレンダリングできます。この時点で、ビジュアル (Raphael の用語では「要素」) が作成されます。

問題は、 Raphael ビジュアルを作成する前にいくつかのプロパティを設定する必要があることです。Raphael では、中心座標と半径を指定しないと円を描くことができません。パス定義なしでパスを作成することはできません。実際のテキストなしでテキスト ラベルを作成することはできません。さらに、一部のプロパティは、ビジュアルの作成後にのみ設定できます。存在しないビジュアルの色、ストローク スタイルなどを設定することはできません。したがって、次のワークフローを想像できます。

var circle = new my.Circle();
circle.set({ x: 10, y: 20, r: 30 }); // can't set color here - no visual yet
circle.render(paper);
circle.set({ stroke: "red", strokeWidth: 5 });

オブジェクトを手動で作成すると、このワークフローを制御できます。しかし、シーン グラフ全体が (保存されたダイアグラムを読み込むために) JSON からアンマーシャリングされている場合、呼び出しのシーケンスを制御することはできず、すべてのプロパティが一度に設定されます。そのため、私の Circle クラスのmembersセクションには次のものが含まれています。

// Setter for stroke
_applyStroke: function(val, old) {
 this.element && this.element.attr({ stroke: val });
}
// The same for fill, stroke width, stroke style, arrowhead style etc.
// ...
render: function(paper) {
 this.element = paper.circle(this.getX(), this.getY(), this.getR());
 this._applyStroke(this.getStroke());
 this._applyStrokeWidth(this.getStrokeWidth());
 // repeat for each style property
}

ボイラープレートを少なくして同じことをする方法はありますか? 実際の要素が作成される前にスタイル属性を受け入れ、作成後にダミーの属性を実際の要素にコミットするために、ダミーのラファエル「要素」を作成することを考えていました。しかし、このアプローチでは、既存のコードに多くの変更を加える必要があるようです。これを達成するためのよりエレガントな方法があるかどうか疑問に思っていますか? AOP は qooxdoo でうまく機能するため、AOP ベースのソリューションは受け入れられます。

4

1 に答える 1

0

答えは、私が十分に知らない RafaelJS に関するいくつかの制約に依存していると思います。

  1. アプリで問題がなければ、x、y、r のデフォルト値を使用して my.Circle コンストラクターで要素を作成できます。次に、通常のプロパティ適用メソッドを要素属性に伝播させます。(これは、明示的なrender()メソッドを無効にします)。

  2. 要素のレンダリングが早すぎて、その属性に対するすべての変更が表示される場合 (これは避けたい場合があります)、要素の非表示/表示タイプのコントロールを探します。要素がまだ隠されているときに、要素を構築および変更できる場合があります。render()メソッドは、可視性を切り替えるだけです。

  3. これがすべて機能せず、何らかの理由でrender()メソッドで要素を作成する必要がある場合は、おそらく何らかの小さなプロトコルを回避する方法はありません。

    • 初期値またはユーザー定義の必須属性 (x、y、r など) に任意の値を指定して、 render()メソッドで要素を作成します。

    • 既存の要素にのみ設定できるプロパティに属する適用メソッドは、要素に直接書き込むのではなく、内部キュー (おそらく属性マップのリスト) に変更を書き込むことができます。このようにして、すべての「時期尚早」のプロパティ変更をキャプチャします。

    • render()メソッドは、キュー内の要素を適用するだけです。これにより、質問のタイトルで言及した「遅延プロパティ アプリケーション」が実装されます。欠点は、それ以降のすべてのプロパティ変更が次のrender()呼び出しでのみ有効になることです (今回は要素の作成を回避します)。

    • もちろん、それと既にあるものを組み合わせて、要素がまだ作成されていないときにキューに書き込み、それ以外の場合は直接変更することができます。

于 2013-06-27T12:48:52.800 に答える