4

我正在尝试构建一个基于 Openlayers 和backbone.js 的应用程序。我应该让每一层都成为一个视图吗?到目前为止,我有一个地图视图、标记视图,并且正在考虑让每一层也成为一个视图。我有一个标记模型和地图模型。任何人都可以帮我设置这个吗?

4

2 回答 2

4

在与@Gagan 过去的回答类似之后,下次我会这样做:

将 OpenLayers Map 视为特殊的渲染表面 - 与 DOM 不同,类似于您对待<canvas>. 认识到 Backbone 围绕您的视图在 DOM 中呈现的想法做了一些(轻)假设:

  1. view.elViews 和它们对应的 DOM 节点(和view.$el魔法)之间有一种特殊的关系。

  2. events哈希会自动转换为在 DOM 节点上触发的事件的处理程序。

我们将要为我们的 OpenLayers 视图重新创建这些概念。一些想法:

  1. 在 Backbone 中,视图是模型和 DOM 的一部分之间的中介。在 OpenLayers 中,我们有一个 OpenLayers Feature、Vector、Marker、Popup 等,而不是 DOM 的一部分。我们可以在 View 和它的 OpenLayers 对象之间重新创建这种特殊关系。监听模型变化和更新 OpenLayers 对象的视图是自然而然的。监听和响应 OpenLayers 对象上的事件怎么样?

这是 OpenLayers 的难点之一。假设你有一个SelectControl. 您可以在层级监听事件,这将为您提供对event.feature. 但是您如何将该功能映射回您的视图以保持良好的职责分离?选择你的毒药。在下面的示例中,我将(重新)直接在视图已经有句柄的功能上触发事件。然后视图将不得不监听功能上的那些事件。请注意,OL 功能没有内置事件。我们将使用_.extend(object, Backbone.Events);.

  1. 您可以创建一个 featureEvents 哈希,但这可能是过度设计的。视图已经接收到模型对象并显式绑定到它的事件。在下面的示例中,我将对视图创建的 OL 功能执行相同的操作。

现在用于构建您的视图。我倾向于将 OpenLayersLayer视为项目的集合。假设您要渲染一组特征。您可以创建一个FeatureCollectionView用对象初始化的类Map。然后它将Layer为其集合创建一个。

FeatureCollectionView = Backbone.View.extend({
    initialize: function(options) {
        // requires options.map, an OpenLayers Map object.
        // requires options.collection, a FeatureCollection object.
        options = options || {};

        this.map = options.map;

        this.initLayer();
        this.initSelectControl();

        this.collection.on('add', this.addFeatureModel, this);
        this.collection.on('remove', this.removeFeatureModel, this);
        this.collection.each(this.addFeatureModel, this);

        // ...
    },

    initLayer: function() {
        this.layer = new OpenLayers.Layer.Vector('a collection of features', {/* options */});
        this.map.addLayers([this.layer]);
    },

    initSelectControl: function() {
        this.selectControl = new OpenLayers.Control.SelectFeature(this.layer, {
            hover: true,
            multiple: false,
            highlightOnly: true
        });

        this.map.addControl(this.selectControl);
        this.selectControl.activate();
        this.layer.events.on({
            featurehighlighted: function(event) {
                // requires that you've extended your view features with Backbone.Events
                if (event.feature.trigger) {
                    event.feature.trigger('featurehighlighted', event);
                }
            },
            featureunhighlighted: function(event) {
                // requires that you've extended your view features with Backbone.Events
                if (event.feature.trigger) {
                    event.feature.trigger('featureunhighlighted', event);
                }
            },
            scope: this
        });
    },

    addFeatureModel: function(model) {
        if (!this.views) this.views = {};

        this.views[model.cid] = new FeatureItemView({
            layer: this.layer,
            model: model
        });
    },

    removeFeatureModel: function(model) {
        this.views && this.views[model.cid] && this.views[model.cid].remove();
    },

    // ...

});

然后我们需要一个FeatureItemView用 OL 初始化的Layer来渲染自己。

MyFeatureView = Backbone.View.extend({
    initialize: function(options) {
        // requires options.layer, an OpenLayers Layer that is already added to your map.
        options = options || {};

        this.layer = options.layer;
        this.initSelectControl();

        // ...

        this.render();

        _(this.feature).extend(Backbone.Events);
        this.feature.on('featurehighlighted', this.showPopup, this);
        this.feature.on('featureunhighlighted', this.hidePopup, this);
    },

    render: function() {
        this.feature = // ...

        this.layer.addFeatures([this.feature]);

        // ...
    },

    remove: function() {
        this.layer.removeFeatures([this.feature]);
    },

    // ...

});

我通过搜索与“骨干和画布”相关的讨论找到了一些其他有趣的解决方案,因为它有一些相似的方面。

于 2014-01-14T17:50:59.627 回答
1

这个要点可能会对你有所帮助。对于使用 OpenLayers 理解 Backbone,它非常有用。 https://gist.github.com/bwreilly/2052314

于 2013-04-26T00:27:51.653 回答