问题

我正在为emberjs制作传单 View ,但遇到了一些问题。 Leaflet是一个外部库,与问题无关,但只知道它是一个映射库。

考虑一个简单的属性,例如缩放级别。传单 map 实例的缩放级别可以通过map.getZoom()进行访问,并可以通过map.setZoom(zoomLevel)进行分配。此外,用户可以与 map 互动,并更改其缩放级别。传单允许我们在缩放更改时添加register a callback

我希望我的“Ember-Leaflet” View 具有zoomLevel ember属性。这样,我就可以从ember对象模型中受益(例如,将zoomLevel绑定(bind)到模板或另一个值),而我们正在以“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);
    }
});

检查 list

为了使这个问题更“可回答”,我认为该问题的解决方案应满足以下要求:
  • 更改属性zoomLevel时, map 应相应地更改其缩放级别(使用map.setZoom(zoomLevel))
  • 当用户以交互方式更改 map 缩放时,应更改zoomLevel属性(可能使用传单 map 的zoomend事件回调)

  • 请注意,这里我们有一种“循环依赖关系”,即“当zoomLevel更改时执行某些操作( map 上的setZoom)”和“当某件事(用户更改缩放)时更改zoomLevel”。我想要一个可以避免这种循环观察者依赖性的解决方案。 Ember的notifyPropertyChange可能是一个解决方案。

    对于Ember's computed properties来说,这似乎是一项理想的任务,但我不知道在依赖属性字符串中应放置什么内容。 zoomLevel基本上是一个属性,该属性依赖于不是ember属性的内容。

    更新资料

    我的第一次尝试是使用观察者在传单上设置缩放并在传单zoomend上绑定(bind)一个事件以在我的 View 上设置zoomLevel

    问题:在zoomend传单事件上设置zoomLevel时,我会自动再次触发观察者。我说清楚了吗?

    因此,事件的顺序发生了:
  • 在交互式 map
  • 上更改zoomLevel
  • 传单触发zoomend事件
  • zoomend事件回调集 Ember zoomLevel
  • 观察者运行
  • 不必要地在传单
  • 上调用setZoom
    这效率不高,但是我不介意它是否有效。
    问题在于,当用户非常快速地多次更改缩放比例(在 map 上进行简单的长滚动)时,观察者被多次调用confusing leaflet

    最佳答案

    好吧,我想我已经做到了。

    我使用了计算属性和辅助属性。

    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);
    
        }
    });
    

    基本上有两种情况:
  • zoomLevel已通过编程方式进行了更改->我们更新了 map
  • 上的缩放比例
  • zoomLevel在 map 上已更改->我们在辅助属性上进行了设置,计算机属性的观察者也会收到通知,而我们没有在 map 上再次设置缩放级别

  • 但是我有一个新问题,但是我认为这与传单有关。当我在另一个缩放动画进行过程中调用setZoom时,将忽略此setZoom。
    例如,执行:
    map.setZoom(1);
    map.setZoom(12);
    

    最终达到1缩放级别。

    也许与传单相关的SO问题可以提供帮助。

    08-19 08:55