ArcGIS Js Api 3.x 熱力圖在數據量達到三萬左右的時候,繪製速度不盡人意,數據量再大些,縮放時候就會很卡,很是影響客戶體驗。
參考了一下網上webgl熱力圖,能達到更流暢的繪製的要求。(參考webgl-heatmap和heatmap-layer-js)webgl熱力圖使用很簡單,只須要把屏幕座標和權重設置到好就行,以下示例
javascript
heatmap.addPoints([{x:x, y:y, size:size, intensity:intensity}]);
依靠這個插件進行下熱力圖擴展,熱力圖插件和地圖綁定首先要將地圖座標點轉換出屏幕座標就行了,設置好事件去聯動請求數據。css
var dataPoint = new Point(geo.x, geo.y, map.spatialReference); screenGeometry = map.toScreen(dataPoint);
綁定好數據還要作的就是將熱力圖的畫布元素放入合適位置(整好疊在地圖上,尺寸一致),不影響地圖自己操做。html
var canvas = document.getElementsByTagName('canvas')[0]; var heatmap = createWebGLHeatmap({ canvas: canvas, intensityToAlpha: true }); var reforeNode = document.getElementById("map_gc"); document.getElementById("map_layers").insertBefore(heatmap.canvas, reforeNode);
寫好了擴展,生成十萬的隨機數據進行測試,與自帶的熱力圖進行一下對比。自帶熱力圖: 435.635ms;webgl熱力圖擴展:126.260ms。說明webgl速度更快,同時使用過程不存在地圖卡頓,性能提高顯著
附完整代碼java
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9"/> <!--The viewport meta tag is used to improve the presentation and behavior of the samples on iOS devices--> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>heatmap.js ArcGIS JavaScript API Heatmap Layer</title> <link rel="shortcut icon" type="image/png" href="http://www.patrick-wied.at/img/favicon.png"/> <link rel="stylesheet" href="https://js.arcgis.com/3.24/esri/css/esri.css"> <style> body, html { margin: 0; padding: 0; width: 99.9%; height: 99.9%; font-family: Arial; } #map { width: 100%; height: 100%; margin: 0; padding: 0; border: 0px dashed black; background-color: rgb(0, 38, 48); } </style> </head> <body> <div id="map"> </div> </body> <script src="https://js.arcgis.com/3.24/"></script> <script type="text/javascript" src="heatmap/webgl-heatmap.js"></script> <script type="text/javascript"> var map; require([ "esri/map", "dojo/on", "dojo/dom", "esri/layers/ArcGISTiledMapServiceLayer", "esri/tasks/query", "esri/tasks/QueryTask", "esri/geometry/screenUtils", "esri/geometry/Extent", "esri/geometry/Point", "dojo/domReady!" ], function ( Map, on, dom, ArcGISTiledMapServiceLayer, Query, QueryTask, screenUtils, Extent, Point ) { // Variables var valueField = 'Focal' // get the features within the current extent from the feature layer function getFeatures() { var q = new Query(); var url = 'http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Earthquakes_Since_1970/FeatureServer/0' var queryTask = new QueryTask(url); q.geometry = map.extent; q.where = "1=1"; q.outFields = [valueField ] q.orderByFields = [valueField ]; q.returnGeometry = true q.geometryPrecision = 10; q.outSpatialReference = map.spatialReference; queryTask.execute(q, function (re) { console.log(re.features.length) if (re.features.length) { console.time('end') console.log(re.features) setdata(re.features); console.timeEnd('end') } }); } var mapExtent = new Extent({ xmax:22189975.059293926, xmin: -15302081.56646192, ymax: 8961447.604325403, ymin: -9569334.036901515, spatialReference: {wkid: 102100} }) map = new Map("map", { basemap: "gray", extent: mapExtent, sliderStyle: "small", logo: false }); map.resize(); var canvas = document.createElement('canvas'); canvas.id = "heatLayer"; canvas.style.zIndex = 99 canvas.style.position = "absolute"; canvas.style.width="100%" canvas.style.height="100%" var heatmap = createWebGLHeatmap({ canvas: canvas, //gradientTexture: 'heatmap-gradient2.png', intensityToAlpha: true }); var reforeNode = document.getElementById("map_gc"); document.getElementById("map_layers").insertBefore(heatmap.canvas, reforeNode); var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var update = function () { //heatmap.addPoint(100, 100, 100, 10/255); heatmap.adjustSize(); // can be commented out for statically sized heatmaps, resize clears the map heatmap.update(); // adds the buffered points heatmap.display(); // adds the buffered points raf(update); } raf(update); //getFeatures() getFeatures() map.on('zoom-end', function (e) { getFeatures() }); map.on('zoom-start', function (e) { heatmap.clear(); }); map.on('pan-start', function (e) { heatmap.clear(); }); map.on('pan-end', getFeatures); map.on('dragstart', function (e) { heatmap.clear(); }); map.on('dragend', getFeatures); map.on('mousewheel', function (e) { heatmap.clear(); getFeatures() }) function setdata(features) { var i, da, m, dataPoint, heatmapdata, attributes, screenGeometry heatmapdata = [] da = [] for (i = 0; i < features.length; i++) { da.push(); } m = features[features.length - 1].attributes[valueField ] for (i = 0; i < features.length; i++) { var geo = features[i].geometry.normalize(); dataPoint = new Point(geo.x, geo.y, map.spatialReference); attributes = features[i].attributes; var va = attributes[valueField ] //var normalizedExtent = map.extent._normalize(); screenGeometry = map.toScreen(dataPoint); //screenUtils.toScreenGeometry(normalizedExtent, map.width, map.height, dataPoint); if (attributes && attributes.hasOwnProperty(valueField )) { heatmapdata.push({ x: screenGeometry.x, y: screenGeometry.y, size: 30, intensity: va / m }); } else { heatmapdata.push({ x: screenGeometry.x, y: screenGeometry.y, size: 30, intensity: 0 }); } } heatmap.clear(); heatmap.addPoints(heatmapdata); } }); </script> </html>
小貼士:開啓大數據量繪製須要修改webgl-heatmap.js中的this.maxPointCount值(默認是10240),這樣就能夠隨心所欲了。。。git