用织梦做的网站下载地址网站开发语言在线检测

当前位置: 首页 > news >正文

用织梦做的网站下载地址,网站开发语言在线检测,应用市场下载手机版,汽车行业网站建设比较好目录 前言 一、场景重现 1、遇到问题的代码 2、问题排查 二、通过实验验证猜想 1、排查LayerGroup和FeatureGroup 2、排查Leaflet.canvaslabel.js 三、柳暗花明又一村 1、点聚类的办法 2、歪打正着 总结 前言 在上一篇博客中介绍了基于SpringBoot的全国风景区WebGIS按… 目录 前言 一、场景重现 1、遇到问题的代码 2、问题排查 二、通过实验验证猜想 1、排查LayerGroup和FeatureGroup 2、排查Leaflet.canvaslabel.js 三、柳暗花明又一村 1、点聚类的办法 2、歪打正着 总结 前言 在上一篇博客中介绍了基于SpringBoot的全国风景区WebGIS按省展示实践。在这篇博客中关于旅游景点我是使用Leaflet.canvaslabel.js进行静态标注的其实在案例中要实现点击风景区点然后自动弹出它的其它信息比如景点名称所在省市县信息还有设立年份。最开始打算采用bindPopup的方案在编写代码的过程当中发现一个有趣的问题。在点击所在省份之后再把景点信息列表在地图上渲染出来然后针对每个点绑定popup。但实际的情况是界面上的景点点击后没有任何反应奇怪的是有时候又可以点。当时想着如果是代码的绑定得有问题肯定是都出不来不存在一份代码两种效果的情况。 遇到了问题便解决问题。在没有找到具体的问题前首先检查代码的问题然后检查相应的组件是否有什么缺陷最后再梳理解决办法大致的思路如此。本文在此背景下诞生博文首先详细介绍了风景区展示时具体的问题然后分析排查思路和方向接着使用不同的方案验证思路最后给出最终的解决方案。解决问题就是对症下药一样找到了病根基本上就是药到病除解决了问题的酸爽感一定让很多技术圈朋友深有体会吧。 一、场景重现 我想在讲述一些解决办法之前还是把碰到的详细问题描述清楚。首先是不至于让看到博文的朋友感到很诧异第二是对于解决方案的前提条件有一个具象的描述。能让我们知道为什么会这样出现了什么情况我们要解决的问题是什么。这里结合代码和实际效果来讲解这样可能比较有针对性。 1、遇到问题的代码 这里将之前的第一版代码贴出来肯定有朋友第一眼就能看到问题的所在但当时折腾了我很久。也许旁观者清也许是经验比较多曾经遇到过一下子就解决了。 /* 展示省份geojson范围*/ function showProvince(id){var myStyle {color:white,weight:5,opacity:1,fillOpacity: 0};\(.ajax({ type:get, url:prefix /geojson/ id, dataType:json, cache:false,processData:false,success:function(result){if(undefined ! provinceAreaLayer ){provinceAreaLayer.removeFrom(mymap);//先移除}if(result.code web_status.SUCCESS){var geojson JSON.parse(result.data);provinceAreaLayer L.geoJSON(geojson,{style:myStyle}).addTo(mymap);//同时设置中心位置和级别一般省份设置为7mymap.setView(provinceAreaLayer.getBounds().getCenter(),7);}},error:function(){\).modal.alertWarning(获取空间信息失败);}); }/风景区展示/
function showScenicSpot(code){\(.ajax({ type:get, url:prefix /datalist/ code, dataType:json, success:function(result){if(result.code web_status.SUCCESS){var strokeStyleSet #23168d;var lat,lng,cityInfo;for(var i0;iresult.data.length;i){var dataInfo result.data[i];var geomObj JSON.parse(dataInfo.geomJson);if(i 0){lat geomObj.coordinates[1];lng geomObj.coordinates[0];continue;}var radiusSize 5;var content strong名称:/strongdataInfo.name br/strong级别:/strong dataInfo.level;content br/strong所属行政区划:/strong dataInfo.province / dataInfo.city / dataInfo.area;content br/strong评定时间:/strong dataInfo.evaluationTime ;var latlng new L.latLng(geomObj.coordinates[1], geomObj.coordinates[0]);let marker L.circleMarker(latlng, {radius: radiusSize,color: strokeStyleSet,labelStyle: {offsetX: 0, //横坐标偏移(像素)offsetY: 30, //纵坐标偏移(像素)text: dataInfo.name,rotation: 0,zIndex: radiusSize,minZoom : 5,strokeStyle: strokeStyleSet}}).addTo(showLayerGroup);marker.bindPopup(content); }mymap.addLayer(showLayerGroup);}},error:function(){\).modal.alertWarning(获取信息失败);}}); } 不出意外的话还是出了意外我们来计划在点击风景区时通过bindPopup弹出经典的一些附属信息。但是无论点击哪个景点似乎都没有符合我们的预期效果如下 遇到点击了没有效果的情况第一个想到的原因是看一下网页的控制台看是否有什么报错信息。根据这个思路我们打开浏览器的控制台看一下 很遗憾控制台没有想要的信息代码是没有问题的可以正常运行的。那么问题到底出在哪里呢  2、问题排查 在明确没有代码语法问题和报错的前提下怎么解决这个问题呢代码是严格按照我们的设计去执行的但是为什么没有按照我们的预期效果来展示呢当时博主从下面两个方向进行思考。首先、排查相关组件的引用是否有问题因为在本案例中涉及到LayerGroup和FeatureGroup的使用是否是因为涉及Group的增加和删除导致了标记对象的事件显示不征程。其次想到的是Leaflet.canvaslabel.js这个组件本身是不是有问题在数量规模和事件绑定上是不是有什么不对的地方。受限于博主的经验首先想到了这两个方面因此排查工作也由此展开。 二、通过实验验证猜想 针对问题我们有了两个方面的猜想要想验证猜想的成立就必须通过代码实验通过实验说明问题可以解决这样才是有说服力的。本节针对上述猜想阐述两个实验环节。 1、排查LayerGroup和FeatureGroup 怀疑LayerGroup和FeatureGroup有问题的根据是因为在展示省份地理范围和风景区点位列表时我们都会设计Group的操作通过Group可以实现图层级的隐藏和展示可以实现某一专题的元素共同的可视化。但是在切换省份时要想实现只展示当前省份和所属的风景区信息首先要把之前的省份地理范围清空掉同时也把之前省份的风景区列表清除掉。所以映入眼帘的第一个嫌疑人出现。添加元素和移除的方法如下 function preview(code,id){showLayerGroup.clearLayers();//图层要素清除showProvince(id);showScenicSpot(code); } 要素添加到图层的代码如下 let marker L.circleMarker(/省略/).addTo(showLayerGroup); mymap.addLayer(showLayerGroup); 通过在Leaflet的官方网站中查看API文档查看相关的示例代码并没有发现什么问题。甚至在当时调试的情况下已经不采用Group的方案直接把marker添加到Map当中问题依然没有解决至此排除是LayerGroup或者FeatureGroup引起的问题。 2、排查Leaflet.canvaslabel.js 在把LayerGroup和FeatureGroup排除了嫌疑之后把目光转向了Leaflet.canvaslabel.js。思考是不是因为Leaflet.canvaslabel.js这个组件自身有什么缺陷在大规模数据量的时候或者说我们在API的调用有没有什么问题。带着这个疑问我们来做两个实验。第一个实验是针对性的看API是否有什么方法或者属性配置没有正确配置。第二个实验是Leaflet.canvaslabel.js配合大规模数据点比如5000个点的情况下能否正常bindPopup。下面逐步来进行验证 options: {defaultLabelStyle: {offsetX: 0, //横坐标偏移(像素)offsetY: 0, //纵坐标偏移(像素)scale: 1, //放大比例rotation: 0, //旋转角度弧度可能会导致碰撞检测不准确text: null, //标注文本内容minZoom: null, //最小显示级别maxZoom: null, //最大显示级别collisionFlg: true, //碰撞检测center: null, //标注位置默认为null,会自动计算几何中心zIndex: 0, //排序defaultHeight: 20, //文本高度,无法自动计算,所以直接传参手动调整//文本样式,具体值请参考canvasfont: 10px sans-serif,fillStyle: rgba(0,0,0,1),lineCap: round,lineDash: [],lineDashOffset: 0,lineJoin: round,strokeStyle: rgba(0,0,0,1),textAlign: center,textBaseline: middle,lineWidth: 1,},}, 这是组件的属性配置基本上与标注的可视化没有关系。再来看事件和执行器 /*** 执行侦听器/_executeListeners: function (event) {if (!this._textBounds) return;var me this;var ret this.getTextByEvent(event);if (ret ret.length 0) {me._map._container.style.cursor pointer;if (event.type click) {me._onClickListeners.forEach(function (listener) {listener(event, ret);});}if (event.type mousemove) {me._onHoverListeners.forEach(function (listener) {listener(event, ret);});}if (event.type mousedown) {me._onMouseDownListeners.forEach(function (listener) {listener(event, ret);});}if (event.type mouseup) {me._onMouseUpListeners.forEach(function (listener) {listener(event, ret);});}} else {me._map._container.style.cursor ;}},/** 添加click侦听器*/addOnClickListener: function (listener) {this._onClickListeners.push(listener);}, 通过代码发现组件也并有修改逻辑只是接收点击事件然后添加到执行器中。基本排除了组件自身的问题。那么剩下最后一个猜想大规模数量下组件的事件是不是失效了。因此我们进行大规模数据量的加载试验。 在之前的博文中在Leaflet中点对象使用SVG和Canvas两种模式的对比对组件的加载能力有较详细的描述在使用5000甚至10000个点的规模下展示非常迅速同时点击对象也能实现Popup的快速提示。 var count 30000; for (let i 0; i count; i) {let latlng L.latLng(23.95 Math.random() * 10, 112.40034 Math.random() * 15);var content strong名称:/strong城市i br/strong级别:/strong i;content br/strong所属行政区划:/strong i / ;content br/strong评定时间:/strong i ;var title 重要城市 Math.random();let c L.circleMarker(latlng, {radius: 5,labelStyle: {text: title,rotation: 0,zIndex: 1,strokeStyle: red,}}).addTo(showGroup);c.bindPopup(content); } map.addLayer(showGroup); 经过两个方向几个步骤的排查依然没有找到具体的原因也没有找到解决方案。有点懊恼于是想着换个思路。对组件的多点展示能力有初步怀疑但没有找到原因。 三、柳暗花明又一村 山重水复疑无路柳暗花明又一村。这句话用形容当时解决问题的情况非常贴切在两个方向都明确没有定位最终问题的情况下。我决定用之前遇到的一个点聚类的思路。遇到问题不要放弃再没有方向的时候发散思路解决了问题经验值就此提升。因此遇到bug解决bug才是好的态度。这里分两个步骤描述问题的解决办法。 1、点聚类的办法 带着之前没有找到的根本问题一直将注意力集中在风景区的点数量上。怀疑是不是点多了导致了事件响应的问题。所以考虑减少点位信息在Leaflet当中可以通过点聚类的办法介绍视野内的对象通过减少点的渲染保障Popup的正常可视化。 大家还记得点聚类的组件用什么吗之前也有文章进行深入讲解就是用leaflet.markercluster-src。代码就不详细贴了创建聚合图层将点添加到图层中。 //创建聚合图层并设置最大聚合半径为 26像素 var markersGroup L.markerClusterGroup({maxClusterRadius: 26}); 通过点聚合发现确实能解决几个省的展示问题当时以为找到了解决办法很欣喜但是在浙江时发现有风景区不能很好的展示出来。开始对数据的加载机制有个第一次怀疑这算个歪打正着。本来没有怀疑数据的加载机制。 2、歪打正着 在对数据的加载机制有了怀疑之后便迅速去看代码。在展示省份地理范围的代码中我们使用ajax的方式去后台请求数据ajax请求头如下 type:get,
url:prefix /geojson/ id,
data:{},
dataType:json 众所周知在ajax当中其默认的数据加载方式异步的也就是asynctrue。其实到了这里才是真正的问题根源。就是由于数据请求的异步方式导致了组件的事件响应问题。再来看一下代码 function preview(code,id){showLayerGroup.clearLayers();//图层要素清除showProvince(id);showScenicSpot(code);} 在上述代码中首先异步加载省份的geojson地理范围再异步加载风景区信息。也就是异步的问题导致的虽然方法看起来像是先加载地理范围实际上设置了异步可能地理范围还没有加载完风景区信息已经再加载了。也正是这个原因导致了事件不响应。按照这个思路我们将ajax方法设置为同步的方式即asyncfalse。 再来看具体的效果以浙江为例 杭州西湖风景区 杭州市千岛湖风景区 浙江普陀山风景区 至此问题得以全部解决Leaflet.canvaslabel在Ajax异步请求时bindPopup无效的解决办法。导致popup无效的问题是ajax的异步机制导致的。当然在实际开发当中您可以使用一个解决返回所有的数据把空间范围和数据列表同时返回就不存在上述问题了。解决办法很多找到问题根本很重要。遇到问题慢慢分析大胆设想小心验证一定会有收获不放弃。 总结 以上就是本文的主要内容本文分享了作者在排查GIS问题当中的一些思路和方法。在没有找到具体的问题前首先检查代码的问题然后检查相应的组件是否有什么缺陷最后再梳理解决办法大致的思路如此。本文在此背景下诞生博文首先详细介绍了风景区展示时具体的问题然后分析排查思路和方向接着使用不同的方案验证思路最后给出最终的解决方案。行文仓促定有不足之处案例的排查方法和经验都不足欢迎有经验的大佬基于批评指正万分感谢。