ol4通过ImageCanvas实现大量点的展示以及交互的实现
概述
在ol4里面可以通過Vector Layer的方式進行點的渲染,但是當點的個數比較多的時候,會存在明顯的操作不流暢。本文講述如何利用ImageCanvas接口,對大量的點進行展示,并添加相應的交互。
實現效果
實現分析
1.效率差異如何得來?
ol的最終渲染也是通過canvas的方式來渲染的,但是為什么效率會差這么多呢?分析原因,是因為:
 1)Vector的渲染方式會保留很多交互相關的操作;
 2)ImageCanvas的方式其實是將數據渲染到一個新的畫布上,再以圖片的方式渲染到map的canvas上;
2.交互如何實現
地圖上的渲染查看相關的接口實現起來比較簡單,這里重點說一下渲染完后如何交互。在實現地圖交互的時候,存在兩個技術點:
 1)如何判斷鼠標經過的位置要觸發交互的位置?
 我們知道每一個點的大小是指的像素值,所以在判斷位置的時候調用view的getResolution()接口,實時計算一個半徑,通過鼠標當前點+半徑可以創建一個圓,在判斷落在圓內的點就為交互的點。代碼實現如下:
2)大量數據的檢索如何優化?
 針對大量數據的檢索,在處理的時候做了前端的分區緩存,在通過經緯度去查找對應的分區位置,再去找里面的數據。實現代碼如下:
實現源碼
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css"><link rel="stylesheet" href="css/demo.css" type="text/css"> </head> <body> <div id="map"></div> <div id="popup"></div> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script> <script src="js/demo.js"></script> <script>var vec_w = getWmsLayer("light");var data = [];var chinaB = [60, 0, 140, 55];var deltLon = 8,deltLat = 5.5;var numLon = (chinaB[2] - chinaB[0]) / deltLon,numLat = (chinaB[3] - chinaB[1]) / deltLat;var dataCache = [];// 數據從左下角開始for(var j =0;j<numLat;j++) {var maxLat = chinaB[1] + (j+1)*deltLat,minLat = chinaB[1] + j*deltLat;for(var i =0;i<numLon;i++) {var maxLon = chinaB[0] + (i+1)*numLon,minLon = chinaB[0] + i*numLon;var dCache = {xmin: minLon,xmax: maxLon,ymin: minLat,yMax: maxLat,data: []};dataCache.push(dCache);}}var r = 3;var map = new ol.Map({controls: ol.control.defaults({attribution: false}),target: 'map',layers: [vec_w],view: new ol.View({center: ol.proj.fromLonLat([98.633, 31.607]),zoom:4,minZoom:0,maxZoom:18})});var popup = new ol.Overlay({element: document.getElementById('popup'),position: null,positioning: 'center-left',offset: [16, 0]});map.addOverlay(popup);var imageLayer = new ol.layer.Image({source: null,opacity: 0.85});map.addLayer(imageLayer);map.on('click', function (e) {var coord = e.coordinate;var res = map.getView().getResolution();var _radius = res * r;var _circle = new ol.geom.Circle(coord, _radius);var lonlat = ol.proj.toLonLat(coord);var index = getLonLatIndex(lonlat[0], lonlat[1]);if(index !== -1) {var data = dataCache[index].data;for (var i = 0; i < data.length; i++) {var d = data[i];var _coord = ol.proj.fromLonLat([d.lon, d.lat]);if (_circle.intersectsCoordinate(_coord)) {console.log(d);break;}}}});map.on('pointermove', function (e) {var coord = e.coordinate;var res = map.getView().getResolution();var _radius = res * r;var _circle = new ol.geom.Circle(coord, _radius);var lonlat = ol.proj.toLonLat(coord);var index = getLonLatIndex(lonlat[0], lonlat[1]);if(index !== -1) {var data = dataCache[index].data;for (var i = 0; i < data.length; i++) {var d = data[i];var _coord = ol.proj.fromLonLat([d.lon, d.lat]);if (_circle.intersectsCoordinate(_coord)) {map.getTargetElement().style.cursor = 'pointer';document.getElementById('popup').innerText = d.n;popup.setPosition(_coord);break;} else {map.getTargetElement().style.cursor = 'default';popup.setPosition(null);}}}});function canvasFunction(extent, res, pixelRatio, size) {var mapSize = map.getSize();var zoom = map.getView().getZoom();r = zoom * 0.6;r = r<3 ? 3: r;r = r > 10 ? 10: r;var xOff = (size[0] - mapSize[0]) / 2,yOff = (size[1] - mapSize[1]) / 2;var canvas = document.createElement('canvas');canvas.setAttribute('width', size[0]);canvas.setAttribute('height', size[1]);var ctx = canvas.getContext('2d');for(var i = 0;i<data.length;i++) {var d = data[i];ctx.fillStyle = getValueColor(d["pre_1h"]);ctx.strokeStyle = 'rgba(0,0,0,0.2)';ctx.strokeWidth = 1;ctx.beginPath();var coord = ol.proj.fromLonLat([d["lon"], d["lat"]]);var pixel = map.getPixelFromCoordinate(coord);// x, y, r, start, endctx.arc(pixel[0] + xOff, pixel[1] + yOff, r, 0, 2*Math.PI);ctx.fill();ctx.stroke();}return canvas;}function getLonLatIndex(lon, lat) {var index = -1;// 在邊界內if(ol.extent.containsCoordinate(chinaB, [lon, lat])) {var idxX = (lon - chinaB[0]) / deltLon,idxY = (lat - chinaB[1]) / deltLat;index = Math.floor(idxY) * numLon + Math.floor(idxX);}return index;}$.get("datas/data.json", (res) => {data = res.data;// data = getRandomData();var source = new ol.source.ImageCanvas({canvasFunction: canvasFunction});imageLayer.setSource(source);for(var i = 0;i<data.length;i++) {var d = data[i];var idx = getLonLatIndex(d.lon, d.lat);if(idx !== -1) {dataCache[idx].data.push(d);}}}) </script> </body> </html>技術博客
 CSDN:http://blog.csdn.NET/gisshixisheng
 在線教程
 https://edu.csdn.net/course/detail/799
 https://edu.csdn.net/course/detail/7471
 聯系方式
| 1004740957 | |
| 公眾號 | lzugis15 | 
| niujp08@qq.com | |
| webgis群 | 452117357 | 
| Android群 | 337469080 | 
| GIS數據可視化群 | 458292378 | 
總結
以上是生活随笔為你收集整理的ol4通过ImageCanvas实现大量点的展示以及交互的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: JSD-2204-续Docker命令-布
- 下一篇: R语言----逻辑回归各统计量解读
