4

この問題について何度も自分の考えを明確にしようとした後、私を正しい方向に向けることができるかもしれない専門家に頼るのが最善だと思いました.

概念は次のとおりです。概念のかなり基本的な考え方です。

  1. 最新のデータは、定期的にサーバー側からデータベースから取得されます。
  2. このデータは、Backbone.js、Ember.js、KnockoutJS などによって管理されるモデルに入れられます。
  3. 更新時に、キャンバス上の要素が関連情報で更新されます (キャンバスは KineticJS や Fabric.js などによって管理されます)。
  4. このプロセスを逆にして、キャンバス上の変更からデータをサーバーに送り返す可能性。

だから私の質問はこれです:キャンバスモデル(キャンバスライブラリのモデル)をMVVM/MVPモデルのモデルとリンクすることは実用的ですか? 私が見たものは HTML 要素に焦点を当てているようです (そして、以前にそのコンテキストで KnockoutJS に手を出しました) が、今回は代わりにキャンバス要素を管理しようとしています。それが可能である (または不可能である) 場合、または自家製のソリューションが必要な場合、何に注意すればよいでしょうか? どのような落とし穴がありますか?

数年前に似たようなことが起こったようですが、それ以降変更されたのでしょうか、それとも家庭でソリューションを開発することの問題なのでしょうか? そこにある答えを拡張できますか?

私は完全な解決策を探しているわけではありませんが、ある程度の経験を積んでいる人が私に何らかの方向性を示してくれることを求めています (この分野でまったく経験がなく、それについて話し合う人が誰もいない職場で私は唯一の人間です)または、それを理解するためにさえ、私はぐるぐる回っています)。

前もって感謝します。

4

2 に答える 2

1

少しの作業で、これを行うことができると思います。

カスタム バインディングを使用して、Raphael.js 要素をビュー モデルに接続しました。pub /sub フレームワークを使用して、canvas 要素のクリック イベント (これがあると仮定) からビュー モデルに通信できます。これにはjQuery pubsubプラグインをお勧めします。

参照用に見ることができるjsFiddleのがありますが、ビューから離れて戻ってきた場合にキャンバス要素を破棄して再作成する必要があるという問題を示すために作成したことに注意してください。だから完璧ではない。しかし、あなたはそれの要点をつかむことができるはずです。

注目すべき重要なセクションは、html コードのカスタム バインディングです。

<div class="span10" data-bind="foreach: Current">
    <div class="gauge" data-bind="createGauge: $data"></div>
</div>

カスタム バインディング js コード:

// Knockout handler to create a gauge for each bound item
ko.bindingHandlers.createGauge = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ko.utils.unwrapObservable(viewModel.updated);
        var gaugeName = viewModel.Name;
        var substation = bindingContext.$parent;

        var gaugeObject = substation.Gauges[gaugeName];

        // I cannot, for the life of me, get the gauge to redraw properly if I just
        // redraw the inner. Leave the real-time values page and come back, and
        // all the gauges are no longer visible.
        // So destroy the existing one and recreate it from scratch.
        // Yes, this is annoying!
        if (gaugeObject) {
            gaugeObject.gauge.removeChildren();
            gaugeObject.gauge.clear();
            gaugeObject.gauge.remove();
            gaugeObject.gauge = null;
            gaugeObject.paper.clear();
            gaugeObject.paper.remove();
            gaugeObject.paper = null;
            gaugeObject = null;
        }

        if (!gaugeObject) {
            var gaugeSize = $(element).height();
            var paper = new Raphael(element, gaugeSize, gaugeSize);
            var gauge = paper.gauge(viewModel);
            gaugeObject = {
                'paper': paper,
                    'gauge': gauge
            };
            substation.Gauges[gaugeName] = gaugeObject;
        }

        gaugeObject.gauge.updateValue(viewModel);
    }
};

Raphael ゲージ コード (ここではコピーしません。長いですが、そのコードで参照されているオブザーバブルは 1 つだけであることに注意してください。そうしないと、更新されたプロパティごとにそのゲージが更新され、すべてのプロパティを更新したかったのです。ビューモデルを一度に再描画しますが、ゲージを再描画するのは 1 回のみです)。ここで、canvas 要素のクリック関数を pubsub フレームワークにフックします。

gauge.clickFunction = function ()
{
    $.publish('/history', [point.IOReference]);
};

私のコードでは、それは別のビューに移動するだけですが、対応するサブスクライブ ハンドラーでは、必要に応じてビュー モデルを更新し、それをサーバーに保存し直します。

于 2013-02-12T09:20:26.767 に答える
1

これが素晴らしい答えかどうかはわかりません。代替案があるかどうか知りたいです。しかし、私は最近、あなたが提供したリンクで提案されていることと非常によく似たことをしました。

Backbone View を見ると、キャンバス要素には役に立たないと言ったDOM管理以外に、多くのことが行われているわけではありません。そこで、バックボーンのビューに似たスタイルの単純なオブジェクトをキャンバス要素で使用するように作成しました (イーゼル.js を使用しました)。

私はイーゼルJSを少しいじっていたので、このコードが完全であるとは言えません...

var CanvasView = function(options) {
        this.model = options.model;
        this.initialize.apply(this, arguments);
    };
_.extend(CanvasView.prototype, Backbone.Events, {
    initialize: function(options) {
        // in extended view, hook up to model change events, etc.
        // Since I used easel, here I also created some easel DisplayObjects,
        // then update their positions/etc. in response to model changes.
    }
});

これにさらに取り組むことがあれば、ビルトインのイーゼル「コンテナ」や、おそらくバックボーン ビューと同様の宣言型イベント ハッシュなど、さらに多くのものが追加されると思います。

于 2013-02-12T07:14:57.957 に答える