【发布时间】:2015-05-06 10:04:18
【问题描述】:
我遇到了 Leaflet(0.7.3 版)的性能问题。我正在使用一个 OSM 地图,我用它来显示一堆由装饰折线链接的 CircleMarkers(每 25 像素带有箭头图案)。加载需要一点时间,但主要问题是,当我缩放地图时,我开始面临严重滞后(从缩放级别 16 开始),并且超过一定限制(大部分时间说 18),浏览器只是冻结并最终崩溃(用chrome和firefox测试)。我尝试了一堆 1,000 个链接标记,然后我下降到一组大约 100 个,但仍然存在同样的问题……当然,使用 10 个或更少的标记我没有任何问题。
您是否已经遇到过类似的麻烦?如何优化 Leaflet 性能,以便我可以使用具有 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: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
maxZoom: 18
});
layer2 = L.tileLayer(
layerUrl(IGN_AMBIENTE_KEY, "GEOGRAPHICALGRIDSYSTEMS.MAPS"),
{attribution: '© <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);
}
数据样本:
var jsonData ={"12":[{"id_stm_device":"7","individual_name":"cerf3","latitude":"42.657283333333","longitude":"9.42362","temperature":null ,"脉冲":null,"电池":"20","date_time":"2015-03-17 15:37:12"}, {"id_stm_device":"7","individual_name":"cerf3","latitude":"42.657381666667","longitude":"9.42365","temperature":null,"pulse":null,"battery":" 20","date_time":"2015-03-17 16:42:16"}, {"id_stm_device":"7","individual_name":"cerf3","latitude":"42.657381666667","longitude":"9.4236933333333","temperature":null,"pulse":null,"battery":" 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","latitude":"42.61683","longitude":"9.4804633333333","temperature":"17.45","pulse":空,"电池":"80","date_time":"2015-04-08 07:45:20"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.538858333333","longitude":"9.48169","temperature":"14.37","pulse":null,"battery" :"80","date_time":"2015-04-08 08:00:29"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.458748333333","longitude":"9.500225","temperature":"14.46","pulse":null,"battery" :"80","date_time":"2015-04-08 08:15:49"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.3302","longitude":"9.5374583333333","temperature":"15.19","pulse":null,"battery" :"80","date_time":"2015-04-08 08:31:05"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.170133333333","longitude":"9.5272116666667","temperature":"15.48","pulse":null,"battery" :"80","date_time":"2015-04-08 08:46:20"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.07959","longitude":"9.47688","temperature":"15.97","pulse":null,"battery" :"80","date_time":"2015-04-08 09:01:31"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.076163333333","longitude":"9.4828633333333","temperature":"20.42","pulse":null,"battery" :"80","date_time":"2015-04-08 09:16:59"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.07194","longitude":"9.4908866666667","temperature":"17.36","pulse":null,"battery" :"80","date_time":"2015-04-08 09:32:17"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.072583333333","longitude":"9.4901516666667","temperature":"17.36","pulse":null,"battery" :"80","date_time":"2015-04-08 09:47:32"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.07238","longitude":"9.4904266666667","temperature":"19.38","pulse":null,"battery" :"80","date_time":"2015-04-08 10:02:42"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.072298333333","longitude":"9.4904983333333","temperature":"17.46","pulse":null,"battery" :"80","date_time":"2015-04-08 10:17:55"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.095093333333","longitude":"9.5148383333333","temperature":"17.47","pulse":null,"battery" :"80","date_time":"2015-04-08 10:33:12"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.112881666667","longitude":"9.5133133333333","temperature":"19.3","pulse":null,"battery" :"80","date_time":"2015-04-08 10:48:23"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.112875","longitude":"9.513285","temperature":"22.71","pulse":null,"battery" :"80","date_time":"2015-04-08 11:03:57"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.141096666667","longitude":"9.5078216666667","temperature":"23.73","pulse":null,"battery" :"80","date_time":"2015-04-08 11:19:12"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.282186666667","longitude":"9.5505183333333","temperature":"18.97","pulse":null,"battery" :"80","date_time":"2015-04-08 11:34:28"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.405126666667","longitude":"9.531145","temperature":"20.71","pulse":null,"battery" :"80","date_time":"2015-04-08 11:49:42"}, {"id_stm_device":"8","individual_name":"cerf5","latitude":"42.482063333333","longitude":"9.480665","temperature":"21.7","pulse":null,"battery" :"80","date_time":"2015-04-08 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;
标记实例化:
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;
}
});
【问题讨论】:
-
这听起来更像是相关代码的问题,而不是一般的传单问题。您是否可以发布一些代码,最好是在 jsfiddle 或类似网站上?
-
我用生成标记的代码编辑我的帖子 :)
标签: performance leaflet openstreetmap zooming