我正在为emberjs制作传单视图,我遇到了一些问题。 Leaflet是一个外部库,与问题有些无关,但只知道它是一个映射库。
考虑像缩放级别这样的简单属性。传单地图实例的缩放级别可通过map.getZoom()
访问,并可通过map.setZoom(zoomLevel)
分配。此外,用户可以与地图交互,并更改其缩放级别。当缩放发生变化时,Leaflet允许我们register a callback。
我希望我的“Ember-Leaflet”视图拥有zoomLevel
余烬属性。通过这种方式,我可以从ember对象模型中受益(例如,将zoomLevel
绑定到模板或另一个值),我们就是“使用ember方式”。
我目前拥有的是Ember.View的子类,具有zoomLevel属性。在didInsertElement
我创建Leaflet地图实例。代码已注释,应该是不言自明的。
App.Leaflet = Ember.View.extend({
classNames : ['ember-leaflet'],
//default zoom level
zoomLevel : 13,
didInsertElement : function() {
var self = this;
var zoomLevel = this.get('zoomLevel');
// create map instance
var map = L.map(this.$().get(0)).setView(center, zoomLevel);
// configure map instance...
// Event listeners
map.on('zoomend', function(e) {
self.set('zoomLevel', e.target.getZoom());
});
// save map instance
this.set('map', map);
}
});
为了使这个问题更“可回答”,我认为这个问题的解决方案应该满足以下要求:
zoomLevel
后,地图应相应更改其缩放级别(使用map.setZoom(zoomLevel)
)zoomLevel
属性(可能使用传单地图的zoomend
事件回调)请注意,我们在这里有一种“循环依赖”,即“当事情发生时zoomLevel
更改”和“时执行某些操作(setZoom在地图上)更改缩放),更改zoomLevel
“。我想要一个可以避免这种循环观察者依赖的解决方案。 Ember的notifyPropertyChange可能是一个解决方案。
这似乎是Ember's computed properties的理想任务,但我不知道在依赖属性字符串中放入什么。 zoomLevel
基本上是一个依赖于不是余烬属性的属性。
我的第一次尝试是使用观察者在传单上设置缩放并在活页zoomend
上绑定事件以在我的视图上设置zoomLevel
。
问题:当我在zoomend leaflet事件上设置zoomLevel时,我会再次自动触发我的观察者。我清楚了吗?
所以,这一系列事件发生了:
zoomLevel
zoomend
事件zoomend
事件回调设置了ember zoomLevel
setZoom
这效率不高,但我不介意它是否有效。 问题是,当用户非常快速地多次更改缩放时(地图上的一个简单的长滚动),观察者被多次调用confusing leaflet。
答案 0 :(得分:2)
好的,我想我已经做到了。
我使用了计算属性和辅助属性。
App.Leaflet = Ember.View.extend({
classNames : ['ember-leaflet'],
//default zoom level
zoomLevelValue : 13,
zoomLevel : function(key, value){
// getter
if (arguments.length === 1) {
var zoomLevel = this.get('zoomLevelValue');
return zoomLevel;
// setter
} else{
var map = this.get('map');
this.set('zoomLevelValue', value);
map.setZoom(value);
return value;
}
}.property('zoomLevelValue'),
didInsertElement : function() {
var self = this;
var zoomLevel = this.get('zoomLevel');
var map = L.map(this.$().get(0)).setView(center, zoomLevel);
// configure map instance...
// Event listeners
map.on('zoomend', function(e) {
console.log('zoomend', 'Setting zoomLevel '+e.target.getZoom());
self.set('zoomLevelValue', e.target.getZoom());
});
// save map instance
this.set('map', map);
}
});
基本上,有两种情况:
但是我有一个新问题,但我认为它与传单有关。当我在另一个缩放动画播放时调用setZoom
时,将忽略此setZoom。
例如,执行:
map.setZoom(1);
map.setZoom(12);
以1
缩放级别结束。
也许与传单相关的SO问题可以提供帮助。
答案 1 :(得分:1)
要从ember中的zoomLevel到setZoom,您可以使用观察者。
另一方面,你可能需要将一个事件绑定到传单上的zoomChange
答案 2 :(得分:1)
使用几乎不同的策略,我将zoomLevel设置为属性并从函数中观察它,并且如果属性的实际值与实际缩放不同,则仅在地图上设置缩放。 看到这个小提琴http://jsfiddle.net/5As2z/30/ 我将逻辑传递给控制器,视图在插入文档时设置了地图
App.ApplicationController = Ember.Controller.extend({
//default zoom level
zoomLevel: 13,
map: null,
zoomLevelChanged: function () {
var zoomLevel = this.get('zoomLevel');
var map = this.get('map');
//Control not changing the zoom of the map if it is yet at the value
if (zoomLevel != map.getZoom()) {
map.setZoom(zoomLevel);
}
}.observes('zoomLevel')});
App.ApplicationView = Ember.View.extend({
templateName: 'application',
didInsertElement: function () {
var center = [41.3823000, 2.1825000];
var controller = this.get('controller');
var zoomLevel = controller.get('zoomLevel');
var map = L.map('map').setView(center, zoomLevel);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// configure map instance...
// Event listeners
map.on('zoomend', function (e) {
console.log('zoomend', 'Setting zoomLevel ' + e.target.getZoom());
controller.set('zoomLevel', e.target.getZoom());
});
// save map instance
this.controller.set('map', map);
}});
HTML
<script type="text/x-handlebars" data-template-name="application">
<h1> Leaflet map ember example </h1>
{{view Ember.TextField valueBinding="zoomLevel"}}
<div id="map"></div >
</script>