4

在多次试图澄清我对此事的想法之后,我认为最好求助于一些专家,他们可能能够为我指明正确的方向。

概念如下,一个相当基本的概念:

  1. 定期从服务器端从数据库中检索最新数据。
  2. 这些数据被放入由 Backbone.js、Ember.js 或 KnockoutJS 等管理的模型中。
  3. 在更新时,画布上的元素会使用相关信息进行更新(画布由 KineticJS 或 Fabric.js 之类的东西管理)。
  4. 有可能逆转此过程,将数据从画布上的更改发送回服务器。

所以我的问题是:将画布模型(画布库的模型)与 MVVM/MVP 模型之一链接起来是否可行?我看过的那些似乎专注于 HTML 元素(我之前曾在这种情况下涉足过 KnockoutJS),但这次我试图管理画布元素。如果可能(或不可能),或者如果需要本土解决方案,我应该注意什么,有什么陷阱,我可能错过或忘记了什么?

几年前似乎出现了类似的情况,从那以后它发生了变化还是仍然是家庭发展解决方案的问题?里面的答案可以扩展吗?

我不是在寻找完整的解决方案,而是寻找有经验的人给我一些指导(我是工作中唯一一个在这方面有任何经验的人,没有任何人可以与之讨论或者,为了理解它,我在绕圈子)。

提前致谢。

4

2 回答 2

1

我不确定这是一个很好的答案,我很想知道是否有任何替代方案。但是,我最近做了一些与您提供的链接中建议的非常相似的事情。

如果您查看 Backbone View,除了 DOM 管理之外并没有太多其他功能,就像您所说的那样,这对于画布元素是无用的。因此,我以类似于 Backbone 的 View 的样式制作了一个简单的对象,以与画布元素一起使用(我使用了 easel.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.
    }
});

我想如果我在这方面做更多的工作,就会添加更多的东西,比如内置的画架“容器”,可能还有类似于 Backbone View 的声明性事件哈希。

于 2013-02-12T07:14:57.957 回答
1

我确实认为您可以通过一些工作来做到这一点。

我已经使用自定义绑定将 Raphael.js 元素连接到视图模型,并且您可以使用 pub/sub 框架从画布元素单击事件(假设它具有此事件)与您的视图模型进行通信。我会为此推荐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 仪表代码(我不会在这里复制它,它很长,但请注意我在该代码中只引用了一个 observable,否则该仪表将针对每个更新的属性进行更新,我想更新所有属性一口气在视图模型上,但只有仪表重绘一次),我将画布元素的点击功能挂钩到 pubsub 框架:

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

在我的代码中,它只导航到不同的视图,但在相应的订阅处理程序上,您可以根据需要更新视图模型并将其保存回服务器。

于 2013-02-12T09:20:26.767 回答