我正在尝试使用一些用户定义的svg图标作为传单上的标记,但是我认为整个任务对于我的浏览器来说太繁重了。
到目前为止,我一直在使用,L.circleMarker
但是现在我不得不使用星号,箭头,星星等标记,因此我决定将它们作为svg路径,然后将其插入而不是我的circleMarkers。为了使事情更复杂,我获得了超过30万的积分。使用circleMarkers,我可以制作一个可行的图表,虽然速度不快,但可以接受,尤其是当使用相当深的缩放来区分各个点时(否则,一切就像一个大斑点,没有用处)。
但是,使用svg标记时,图表的计算量变得很大,以至于浏览器只能挂起。我玩过100、1000和10000分,即使有1000分,差异也很明显。请问对此有什么解决方案,有人使用带有大量数据点的svg标记吗?我认为我的代码中正确使用了canvas,尤其是对于canvas,circleMarkers
但我可能会误会。任何帮助,高度赞赏。摘录中的代码,对底部的几行进行注释/取消注释:
return L.circleMarker(p, style(feature));
要么
console.log("Starting markers.")
return L.marker(p, {
renderer: myRenderer,
icon: makeIcon('6-pointed-star', style(feature).color),
});
从切换circleMarkers
到svg
标记。非常感谢!
PS。使用svg标记,代码会因Highlight事件而中断,但是我已经很了解发生了什么错误。circleMarkers
return L.circleMarker(p, style(feature));
rioV8..
8
您的SVG 6点标记不会由“画布”渲染。看一下DevTools,您会看到它们是img
带有base-64编码的svg作为源的标签。如果您有大量的标记,这将减慢HTML渲染器的速度。
CircleMarkers在画布上渲染。
通过创建一个新的L.Path
子类,您可以在画布上绘制所需的任何标记,并让Leaflet发挥其最大作用。在任何其他JS代码之前进行这些传单的修改,否则它将抱怨它不是构造函数。
L.Canvas.include({
_updateMarker6Point: function (layer) {
if (!this._drawing || layer._empty()) { return; }
var p = layer._point,
ctx = this._ctx,
r = Math.max(Math.round(layer._radius), 1);
this._drawnLayers[layer._leaflet_id] = layer;
ctx.beginPath();
ctx.moveTo(p.x + r , p.y );
ctx.lineTo(p.x + 0.43*r, p.y + 0.25 * r);
ctx.lineTo(p.x + 0.50*r, p.y + 0.87 * r);
ctx.lineTo(p.x , p.y + 0.50 * r);
ctx.lineTo(p.x - 0.50*r, p.y + 0.87 * r);
ctx.lineTo(p.x - 0.43*r, p.y + 0.25 * r);
ctx.lineTo(p.x - r, p.y );
ctx.lineTo(p.x - 0.43*r, p.y - 0.25 * r);
ctx.lineTo(p.x - 0.50*r, p.y - 0.87 * r);
ctx.lineTo(p.x , p.y - 0.50 * r);
ctx.lineTo(p.x + 0.50*r, p.y - 0.87 * r);
ctx.lineTo(p.x + 0.43*r, p.y - 0.25 * r);
ctx.closePath();
this._fillStroke(ctx, layer);
}
});
var Marker6Point = L.CircleMarker.extend({
_updatePath: function () {
this._renderer._updateMarker6Point(this);
}
});
您使用的方法与circleMarker相同
return new Marker6Point(p, style(feature));
在代码中,有2个L.canvas
实例和2个变量myRenderer
。我保留了全局变量,但仅在renderChart()
函数中构造了L.map()时才分配它。
对于演示,我使用了较大的标记区域并使用了10000个标记。我的浏览器没有任何问题。我size
将属性的值增加到500,这样我们得到了一个半径13像素的标记,因此您可以清楚地看到星星。
我使用了最新的传单版本1.3.3。
L.Canvas.include({
_updateMarker6Point: function (layer) {
if (!this._drawing || layer._empty()) { return; }
var p = layer._point,
ctx = this._ctx,
r = Math.max(Math.round(layer._radius), 1);
this._drawnLayers[layer._leaflet_id] = layer;
ctx.beginPath();
ctx.moveTo(p.x + r , p.y );
ctx.lineTo(p.x + 0.43*r, p.y + 0.25 * r);
ctx.lineTo(p.x + 0.50*r, p.y + 0.87 * r);
ctx.lineTo(p.x , p.y + 0.50 * r);
ctx.lineTo(p.x - 0.50*r, p.y + 0.87 * r);
ctx.lineTo(p.x - 0.43*r, p.y + 0.25 * r);
ctx.lineTo(p.x - r, p.y );
ctx.lineTo(p.x - 0.43*r, p.y - 0.25 * r);
ctx.lineTo(p.x - 0.50*r, p.y - 0.87 * r);
ctx.lineTo(p.x , p.y - 0.50 * r);
ctx.lineTo(p.x + 0.50*r, p.y - 0.87 * r);
ctx.lineTo(p.x + 0.43*r, p.y - 0.25 * r);
ctx.closePath();
this._fillStroke(ctx, layer);
}
});
var Marker6Point = L.CircleMarker.extend({
_updatePath: function () {
this._renderer._updateMarker6Point(this);
}
});
如果速度不够快,您始终可以设置自己的图块服务器,并以不同的缩放级别(在透明的PNG文件中)将标记烘烤到图块中。并将其用作地形图块上方的单独图块层。您没有简单的弹出窗口,但是300K标记的渲染非常快。您可以为要显示的每个图层/组制作一个瓷砖叠加层。所有服务均来自同一图块服务器。
1> rioV8..:
您的SVG 6点标记不会由“画布”渲染。看一下DevTools,您会看到它们是img
带有base-64编码的svg作为源的标签。如果您有大量的标记,这将减慢HTML渲染器的速度。
CircleMarkers在画布上渲染。
通过创建一个新的L.Path
子类,您可以在画布上绘制所需的任何标记,并让Leaflet发挥其最大作用。在任何其他JS代码之前进行这些传单的修改,否则它将抱怨它不是构造函数。
L.Canvas.include({
_updateMarker6Point: function (layer) {
if (!this._drawing || layer._empty()) { return; }
var p = layer._point,
ctx = this._ctx,
r = Math.max(Math.round(layer._radius), 1);
this._drawnLayers[layer._leaflet_id] = layer;
ctx.beginPath();
ctx.moveTo(p.x + r , p.y );
ctx.lineTo(p.x + 0.43*r, p.y + 0.25 * r);
ctx.lineTo(p.x + 0.50*r, p.y + 0.87 * r);
ctx.lineTo(p.x , p.y + 0.50 * r);
ctx.lineTo(p.x - 0.50*r, p.y + 0.87 * r);
ctx.lineTo(p.x - 0.43*r, p.y + 0.25 * r);
ctx.lineTo(p.x - r, p.y );
ctx.lineTo(p.x - 0.43*r, p.y - 0.25 * r);
ctx.lineTo(p.x - 0.50*r, p.y - 0.87 * r);
ctx.lineTo(p.x , p.y - 0.50 * r);
ctx.lineTo(p.x + 0.50*r, p.y - 0.87 * r);
ctx.lineTo(p.x + 0.43*r, p.y - 0.25 * r);
ctx.closePath();
this._fillStroke(ctx, layer);
}
});
var Marker6Point = L.CircleMarker.extend({
_updatePath: function () {
this._renderer._updateMarker6Point(this);
}
});
您使用的方法与circleMarker相同
return new Marker6Point(p, style(feature));
在代码中,有2个L.canvas
实例和2个变量myRenderer
。我保留了全局变量,但仅在renderChart()
函数中构造了L.map()时才分配它。
对于演示,我使用了较大的标记区域并使用了10000个标记。我的浏览器没有任何问题。我size
将属性的值增加到500,这样我们得到了一个半径13像素的标记,因此您可以清楚地看到星星。
我使用了最新的传单版本1.3.3。
L.Canvas.include({
_updateMarker6Point: function (layer) {
if (!this._drawing || layer._empty()) { return; }
var p = layer._point,
ctx = this._ctx,
r = Math.max(Math.round(layer._radius), 1);
this._drawnLayers[layer._leaflet_id] = layer;
ctx.beginPath();
ctx.moveTo(p.x + r , p.y );
ctx.lineTo(p.x + 0.43*r, p.y + 0.25 * r);
ctx.lineTo(p.x + 0.50*r, p.y + 0.87 * r);
ctx.lineTo(p.x , p.y + 0.50 * r);
ctx.lineTo(p.x - 0.50*r, p.y + 0.87 * r);
ctx.lineTo(p.x - 0.43*r, p.y + 0.25 * r);
ctx.lineTo(p.x - r, p.y );
ctx.lineTo(p.x - 0.43*r, p.y - 0.25 * r);
ctx.lineTo(p.x - 0.50*r, p.y - 0.87 * r);
ctx.lineTo(p.x , p.y - 0.50 * r);
ctx.lineTo(p.x + 0.50*r, p.y - 0.87 * r);
ctx.lineTo(p.x + 0.43*r, p.y - 0.25 * r);
ctx.closePath();
this._fillStroke(ctx, layer);
}
});
var Marker6Point = L.CircleMarker.extend({
_updatePath: function () {
this._renderer._updateMarker6Point(this);
}
});