6

問題

emberjsのリーフレットビューに取り組んでいますが、いくつか問題があります。リーフレットは外部ライブラリであり、質問とは多少関係がありませんが、マッピングライブラリであることを知っているだけです。

ズームレベルのような単純なプロパティを考えてみましょう。Leafletマップインスタンスには、を介してアクセスmap.getZoom()および割り当て可能なズームレベルがありますmap.setZoom(zoomLevel)。また、ユーザーはマップを操作したり、ズームレベルを変更したりできます。リーフレットを使用すると、ズームが変更されたときにコールバックを登録できます。

zoomLevel「Ember-Leaflet」ビューに残り火プロパティを設定したいと思います。zoomLevelこのようにして、残り火オブジェクトモデル(たとえば、テンプレートや別の値にバインド)の恩恵を受けることができ、「残り火の方法」で実行しています。

基本ソリューション

私が現在持っているのは、zoomLevelプロパティを持つEmber.Viewのサブクラスです。で、リーフレットdidInsertElementマップインスタンスを作成します。コードはコメント化されており、自明である必要があります。

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

チェックリスト

この質問をより「答えやすい」ものにするために、この問題の解決策は次の要件を満たす必要があると思います。

  1. プロパティzoomLevelが変更されると、マップはそれに応じてズームレベルを変更する必要があります(を使用してmap.setZoom(zoomLevel)
  2. ユーザーが地図上のズームをインタラクティブに変更する場合は、zoomLevelプロパティを変更する必要があります(おそらくリーフレットマップのzoomendイベントコールバックを使用して)

ここに一種の「循環依存」があることに注意してください。つまり、「変更時に何かを実行する(マップ上でsetZoom)zoomLevelおよび「何かが発生したときに(ユーザーがズームを変更する)、変更するzoomLevel」ということです。この循環オブザーバーの依存関係を回避できるソリューションが必要です。EmberのnotifyPropertyChangeが解決策になる可能性があります。

これは、 Emberの計算されたプロパティにとって理想的なタスクのように見えましたが、依存するプロパティの文字列に何を入れるべきかわかりませんでした。zoomLevel基本的には、残り火のプロパティではないものに依存するプロパティです。


アップデート

私の最初の試みは、オブザーバーを使用してリーフレットのズームを設定し、リーフレットのイベントをバインドしてビューzoomendを設定することでした。zoomLevel

問題:zoomendリーフレットイベントでzoomLevelを設定すると、オブザーバーが自動的に再度トリガーされます。私は自分自身を明確にしましたか?

したがって、この一連のイベントが発生します。

  1. zoomLevelインタラクティブマップで変更
  2. リーフレット火災zoomendイベント
  3. zoomendイベントコールバックは残り火を設定しますzoomLevel
  4. オブザーバーが実行します
  5. setZoom不必要にリーフレットを要求する

これは効率的ではありませんが、うまくいったかどうかは気になりません。問題は、ユーザーがズームを非常にすばやく複数回変更すると(マップ上の単純な長いスクロール)、オブザーバーが複数回呼び出され、リーフレットが混乱することです。

4

3 に答える 3

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

    }
});

基本的に、2つのシナリオがあります。

  1. ZoomLevelはプログラムで変更されました->マップ上のズームを更新します
  2. マップ上でzoomLevelが変更されました->補助プロパティに設定しました。コンピュータープロパティオブザーバーにも通知が届きます。マップ上でズームレベルを再度設定しませんでした。

しかし、私は新しい問題を抱えていますが、それはリーフレットに関連していると思います。コース上で別のズームアニメーションを呼び出すとsetZoom、このsetZoomは無視されます。たとえば、次を実行します。

map.setZoom(1);
map.setZoom(12);

1ズームレベルになります。

たぶん、リーフレット関連のSOの質問が役立つでしょう。

于 2013-03-27T16:19:04.627 に答える
1

emberのzoomLevelからsetZoomに移動するには、オブザーバーを使用できます。

逆にするには、リーフレットのzoomChangeにイベントをバインドする必要がある場合があります

于 2013-03-27T14:29:19.127 に答える
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: '&copy; <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>
于 2013-06-21T17:23:46.630 に答える