我正在尝试构建一个基于 Openlayers 和backbone.js 的应用程序。我应该让每一层都成为一个视图吗?到目前为止,我有一个地图视图、标记视图,并且正在考虑让每一层也成为一个视图。我有一个标记模型和地图模型。任何人都可以帮我设置这个吗?
2 回答
在与@Gagan 过去的回答类似之后,下次我会这样做:
将 OpenLayers Map 视为特殊的渲染表面 - 与 DOM 不同,类似于您对待<canvas>
. 认识到 Backbone 围绕您的视图在 DOM 中呈现的想法做了一些(轻)假设:
view.el
Views 和它们对应的 DOM 节点(和view.$el
魔法)之间有一种特殊的关系。events
哈希会自动转换为在 DOM 节点上触发的事件的处理程序。
我们将要为我们的 OpenLayers 视图重新创建这些概念。一些想法:
- 在 Backbone 中,视图是模型和 DOM 的一部分之间的中介。在 OpenLayers 中,我们有一个 OpenLayers Feature、Vector、Marker、Popup 等,而不是 DOM 的一部分。我们可以在 View 和它的 OpenLayers 对象之间重新创建这种特殊关系。监听模型变化和更新 OpenLayers 对象的视图是自然而然的。监听和响应 OpenLayers 对象上的事件怎么样?
这是 OpenLayers 的难点之一。假设你有一个SelectControl
. 您可以在层级监听事件,这将为您提供对event.feature
. 但是您如何将该功能映射回您的视图以保持良好的职责分离?选择你的毒药。在下面的示例中,我将(重新)直接在视图已经有句柄的功能上触发事件。然后视图将不得不监听功能上的那些事件。请注意,OL 功能没有内置事件。我们将使用_.extend(object, Backbone.Events);
.
- 您可以创建一个 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]);
},
// ...
});
我通过搜索与“骨干和画布”相关的讨论找到了一些其他有趣的解决方案,因为它有一些相似的方面。
这个要点可能会对你有所帮助。对于使用 OpenLayers 理解 Backbone,它非常有用。 https://gist.github.com/bwreilly/2052314