基于百度地图的数据可视化,包括大量数据的标绘以及热力图的插入
在日常的开发工作中经常可以遇到地图的相关应用,但是大部分的问题我们都可以通过查询相关的地图api接口就可以得到我们想要的结果,无非会在数据处理以及一些基础的函数的问题,但是如果想在地图上实现一些大量数据的标绘制的时候,问题就出现了。经过测试,百度地图(本文中的地图均指百度地图)在实现基于图片的标绘物品的时候,在200个点属于完美性能(PC,移动端未测试)一旦超过2000个标绘物的时候就会出现明显的卡顿,而超过5000的时候则会出现浏览器直接奔溃的情况。经过多方查找且改进,我找到了基于百度地图canvas的额外图层绘制。经过测试,可以实现10000个点基本完美性能。但是再往上我也不太会了,因此希望诸位大佬给出改进意见。
html
<!DOCTYPE html>
<html>
<head>
<title>baidu map pointline</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="./style.css">
<!-- <link rel="stylesheet" type="text/css" href="../../css/map.css" />
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../map_load.js"></script>
<script type="text/javascript" src="../../map.js"></script>
<script src="../../layer/layer.js" type="text/javascript" charset="utf-8"></script> -->
<script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=nuWah68S1WieW2AEwiT8T3Ro&s=1"></script>
<!-- <script type="text/javascript" src="mapstyle/gray.js"></script> -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script src="./data/point.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="map"></div>
<img src="images/red.png" >
<script type="text/javascript" src="./baidu-map-pointLine.js"></script>
<script type="text/javascript">
var map = new BMap.Map('map', {
minZoom: 5
});
map.centerAndZoom(new BMap.Point(112.954699, 27.936651192), 7);
map.enableScrollWheelZoom(true);
var arr=[]
for(var i=0;i<10000;i++){
var obj={
lng:Math.random()*10+100,
lat:Math.random()*10+30,
message:"标绘物"+i
}
arr.push(obj)
}
var pointLine = new PointLine(map, {
//数据源
data: arr,
//事件
methods: {
click: function (e, msg) {
console.log('你当前点击的是' + msg);
},
// mousemove: function (e, name) {
// console.log('你当前点击的是' + name);
// }
}
});
</script>
</body>
js
在这儿需要感谢一位大哥完成了代码里最麻烦的部分,就是百度地图和canvas的经纬度坐标和canvas的屏幕坐标转换的部分,而他也完成了多条地铁线路的地图标会,而我在他的基础上加入了海量图片的标绘以及热力图的嵌入+点聚合的优化方法,这是那哥们的github地址:https://github.com/chengquan223
(function(global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.PointLine = factory());
}(this, (function() {
'use strict';
/**
* @author https://github.com/chengquan223
* @Date 2017-02-27
* */
function CanvasLayer(options) {
this.options = options || {};
this.paneName = this.options.paneName || 'labelPane';
this.zIndex = this.options.zIndex || 0;
this._map = options.map;
this._lastDrawTime = null;
this.show();
}
CanvasLayer.prototype = new BMap.Overlay();
CanvasLayer.prototype.initialize = function(map) {
this._map = map;
var canvas = this.canvas = document.createElement('canvas');
var ctx = this.ctx = this.canvas.getContext('2d');
canvas.style.cssText = 'position:absolute;' + 'left:0;' + 'top:0;' + 'z-index:' + this.zIndex + ';';
this.adjustSize();
this.adjustRatio(ctx);
map.getPanes()[this.paneName].appendChild(canvas);
var that = this;
map.addEventListener('resize', function() {
that.adjustSize();
that._draw();
});
return this.canvas;
};
CanvasLayer.prototype.adjustSize = function() {
var size = this._map.getSize();
var canvas = this.canvas;
canvas.width = size.width;
canvas.height = size.height;
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
};
CanvasLayer.prototype.adjustRatio = function(ctx) {
var backingStore = ctx.backingStorePixelRatio || ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
var pixelRatio = (window.devicePixelRatio || 1) / backingStore;
var canvasWidth = ctx.canvas.width;
var canvasHeight = ctx.canvas.height;
ctx.canvas.width = canvasWidth * pixelRatio;
ctx.canvas.height = canvasHeight * pixelRatio;
ctx.canvas.style.width = canvasWidth + 'px';
ctx.canvas.style.height = canvasHeight + 'px';
// console.log(ctx.canvas.height, canvasHeight);
ctx.scale(pixelRatio, pixelRatio);
};
CanvasLayer.prototype.draw = function() {
var self = this;
var args = arguments;
clearTimeout(self.timeoutID);
self.timeoutID = setTimeout(function() {
self._draw();
}, 15);
};
CanvasLayer.prototype._draw = function() {
var map = this._map;
var size = map.getSize();
var center = map.getCenter();
if (center) {
var pixel = map.pointToOverlayPixel(center);
this.canvas.style.left = pixel.x - size.width / 2 + 'px';
this.canvas.style.top = pixel.y - size.height / 2 + 'px';
this.dispatchEvent('draw');
this.options.update && this.options.update.call(this);
}
};
CanvasLayer.prototype.getContainer = function() {
return this.canvas;
};
CanvasLayer.prototype.show = function() {
if (!this.canvas) {
this._map.addOverlay(this);
}
this.canvas.style.display = 'block';
};
CanvasLayer.prototype.hide = function() {
this.canvas.style.display = 'none';
//this._map.removeOverlay(this);
};
CanvasLayer.prototype.setZIndex = function(zIndex) {
this.canvas.style.zIndex = zIndex;
};
CanvasLayer.prototype.getZIndex = function() {
return this.zIndex;
};
var tool = {
merge: function merge(settings, defaults) {
Object.keys(settings).forEach(function(key) {
defaults[key] = settings[key];
});
},
//计算两点间距离
getDistance: function getDistance(p1, p2) {
return Math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]));
},
//判断点是否在线段上
containStroke: function containStroke(x0, y0, x1, y1, lineWidth, x, y) {
if (lineWidth === 0) {
return false;
}
var _l = lineWidth;
var _a = 0;
var _b = x0;
// Quick reject
if (y > y0 + _l && y > y1 + _l || y < y0 - _l && y < y1 - _l || x > x0 + _l && x > x1 + _l || x < x0 - _l && x <
x1 - _l) {
return false;
}
if (x0 !== x1) {
_a = (y0 - y1) / (x0 - x1);
_b = (x0 * y1 - x1 * y0) / (x0 - x1);
} else {
return Math.abs(x - x0) <= _l / 2;
}
var tmp = _a * x - y + _b;
var _s = tmp * tmp / (_a * _a + 1);
return _s <= _l / 2 * _l / 2;
},
// 判断点击图片的位置
containStrokeImage: function(clickPoint, markerPoint) {
var markerWidth = 32,
markerHeight = 32,
self = this;
var marker = self.isimageContent(markerPoint);
var arr = [];
if (marker.leftTopX <= clickPoint.x && clickPoint.x <= marker.rightBottomX && clickPoint.y < marker.rightBottomY &&
marker.leftTopY < clickPoint.y) {
return true;
} else {
return false;
}
// ctx.clearRech(0,0,ctx.width,ctx.height);
/**
* 1.点击的位置
* 2.计算出四个边角的位置
* 3. 筛选出是否在四边之内
*
*
*
*
* **/
},
isimageContent: function(markerPoint) {
return {
leftTopX: markerPoint.x,
leftTopY: markerPoint.y,
rightBottomX: markerPoint.x + 32,
rightBottomY: markerPoint.y + 32
}
},
//点击的区域重合的时候
selectZjFunc: function(markerarr, e) {
var thatSelectjl = 0;
var thatIndex = 0
var self = this;
markerarr.forEach((item, index) => {
var markerpix = item.marker.pixel;
var thisjl = self.selectjsFunc(markerpix, e)
if (thisjl > thatSelectjl) {
thatSelectjl = thisjl
thatIndex = index
}
})
return thatIndex;
},
// 计算点击的位置距离部署点位的距离
selectjsFunc: function(marker, e) {
return Math.sqrt((marker.x - e.x) * (marker.x - e.x) + (e.y - marker.y) * (e.y - marker.y))
},
//点聚合算法的实现1. 实现拆分屏幕
// 2. 数据判断
// 3. 实现绘制(仅限热力图,如果有后续需要做出标绘的点聚合,也可以)
cfpmFunc: function(width, height, cfWidth) {
var self = this;
//横向
var widthLength = parseInt(width / cfWidth) + 1;
var widthOver = width % cfWidth
var widthHeight = parseInt(height / cfWidth) + 1;
var heightOver = height % cfWidth
var pointarr = [];
for (var i = 1; i <= widthLength; i++) {
for (var j = 1; j <= widthHeight; j++) {
var obj = {}
obj.leftTopX = (i - 1) * cfWidth;
obj.leftTopY = (j - 1) * cfWidth;
obj.rightBottomX = (i - 1) * cfWidth;
obj.rightBottomY = (j - 1) * cfWidth;
if (i == widthLength) {
if (j == widthHeight) {
obj.rightBottomX = (i - 1) * cfWidth + widthOver;
obj.rightBottomY = (j - 1) * cfWidth + heightOver;
} else {
obj.rightBottomX = (i - 1) * cfWidth + widthOver;
obj.rightBottomY = j * cfWidth;
}
} else {
obj.rightBottomX = i * cfWidth;
obj.rightBottomY = (j - 1) * cfWidth + heightOver;
}
pointarr.push(obj)
}
}
return pointarr;
},
// 当前方框内是否存在数据
jhFunc: function(clickPoint, marker, width, height) {
var self = this;
if (marker.leftTopX <= clickPoint.x && clickPoint.x <= marker.rightBottomX && clickPoint.y < marker.rightBottomY &&
marker.leftTopY < clickPoint.y) {
return true;
} else {
return false;
}
},
};
//所有图片存储的位置
var base64Image = {
tzred:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDozMmMyNjgwOS1mOTMwLTQyYTEtYjBjZi1kNjYyNjY3MjFhYzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDREODQ2QTAxMTgyMTFFNDk0QTg5MjZDRjBEOTA3RDkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDREODQ2OUYxMTgyMTFFNDk0QTg5MjZDRjBEOTA3RDkiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NjY2N2Q2MDAtM2RkMS00ZWZhLTgyNTktZTA0MWUyYTkwOTZjIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjMyYzI2ODA5LWY5MzAtNDJhMS1iMGNmLWQ2NjI2NjcyMWFjMSIvPiA8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"
}
var PointLine = function PointLine(map, userOptions) {
var self = this;
self.map = map;
self.lines = [];
self.pixelList = [];
//默认参数
//需要的数据
/**
* 经度,纬度,标题头 添加的点击事件
*
* **/
var options = {
};
//全局变量
var baseLayer = null,
//获取当前所需要的canvas的宽高
width = map.getSize().width,
height = map.getSize().height;
function Line(opts) {
// this.message = opts.message;//装备信息
// this.path = opts.path;//装备的位置
this.tzArr = opts.tzArr;
}
//绘制军标
Line.prototype.draw = function() {
var self = this;
var ctx = self.ctx;
var img = new Image();
//等待处理
// img.setAttribute("crossOrigin","")
img.onload = function() {
for (let i = 0; i < self.pixelList.length; i++) {
const item = self.pixelList[i]
ctx.drawImage(img, item.pixel.x, item.pixel.y, 32, 32);
}
// 存储到这个的全局变量
}
img.src = base64Image.tzred;
}
//热力图绘制
Line.prototype.drawHot = function() {
var self = this;
var ctx = self.ctx;
var radius = 50;
for (let i = 0; i < self.jhArr.length; i++) {
const item = self.jhArr[i]
if(!item){
continue
}
ctx.beginPath()
ctx.arc(item.pixel.x, item.pixel.y, radius, 0, 2 * Math.PI);
ctx.closePath()
let radialGradient = ctx.createRadialGradient(item.pixel.x, item.pixel.y, 0, item.pixel.x, item.pixel.y,
radius);
radialGradient.addColorStop(0.0, "rgba(0,0,0,1)")
radialGradient.addColorStop(1.0, "rgba(0,0,0,0)")
ctx.fillStyle = radialGradient;
//权重对比算法,替换算法
// let globalAlpha = (value - min) / (max - min);
// ctx.globalAlpha = Math.max(Math.min(globalAlpha, 1), 0)
ctx.fill()
}
//自定义调色板
var paientCanvas = document.createElement('canvas')
var paientctx = paientCanvas.getContext('2d');
let gradentConfig = {
'0.2': 'rgba(0,0,255,0.2)',
'0.3': 'rgba(43,111,231,0.3)',
'0.4': 'rgba(2,192,241,0.4)',
'0.6': 'rgba(44,222,148,0.6)',
'0.8': 'rgba(254,237,83,0.8)',
'0.9': 'rgba(255,118,55,0.9)',
'1.0': 'rgba(255,64,28,1)',
}
paientCanvas.width = 256;
paientCanvas.height = 1;
var gradient = paientctx.createLinearGradient(0, 0, 256, 1)
for (var key in gradentConfig) {
gradient.addColorStop(key, gradentConfig[key])
}
paientctx.fillStyle = gradient;
paientctx.fillRect(0, 0, 256, 1)
//获取到需要映射的imagedata
var imgdata = paientctx.getImageData(0, 0, 256, 1).data;
var img = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height)
var ctxImagedata = img.data
for (var i = 3; i < ctxImagedata.length; i += 4) {
var alpha = ctxImagedata[i]
var offset = alpha * 4;
if (!offset) {
continue
}
ctxImagedata[i - 3] = imgdata[offset]
ctxImagedata[i - 2] = imgdata[offset + 1]
ctxImagedata[i - 1] = imgdata[offset + 2]
}
//卡顿,需要点聚合的算法进行相应处理
ctx.putImageData(img, 0, 0, 0, 0, ctx.canvas.width, ctx.canvas.height)
}
//底层canvas添加
var brush = function brush() {
// 创建一个新的canvas
var baseCtx = baseLayer.canvas.getContext('2d');
if (!baseCtx) {
return;
}
//添加军标
addLine();
baseCtx.clearRect(0, 0, width, height);
//获取当前地图层级
var zoom = map.getZoom();
self.lines.pixelList = [];
self.lines.tzArr.forEach((item) => {
self.lines.pixelList.push({
message: item.message,
pixel: map.pointToPixel(item.H)
})
})
self.lines.ctx = baseCtx
if (zoom > 12) {
self.lines.draw();
} else {
//将屏幕分为50*50的网格,并且确定左上角和右下角的点的位置
var pmWg = tool.cfpmFunc(baseCtx.canvas.width, baseCtx.canvas.height, 50)
//将网格内存在的点做进一步的筛选
// console.log(pmWg)
var jhArr = []
self.lines.tzArr.forEach((item) => {
var thisPixel = map.pointToPixel(item.H);
//筛选掉超出屏幕边界的点
if (thisPixel.x < 0 || thisPixel.y < 0 || thisPixel.x > baseCtx.canvas.width || thisPixel.y > baseCtx.canvas
.height) {
return
}
//进一步筛选点
for (let k in pmWg) {
var itemWg = pmWg[k]
if (tool.jhFunc(thisPixel, itemWg, 50, 50)) {
if (jhArr[k]) {
continue;
} else {
jhArr[k] = {
message: item.message,
pixel: thisPixel
}
}
}
}
})
self.lines.jhArr = jhArr;
self.lines.drawHot();
}
};
var addLine = function addLine() {
// if (self.lines!=""&&!self.lines) return;
var dataset = options.data;
dataset.forEach((item, index) => {
item.H = new BMap.Point(item.lng, item.lat)
})
var line = new Line({
tzArr: dataset
})
self.lines = line;
};
self.init(userOptions, options);
baseLayer = new CanvasLayer({
map: map,
update: brush
});
this.clickEvent = this.clickEvent.bind(this);
this.bindEvent();
};
PointLine.prototype.init = function(settings, defaults) {
//合并参数
tool.merge(settings, defaults);
this.options = defaults;
};
PointLine.prototype.bindEvent = function(e) {
var map = this.map;
if (this.options.methods) {
if (this.options.methods.click) {
map.setDefaultCursor("default");
map.addEventListener('click', this.clickEvent);
}
if (this.options.methods.mousemove) {
map.setDefaultCursor("default");
map.addEventListener('mousemove', this.moveEvent);
}
}
};
PointLine.prototype.clickEvent = function(e) {
var self = this,
lines = self.lines.pixelList;
var curPt = e.pixel;
var arr = []
if (lines.length > 0) {
lines.forEach(function(marker, i) {
var markerPixel = marker.pixel;
var isOnMarker = tool.containStrokeImage(curPt, markerPixel)
if (isOnMarker) {
arr.push({
index: i,
marker: marker
})
}
});
}
if (arr.length > 1) {
var lastGod = tool.selectZjFunc(arr, curPt)
self.options.methods.click(e, arr[lastGod].marker.message);
return;
} else if (arr.length == 1) {
var lastGod = arr[0].marker.message
self.options.methods.click(e, arr[0].marker.message);
return;
} else {
return;
}
};
return PointLine;
})));
实现的结果如下图所示:
下面是我的源码地址,可以直接运行,具体的点聚合算法以及屏幕切割算法、点击重合标绘物的判断方法等等我都有详细的注释,目前10万左右的数据会在最小层级上卡顿,还有就是图片需要用到base64的方法,因为做测试老是出现图片跨域的方法,我也懒得专门弄一个服务端的环境了。具体的解决方法自行百度。。。
github地址
本文地址:https://blog.csdn.net/wusu0wei/article/details/112547540
上一篇: HTML5 知识点总结(六)
下一篇: HTML5基础知识概述