2015-05-06 103 views
0

我正面臨Leaflet(0.7.3版)的性能問題。我正在使用OSM貼圖來顯示一系列由裝飾折線連接的CircleMarkers(每25px帶有一個箭頭圖案)。加載需要一點時間,但主要問題是,當我縮放地圖時,我開始面臨嚴重滯後(來自縮放級別16),並超過一定的限制(大多數情況下說18),瀏覽器會凍結並最終崩潰(使用Chrome和Firefox進行測試)。我嘗試了一堆1000個鏈接的標記,然後我下降到了大約100個,但仍然是同樣的問題......當然,使用10個標記或更少的標記我沒有任何問題。縮放時出現性能問題(小冊子0.7.3)

您是否已經面臨類似的麻煩?我如何優化傳單表演,以便我可以使用超過100個鏈接的CircleMarkers進行精確縮放(超過16級)?我也想知道爲什麼演出都在不斷下降得很厲害縮放時,同時標記量保持不變...

預先感謝您爲您的回答,

Lenalys。

無法讓PolylineDecorator插件在jsfiddle上工作。 但這裏要說的是生成標記的代碼:

地圖初始化:

var map; 

function initializeMap(){ 
    "use strict"; 

    var layer; 
    var layer2; 

    function layerUrl(key, layer) { 
     return "http://wxs.ign.fr/" + key 
      + "/geoportail/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&" 
      + "LAYER=" + layer + "&STYLE=normal&TILEMATRIXSET=PM&" 
      + "TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg"; 
    } 

    layer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', 
    { 
    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors', 
    maxZoom: 18 
    }); 

    layer2 = L.tileLayer(
    layerUrl(IGN_AMBIENTE_KEY, "GEOGRAPHICALGRIDSYSTEMS.MAPS"), 
    {attribution: '&copy; <a href="http://www.ign.fr/">IGN</a>'} 
); 

    var baseMaps = { 
     "Terrestre": layer, 
     "Bathymetrique": layer2 
    }; 

    map = L.map('map', { 
     layers: [layer], 
     zoom: 8, 
     center: [42.152796, 9.139150], 
     zoomControl: false 
    }); 

    L.control.layers(baseMaps).addTo(map); 

    //add zoom control with your options 
    L.control.zoom({ 
     position:'topright' //topleft 
    }).addTo(map); 

    L.control.scale({ 
     position:'bottomleft', 
     imperial : false 
    }).addTo(map); 


} 

數據樣本:

變種jsonData = { 「12」:[{ 「id_stm_device」: 「7」,」 individual_name 「:」 cerf3" , 「緯度」: 「42.657283333333」, 「經度」: 「9.42362」, 「溫度」:空, 「脈衝」:NULL, 「電池」: 「20」, 「DATE_TIME」:「2015 - 03-17 15:37:12「}, {」id_stm_device「:」7「,」individual_name「:」cerf3「,」緯度「:」42.657381666667「,」經度「:」9.42365「,」溫度「:空,「pulse」:null,「battery」:「20」,「date_time」:「2015-03-17 16:42:16」}, {「id_stm_device」:「7」,「individual_name」:「cerf3」,「緯度」:「42.657381666667」,「經度」:「9.4236933333333」,「溫度」:空,「脈衝」:空,「電池」: 「20」,「date_time」:「2015-03-17 17:47:21」}, {「id_stm_device」:「7」,「individual_name」:「cerf3」,「latitude」:「42.657283333333」,「longitude 「:」9.4237383333333「,」temperature「:null,」pulse「:null,」battery「:」20「,」date_time「:」2015-03-17 19:57:23「}], 」13「: [{ 「id_stm_device」: 「8」, 「individual_name」: 「cerf5」, 「緯度」: 「42.61683」, 「經度」: 「9.4804633333333」, 「溫度」: 「17.45」, 「脈衝」:NULL,「電池「:」80「,」date_time「:」2015-04-08 07:45:20「}, {」id_stm_device「:」8「,」individual_name「:」cerf5「,」緯度「:」42.538858333333「, 「經度」:「9.48169」,「溫度」:「14.37」,「脈衝」:空,「電池」:「80」,「日期時間」:「2015-04-08 08:00:29」}, { 「id_stm_device」: 「8」, 「individual_name」: 「cerf5」, 「緯度」: 「42.458748333333」, 「經度」:「9 。「500225」,「temperature」:「14.46」,「pulse」:null,「battery」:「80」,「date_time」:「2015-04-08 08:15:49」}, {「id_stm_device」: 「8」, 「individual_name」: 「cerf5」, 「緯度」: 「42.3302」, 「經度」: 「9.5374583333333」, 「溫度」: 「15.19」, 「脈衝」:空, 「電池」: 「80」, 「date_time」:「2015-04-08 08:31:05」}, {「id_stm_device」:「8」,「individual_name」:「cerf5」,「緯度」:「42.170133333333」,「經度」:「9.5272116666667 「,」temperature「:」15.48「,」pulse「:null,」battery「:」80「,」date_time「:」2015-04-08 08:46:20「}, {」id_stm_device「:」8 「 」individual_name「: 」cerf5「, 」緯度「: 」42.07959「, 」經度「: 」9.47688「, 」溫度「: 」15.97「, 」脈衝「:NULL, 」電池「: 」80「,」 DATE_TIME 「:」2015-04-08 09:01:31「}, {」id_stm_device「:」8「,」individual_name「:」cerf5「,」緯度「:」42.076163333333「,」經度「:」9.4828633333333「, 「溫度」:「20.42」,「脈衝」:空,「電池」:「80」,「日期時間」:「2015-04-08 09:16:59」}, {「id_stm_device」:「8」,「individual_name」:「cerf5」,「緯度」:「42.07194」,「經度」:「9.4908866666667」,「溫度」:「17.36」,「脈衝」 「:」80「,」date_time「:」2015-04-08 09:32:17「}, {」id_stm_device「:」8「,」individual_name「:」cerf5「,」latitude「:」42.072583333333「, 「經度」: 「9.4901516666667」, 「溫度」:「17。36「,」pulse「:null,」battery「:」80「,」date_time「:」2015-04-08 09:47:32「}, {」id_stm_device「:」8「,」individual_name「:」 cerf5" , 「緯度」: 「42.07238」, 「經度」: 「9.4904266666667」, 「溫度」: 「19.38」, 「脈衝」:NULL, 「電池」: 「80」, 「DATE_TIME」:「2015-04- 08:10:42「}, {」id_stm_device「:」8「,」individual_name「:」cerf5「,」緯度「:」42.072298333333「,」經度「:」9.4904983333333「,」溫度「:」17.46「 ,「pulse」:null,「battery」:「80」,「date_time」:「2015-04-08 10:17:55」}, {「id_stm_device」:「8」,「individual_name」:「cerf5」 ,「緯度」:「42.095093333333」,「經度」:「9.5148383333333」,「溫度」:「17.47」,「脈衝」:空,「電池」:「80」,「日期時間」:「2015-04-08 10 :33:12「}, {」id_stm_device「:」8「,」individual_name「:」cerf5「,」緯度「:」42.112881666667「,」經度「:」9.5133133333333「,」溫度「:」19.3「脈衝「:空,」電池「:」80「,」date_time「:」2015-04-08 10:48:23「}, {」id_st m_device 「:」 8" , 「individual_name」: 「cerf5」, 「緯度」: 「42.112875」, 「經度」: 「9.513285」, 「溫度」: 「22.71」, 「脈衝」:NULL, 「電池」:」 80「,」date_time「:」2015-04-08 11:03:57「}, {」id_stm_device「:」8「,」individual_name「:」cerf5「,」緯度「:」42.141096666667「,」經度「 :「9.5078216666667」,「temperature」:「23.73」,「pulse」:null,「battery」:「80」,「date_time」:「2015-04-08 11:19:12」}, {「id_stm_device」 : 「8」, 「individual_name」: 「cerf5」, 「緯度」: 「42.282186666667」, 「經度」: 「9.5505183333333」, 「溫度」: 「18.97」, 「脈衝」:空, 「電池」: 「80」 ,「date_time」:「2015-04-08 11:34:28」}, {「id_stm_device」:「8」,「individual_name」:「cerf5」,「緯度」:「42.405126666667」,「經度」:「 9.531145「,」temperature「:」20.71「,」pulse「:null,」battery「:」80「,」date_time「:」2015-04-08 11:49:42「}, {」id_stm_device「:」 8" , 「individual_name」: 「cerf5」, 「緯度」: 「42.482063333333」, 「經度」: 「9.480665」, 「溫度」: 「21.7」, 「脈衝」 :NULL, 「電池」: 「80」, 「DATE_TIME」: 「2015-04-09 12時05分07秒」}]}

var oJSON = JSON.parse(jsonData); 



var colors = [ 
    "#400080", 
    "#008000", 
    "#EC7600", 
    "#E40341", 
    "#0D5E5E", 
    "#919191", 
    "#FF3C9D", 
    "#A70A0E", 
    "#00BFBF", 
    "#7171FF" 
    ]; 

var classes = [ 
    "color1", 
    "color2", 
    "color3", 
    "color4", 
    "color5", 
    "color6", 
    "color7", 
    "color8", 
    "color9", 
    "color10" 
]; 


var lastMarkers = []; 
var layers = new Array(); 
var polyline; 
var decorator; 

window.graphicsDevices = []; 
var offsetLatitude = 0.003333; 
var offsetLongitude = 0.011666; 

標記instanciation:

function printGPSOnMap(oJSON){ 
    var nbKeys = 0; 

    for (var key in oJSON) { 
    nbKeys++; 

    var classe = classes[(key-1)%classes.length]; 
    var color = colors[(key-1)%colors.length]; 

    var positionInfo = []; 

    if (oJSON.hasOwnProperty(key)) { 

      var aInfo = oJSON[key]; 
      var marker; 
      var latlngs = Array(); 

      var startMarker = lastMarkers[key]; 
      if(startMarker !== undefined && startMarker != null) { 

      var myIcon = L.divIcon({className: "myCircle "+classe, iconSize : [ 20, 20 ] }); 
      startMarker.setIcon(myIcon); 
      latlngs.push(startMarker.getLatLng()); 
      } 
      for(var i = 0; i < aInfo.length; i++) { 
       var oInfos = aInfo[i]; 
       var sIdIndividual = oInfos["id_individual"]; 
       var sLongitude = oInfos["longitude"]; 
       var sLatitude = oInfos["latitude"]; 
       var sTemperature = oInfos["temperature"]; 
       var sPulse = oInfos["pulse"]; 
       var sBattery = oInfos["battery"]; 
       var sDatetime = oInfos["date_time"]; 
       var sIndividualName = oInfos["individual_name"]; 
       var id_device = oInfos["id_stm_device"]; 

       var popupMsg = "..."; 

       latlngs.push(L.marker([sLatitude,sLongitude]).getLatLng()); 

       marker = new MyCustomMarker([sLatitude,sLongitude], { 
             icon : L.divIcon({ 
              className : "myCircle "+classe + ((i == aInfo.length-1) ? ' myCircleEnd' : ''), 
              iconSize : [ 20, 20 ] 
             }) 
             }); 
             marker.bindPopup(popupMsg, { 
               showOnMouseOver: true 
             }); 
             marker.bindLabel(key, { 
               noHide: true, 
               direction: 'middle', 
               offset: [offset[0], offset[1]] 
             }); 
       positionInfo.push(marker); 
     } 

     lastMarkers[key] = marker; 
     } 

     if(latlngs.length > 1) 
     { 

     polyline = L.polyline(latlngs, {className: classe, weight: 2,opacity: 0.4}).addTo(map); 
     decorator = L.polylineDecorator(polyline, { 
     patterns: [ 
      // define a pattern of 10px-wide arrows, repeated every 20px on the line 
      {offset: 0, repeat: '25px', symbol: new L.Symbol.arrowHead({pixelSize: 10, pathOptions: {fillOpacity:   
       0.76, color: color, weight: 1}})} 
     ]}).addTo(map); 
    } 

    if(!window.graphicsDevices.hasOwnProperty(key)) 
     window.graphicsDevices[key] = []; 
    for(var i = 0; i < positionInfo.length; i++) { 
     window.graphicsDevices[key].push(positionInfo[i]); 
     positionInfo[i].addTo(map); 
     if(latlngs.length > 1){ 
      window.graphicsDevices[key].push(polyline); 
      polyline.addTo(map); 
      window.graphicsDevices[key].push(decorator); 
      decorator.addTo(map); 
     } 
     } 
    }//foreach key 

} 

代碼爲自定義標記:

var MyCustomMarker = L.Marker.extend({ 

    bindPopup: function(htmlContent, options) { 
    if (options && options.showOnMouseOver) { 
     // call the super method 
     L.Marker.prototype.bindPopup.apply(this, [htmlContent, options]); 
     // unbind the click event 
     this.off("click", this.openPopup, this); 
     // bind to mouse over 
     this.on("mouseover", function(e) { 
     // get the element that the mouse hovered onto 
     var target = e.originalEvent.fromElement || e.originalEvent.relatedTarget; 
     var parent = this._getParent(target, "leaflet-popup"); 
     // check to see if the element is a popup, and if it is this marker's popup 
     if (parent == this._popup._container) 
      return true; 
     // show the popup 
     this.openPopup(); 
     }, this); 
     // and mouse out 
     this.on("mouseout", function(e) { 
     // get the element that the mouse hovered onto 
     var target = e.originalEvent.toElement || e.originalEvent.relatedTarget; 
     // check to see if the element is a popup 
     if (this._getParent(target, "leaflet-popup")) { 
      L.DomEvent.on(this._popup._container, "mouseout", this._popupMouseOut, this); 
      return true; 
     } 
     // hide the popup 
     this.closePopup(); 
     }, this); 
    } 
    }, 
    _popupMouseOut: function(e) { 

    // detach the event 
    L.DomEvent.off(this._popup, "mouseout", this._popupMouseOut, this); 
    // get the element that the mouse hovered onto 
    var target = e.toElement || e.relatedTarget; 
    // check to see if the element is a popup 
    if (this._getParent(target, "leaflet-popup")) 
     return true; 
    // check to see if the marker was hovered back onto 
    if (target == this._icon) 
     return true; 
    // hide the popup 
    this.closePopup(); 
    }, 

    _getParent: function(element, className) { 

    var parent = null; 

    if(element != null) parent = element.parentNode; 

    while (parent != null) { 
     if (parent.className && L.DomUtil.hasClass(parent, className)) 
     return parent; 
     parent = parent.parentNode; 
    } 
    return false; 
    } 
}); 
+0

這聽起來更像是有問題的代碼的問題,而不是一般的Leaflet問題。是否有可能發佈一些代碼,理想情況下在jsfiddle或類似的? – Liedman

+0

我使用生成標記的代碼編輯我的帖子:) – Lenalys

回答

0

您是否在canvas mode中衡量過性能? 在初始化傳單地圖容器之前使用L_PREFER_CANVAS = true.Might能夠幫助您。

+0

我已經嘗試了這個代碼片段,儘管性能增益很小,但是在縮放之後,地圖會繼續滯後和freezzing。我使用自定義標記而不是circleMarker,也許問題可能來自它? – Lenalys

+0

我在我的帖子中添加了「MyCustomMarker」對象的代碼。 – Lenalys

+0

您是否嘗試過在標記之間使用非裝飾的香草多段線而不是現在正在做的?嘗試瞭解瓶頸在哪裏。 – snkashis