记vue+leaflet的一次canvas渲染爆栈

Posted cqq626

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记vue+leaflet的一次canvas渲染爆栈相关的知识,希望对你有一定的参考价值。

背景:

在地图上绘制大量的circleMarker,leaflet能选择使用canvas来渲染,比起默认的svg渲染来说在大量绘制的情况下会更加流畅。但当触发其中某一个circleMarker的tooltip或popup时,浏览器报错“Uncaught RangeError: Maximum call stack size exceeded”:
技术分享图片

 

解决过程:

1、写了个测试代码来复现问题:

技术分享图片
 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta charset=‘utf-8‘ />
 5     <title>Add a raster tile source</title>
 6     <meta name=‘viewport‘ content=‘initial-scale=1,maximum-scale=1,user-scalable=no‘ />
 7     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
 8     <script src="https://unpkg.com/[email protected]/dist/leaflet-src.js"></script>
 9     <!--<script src="./vue.js"></script>-->
10     <!--<script src="./leaflet.js"></script>-->
11     <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
12           integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
13           crossorigin=""/>
14     <style>
15         * { margin:0; padding:0; }
16         html,body,#vue-wrap,#map { height: 100%; }
17     </style>
18 </head>
19 <body>
20     <div id="vue-wrap">
21         <div id="map">test</div>
22     </div>
23 <script>
24     new Vue({
25         el: ‘#vue-wrap‘,
26         data: function () {
27             return {
28                 map: ‘‘,
29                 canvas: L.canvas()
30             };
31         },
32         mounted: function () {
33             this.init();
34         },
35         methods: {
36             init () {
37                 this.map = new L.Map(‘map‘, {
38                     center: [39.928953, 116.389129],
39                     zoom: 11,
40                     maxZoom: 18,
41                     attributionControl: false,
42                     zoomControl: true
43                 });
44 
45                 this.paintMarkers();
46             },
47             paintMarkers () {
48                 console.log(‘start paint‘);
49                 console.time(‘paint‘);
50                 for (let i = 0; i < 50000; i++) {
51                     let marker = L.circleMarker(this.generateLatlng(), {
52                         color: ‘#000‘,
53                         weight: 1,
54                         opacity: 1,
55                         fillOpacity: 0.8,
56                         radius: 6,
57                         fillColor: ‘orange‘,
58 
59                         renderer: this.canvas
60                     });
61                     marker.bindTooltip(i + ‘‘);
62                     marker.bindPopup(`i: ${i}`);
63                     this.map.addLayer(marker);
64                 }
65                 console.timeEnd(‘paint‘);
66             },
67             generateLatlng () {
68                 let lat_min = 39.70111,
69                     lat_max = 40.14660,
70                     lng_min = 116.05843,
71                     lng_max = 116.63521;
72 
73                 let lat = this.getRandomNum(lat_min, lat_max),
74                     lng = this.getRandomNum(lng_min, lng_max);
75 
76                 return [lat, lng];
77             },
78             getRandomNum (min, max) {
79                 max = Math.max(min, max);
80                 min = Math.min(min, max);
81                 return Math.random() * (max - min) + min;
82             }
83         }
84     });
85 </script>
86 
87 </body>
88 </html>
View Code

 


以上是关于记vue+leaflet的一次canvas渲染爆栈的主要内容,如果未能解决你的问题,请参考以下文章

SVG 与 HTML5 的 canvas 各有啥优点,哪个更有前途

Leaflet系列:webgl方式加载point

使用vue学习three.js之加载和使用纹理-使用canvas画布上的绘画作为纹理渲染到方块上,使用动态绘画纹理

leaflet 动态线渲染

封装leaflet pm 地图打点标记组件

封装leaflet pm 地图打点标记组件