概述

在ol4里面可以通过Vector Layer的方式进行点的渲染,但是当点的个数比较多的时候,会存在明显的操作不流畅。本文讲述如何利用ImageCanvas接口,对大量的点进行展示,并添加相应的交互。

实现效果

实现分析

1.效率差异如何得来?

ol的最终渲染也是通过canvas的方式来渲染的,但是为什么效率会差这么多呢?分析原因,是因为:
1)Vector的渲染方式会保留很多交互相关的操作;
2)ImageCanvas的方式其实是将数据渲染到一个新的画布上,再以图片的方式渲染到map的canvas上;

2.交互如何实现

地图上的渲染查看相关的接口实现起来比较简单,这里重点说一下渲染完后如何交互。在实现地图交互的时候,存在两个技术点:
1)如何判断鼠标经过的位置要触发交互的位置?
我们知道每一个点的大小是指的像素值,所以在判断位置的时候调用view的getResolution()接口,实时计算一个半径,通过鼠标当前点+半径可以创建一个圆,在判断落在圆内的点就为交互的点。代码实现如下:

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);}}}
});

2)大量数据的检索如何优化?
针对大量数据的检索,在处理的时候做了前端的分区缓存,在通过经纬度去查找对应的分区位置,再去找里面的数据。实现代码如下:

  // 1、核心函数,通过经纬度计算分区位置
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;
}// 2、缓存数据
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);}
}

实现源码

<!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
联系方式

类型 内容
qq 1004740957
公众号 lzugis15
e-mail niujp08@qq.com
webgis群 452117357
Android群 337469080
GIS数据可视化群 458292378

ol4通过ImageCanvas实现大量点的展示以及交互的实现相关推荐

  1. springboot_Vue花卉展示与交互平台网站

    花卉展示与交互平台,本网站是基于WEB采用了BS架构开发,利用当前最流行的vue与mysql数据库相结合的技术,主要实现一个以花会友的交流平台,通过对花的展示来吸引爱花的人的关注,系统主要用于计算机专 ...

  2. 博物馆3d数字化全景展示设计方案

    作为近几年新兴的营销方式,交互式营销能够让消费者对产品从主动感兴趣到互动体验,甚至自主自发传播,达到"在销售中传播,在传播中销售"的目的.进入数字体验经济时代,当3d数字化展示技术 ...

  3. 如何在PPT中嵌入交互式图表?LightningChart助力炫酷展示

    我们在PPT演示文稿中嵌入图表很容易,但嵌入交互式图表似乎就没听说过了,接下来我们就一起来看看通过交互式图表在PPT中展示病人心跳的效果: PPT中展示病人心跳 下方是一个实时地图在PPT中的展现实例 ...

  4. 广交会要求的企业三维展示是什么软件做的?

    129届春季广交会到来,企业参展商们着手准备的广交会要求的企业三维展示是什么软件做的?按照广交会的要求,企业三维展示需要参展商上传搭建好的线上展厅以及三维展品,商迪3D在线提供企业三维制作服务,从3D ...

  5. 「构建企业级推荐系统系列」推荐系统的UI交互与视觉展示

    作者 | gongyouliu 编辑 | auroral-L 推荐系统是一个偏工程应用的领域,要想在商业产品中引入推荐系统,利用推荐系统来帮助用户过滤信息,除了构建精准高效的推荐算法外,还需要设计适合 ...

  6. 向正展厅云平台:推动数字化展示转型的不二之选

    近年来,数字化改革这个名词不止一次的出现在我们的面前.数字化改革包含了五个综合应用,即党政机关整体智治综合应用.数字政府综合应用.数字经济综合应用.数字社会综合应用和数字法治综合应用,包含" ...

  7. 推荐系统的UI交互与视觉展示

    点击上方"大数据与人工智能","星标或置顶公众号" 第一时间获取好内容 作者丨gongyouliu 编辑丨P新 这是作者的第27篇文章,约1.2w字,阅读需60 ...

  8. 如何制作网页和电商官网的3D产品展示?

    电商网站和各个电子产品官网看到的3D产品展示,通常是结合3D建模软件制作的. 以下是创建 3D 产品展示所涉及的一些步骤: 模型创建:使用3ds max.Blender或Maya 等 3D 建模软件创 ...

  9. 地图API总结与比较(GIS)

    1.GIS地图库:OpenLayer,LeafLet,arcgis api等都属于企业级地图应用开发库,彼此之间大同小异.稍微的差异是arcgis api需要arcserver提供服务,离开了serv ...

最新文章

  1. 【文本分类】Attention Is All You Need
  2. 通过自定义ISAPI Filter来禁止敏感文件的访问
  3. html5-6 Frame框架窗口类型
  4. DOM编程艺术12章
  5. python去空格的函数_Python中用于去除空格的三个函数的使用小结
  6. 最小生成树(模板 prim)
  7. C++ 动态联编实现原理分析
  8. linux下order by 报出ORDER BY clause is not in SELECT list
  9. html表格基础及案例示图代码。
  10. PS案例教程:photoshop路径运算和路径组合操作
  11. Roslyn入门(1):一个简单修改C#代码的例子
  12. 明净素雅-会议礼品送什么
  13. ubuntu电源管理
  14. 关于人生的15句话——特别现实的讽刺性句子
  15. 搭档之家|紧跟信息消费大发展时代步伐
  16. Druid java.sql.SQLException: 违反协议 / Oracle连接报错生违反协议
  17. 【转】BCWS、BCWP、ACWP的理解
  18. “听觉”营销价值凸显,喜马拉雅迎来新局点
  19. 关于PhotoShop中保存CMYK格式TIFF文件在GDI+错误地显示颜色的问题解决方法
  20. 关于macbook鼠标不流畅问题

热门文章

  1. Oracle中的dual
  2. mysql好评中评统计_scrapy爬取京东笔记本及评论信息存入MySQL数据库
  3. Chrome Custom Tabs最佳实践
  4. MQTT——EMQX学习笔记01——EMQX安装使用
  5. 利用 ARCHPR 暴力破解 压缩包解压密码
  6. 前端工程筹建NodeJs+gulp+bower
  7. python基于svm实现指数预测_基于SVM的股票预测 Python实现 附Github
  8. 【笔记】COA课内实验-MMX指令集
  9. 关于我unity创建2d横版游戏的这件事1
  10. 类的设计---麻球与油果