百度地图中。上万级别数据打点渲染图标的方式
1. 本体js文件内容
export const getRandom = () => { const crypto = window.crypto || window.msCrypto; const array = new Uint32Array(1); return crypto.getRandomValues(array)[0]; }; // 缩放级别 const getZoom = function(){ // 获取当前屏幕的缩放比例 let zoom = document.body.style.zoom * 1; if( isNaN(zoom) || zoom === 0 ){ zoom = 1; } return [ zoom, zoom ]; } export class MapCanvasLayer { // 数据集 datas = []; // 地图对象 _map = null; // 显示的canvas canvas = null; id = parseInt(getRandom() * 1000, 10); events = []; // 缩放比例 zoom = [1, 1]; // 过滤数据 renderFilter = (data) => data; constructor() { this.zoom = getZoom(); // 创建矩阵驱动器 this.matrixDrive = new MatrixDrive(); // 创建worker支线 this.worker = { postMessage: () => { }, terminate: () => { } }; this.worker = new Worker('/map/mapCanvasLayerWorker.js'); this.worker.onmessage = (event) => { // 对其时间轴 if( event.data.t !== this.renderTime || window.noRender === false ){ return; } this.renderMap(event) } } // 获取当前地图的可视范围 getBounds() { if (!this.centerDiff) return; const map = this._map; // 右上 const ys = this.transformXYByYuan(map.getBounds().ne); // 这个是左下 const zx = this.transformXYByYuan(map.getBounds().sw); const bounds = [ys, zx]; return bounds; } // 坐标转换 转换为原点坐标系的 transformXYByYuan({ lng, lat }) { const map = this._map; // 获取原点的位置 const p = map.pointToPixel(); // 求目前缩放比 const rate = this.getLayerRate(); // 求当前坐标的距离 const np = map.pointToPixel({ lng: lng, lat: lat }); // 计算后的x const x1 = np.x - p.x; // 计算后的y const y1 = np.y - p.y; return [x1 / rate[0], y1 / rate[1]]; } getLayerRate() { const newcenterdiff = [this._map.pointToPixel(this.center), this._map.pointToPixel()]; const centerdiff = this.centerDiff; const xrate = Math.abs(newcenterdiff[0].x - newcenterdiff[1].x) / centerdiff[0]; const yrate = Math.abs(newcenterdiff[0].y - newcenterdiff[1].y) / centerdiff[1]; return [xrate, yrate]; } renderMatrixDrive() { // 获取当前可视范围 const bound = this.getBounds(); console.log(bound); const datas = this.matrixDrive.render(bound); // const cw = this.canvas.width; // const ch = this.canvas.width; // 获取当前canvas的像素组 const canvasData = new ImageData(this.canvas.width, this.canvas.height); let it, images, picData, x, y, w, h; let pstart, pend, d, dindex; // 然后将像素数据解析到的点加载到地图上 for (var i in datas) { it = datas[i]; images = this.getImages(it.data); if (!images) continue; // 获取像素数据 picData = new ImageData(images.imageData.imageData.width, images.imageData.imageData.height); // images.imageData.imageData; // picData.data.fill(255); // 获取当前数据的像素坐标 // const x = parseInt(canvasData.width * it.pos[0] / (bound[1][0] + bound[0][0])); x = parseInt(canvasData.width * (it.pos[0] - bound[1][0]) / (bound[0][0] - bound[1][0])); // const y = parseInt(canvasData.height * it.pos[1] / (bound[1][1] + bound[0][1])); y = parseInt(canvasData.height * (bound[1][1] - it.pos[1]) / (bound[1][1] - bound[0][1])); // 获取每一行的w w = picData.width; // console.time("test") // for (h = 0; h < picData.height; h++) { // pstart = (0 + h) * w * 4; // pend = w * 4 + pstart; // // canvasData.data.set( // // picData.data.slice(pstart, pend), // // (x + (y + h) * canvasData.width) * 4, // // ); // d = picData.data.slice(pstart, pend); // dindex = (x + (y + h) * canvasData.width) * 4; // for (var i = 0; i < d.length; i++) { // // canvasData.data[dindex + i] = d[i]; // } // // canvasData.data // } // console.timeEnd("test") this.canvas2d.drawImage(images, x, y, it.data.iconConfig?.width || 24, it.data.iconConfig?.height || 30); } // this.canvas2d.putImageData(canvasData, 0, 0); } setFilter(fn) { this.renderFilter = fn; this.handleFilterData(); } handleFilterData() { this.filterData = this.renderFilter(this.datas); } getDatas() { return this.filterData || []; } setMap(map) { this._map = map; // 传入地图宽高 this.matrixDrive.setOff([map.width, map.height]); this.createCanvas(); // 绑定时间 this.mapUpdate = (e) => { // 移动canvas // this.renderCanvasPosition(e); // this.clearCanvas(); this.renderIcon(); }; this._map.addEventListener('update', this.mapUpdate); this.mapClick = (e) => { // const x = e.layerX; // const y = e.layerY; this.clickMap(e); }; this._map.addEventListener('click', this.mapClick); this.mapMousemove = (e) => { const x = e.layerX; const y = e.layerY; this.moveMap(x, y, e); }; // 绑定鼠标浮动事件 this._map.addEventListener('mousemove', this.mapMousemove); this.mapMouseout = (e) => { clearTimeout(this.moveMapKey); if (this.mouseObject) { this.emit('mouseout', this.mouseObject, e); } }; // 绑定鼠标浮动事件 this._map.addEventListener('mouseout', this.mapMouseout); this.mapMoving = (event) => { let xy = [0, 0]; if (this.offsetXY) { xy = this.offsetXY; } // 这个需要记录下来 这里的offsetX很奇怪 每一次新的拖拉都会导致叠加 要减去上一次最后的值 this.xyArray = [event.currentTarget.offsetX, event.currentTarget.offsetY]; // console.log("mapMoving", this.xyArray, event); this.renderCanvasPosition([event.currentTarget.offsetX - xy[0], event.currentTarget.offsetY - xy[1]]); }; this._map.addEventListener('moving', this.mapMoving); this.mapDragstart = (event) => { this.offRenderMap(); if (!this.offsetXY) { // 这个需要记录下来 这里的offsetX很奇怪 每一次新的拖拉都会导致叠加 要减去上一次最后的值 this.offsetXY = [event.currentTarget.offsetX, event.currentTarget.offsetY]; } // console.log("movestart"); }; this._map.addEventListener('movestart', this.mapDragstart); this.mapDragend = (event) => { // 这个需要记录下来 这里的offsetX很奇怪 每一次新的拖拉都会导致叠加 要减去上一次最后的值 // this.offsetXY = null; this.onRenderMap(); // console.log("moveend"); }; this._map.addEventListener('moveend', this.mapDragend); this.mapZoomstart = (event) => { this.offRenderMap(); this.clearCanvas(); }; this._map.addEventListener('zoomstart', this.mapZoomstart); this.mapZoomend = (event) => { this.onRenderMap() }; this._map.addEventListener('zoomend', this.mapZoomend); } // 开启渲染 onRenderMap (){ this.isRenderMap = true; } // 关闭渲染 offRenderMap (){ this.isRenderMap = false; } renderMap (event){ console.log("workerTime:", event.data.t); if( this.isRenderMap === true ){ this.clearCanvasPosition(); // this.clearCanvas(); this.canvas2d.putImageData(event.data.d, 0, 0); } } // 清除掉事件 clearEvent() { this._map.removeEventListener('update', this.mapUpdate); this._map.removeEventListener('click', this.mapClick); this._map.removeEventListener('mousemove', this.mapMousemove); this._map.removeEventListener('mouseout', this.mapMouseout); this._map.removeEventListener('moving', this.mapMoving); this._map.removeEventListener('movestart', this.mapDragstart); this._map.removeEventListener('moveend', this.mapDragend); this._map.removeEventListener('zoomstart', this.mapZoomstart); this._map.removeEventListener('zoomend', this.mapZoomend); } clearCanvasPosition() { this.offsetXY = null; this.canvas.style.transform = ''; } renderCanvasPosition(event) { // // 赋值canvas位置 const { canvas } = this; const textCss = `translate(${event[0]}px, ${event[1]}px)`; canvas.style.transform = `${textCss}`; // // 赋值canvas位置 // const { canvas } = this; // let textCss = `translate(${x}px, ${y}px)`; // if (this.mapBounds) { // const ws = this._map.pointToPixel(this.mapBounds.sw); // const ne = this._map.pointToPixel(this.mapBounds.ne); // const bounds = this._map.getBounds(); // const ws_ = this._map.pointToPixel(bounds.sw); // const ne_ = this._map.pointToPixel(bounds.ne); // const diffx = (ws.x - ne.x) / (ws_.x - ne_.x); // const diffy = (ws.y - ne.y) / (ws_.y - ne_.y); // textCss += `scale(${diffx},${diffy})`; // } // canvas.style.transform = `${textCss}`; } setData(datas) { // datas = datas.slice(0, 1); // 记录原点到中心点的距离 this.center = map.getCenter(); const cp = map.pointToPixel(this.center); const yp = map.pointToPixel(); this.centerDiff = [Math.abs(cp.x - yp.x), Math.abs(cp.y - yp.y)]; this.datas = datas; this.handleFilterData(); const center = this._map.getCenter(); // 获取原点距离 const p = this._map.pointToPixel(); p.y *= -1; // 求中心点 const c = this._map.pointToPixel(center); c.y *= -1; const cx = c.x - p.x; const cy = c.y - p.y; this.matrixDrive.setMatrix( datas.map((data) => { // const points = this._map.pointToPixel(new window.BMapGL.Point(data.x, data.y)); return { // pos: [points.x - p.x, points.y - p.y], pos: this.transformXYByYuan(new window.BMapGL.Point(data.x, data.y)), data }; }), center ); this.renderIcon(); } // 生成一个canvas组件 createCanvas() { this.canvas = document.createElement('canvas'); this.canvas.style.cssText = 'position: absolute; left: 0px; top: 0px;transform-origin: 50% 50%;z-index: 1;'; this.canvas.id = `canvas_${this.id}`; this.canvas.width = this._map.width; this.canvas.height = this._map.height; // 创建一个canvasoff对象 // const canvas = this.canvas.transferControlToOffscreen(); // this.worker.postMessage({ type: "addCanvas", canvas }, [canvas]); this.canvas2d = this.canvas.getContext('2d'); this._map.container.appendChild(this.canvas); return this.canvas; } setImages(images) { this.imagesConfig = {}; this.imagesConfig.getImages = images.getImages; this.imagesConfig.datas = images.datas || []; } getImages(data) { const path = this.imagesConfig.getImages(data); return this.imagesConfig.datas[path]; } // 清楚canvas clearCanvas() { this.canvas2d?.clearRect(0, 0, this.canvas.width, this.canvas.height); } renderIcon() { this.timeRandom = getRandom(); if (this.renderIconKey) { clearTimeout(this.renderIconKey); } this.renderIconKey = setTimeout(() => { this.render(this.timeRandom); }, 200); } // 在worker图片加载 loadImagesWorker(image, id) { this.worker.postMessage({ type: "addImages", data: { imageIndex: image.imageIndex, w: image.imageData.width, h: image.imageData.height, id } }); } loadImages() { return new Promise((resolve) => { const datas = this.getDatas(); // 记录一下需要加载的图片 const promise = new Set(); for (var i = 0; i < datas.length; i++) { const data = datas[i]; // 首先检查一下缓存中是否存在这个图片 const path = this.imagesConfig.getImages(data); const image = this.imagesConfig.datas[path]; if (image === undefined) { if (!promise.has(path)) { // 添加进入等待加载的列表 promise.add(path); // 如果没有缓存的图片 则加载 this.loadImage(path).then((img) => { img.width = 24; img.height = 30; this.imagesConfig.datas[path] = img; img.imageData = new ImageCanvasData(img); this.loadImagesWorker(img.imageData, path); // 将图片解析成像素数据 promise.delete(path); if (promise.size === 0) { resolve(); } }).catch(() => { this.imagesConfig.datas[path] = null; promise.delete(path); setTimeout(() => { if (promise.size === 0 && i === datas.length) { resolve(); } }, 100); }); } } } if (promise.size === 0) { resolve(); } }); } loadImage(path) { return new Promise((resolve, error) => { const img = document.createElement('img'); img.src = path; img.onload = () => { resolve(img); }; img.onerror = () => error(); }); } render(timeRandom) { if (timeRandom !== this.timeRandom) { return; } this.renderTime = new Date() * 1; // this.clearCanvas(); // 渲染之前先加载一下需要的图片 this.loadImages().then(() => { // console.time("matrixRender"); // this.renderMatrixDrive(); // console.timeEnd("matrixRender"); const map = this._map; const datas = this.getDatas(); if( this.canvas.width !== this._map.width ){ this.canvas.width = this._map.width; } if( this.canvas.height !== this._map.height ){ this.canvas.height = this._map.height; } // 解析数据的屏幕坐标和id const workerData = datas.map((data)=> { return { iconkey: this.imagesConfig.getImages(data), // this.getImages(data), p: map.pointToPixel(new window.BMapGL.Point(data.x, data.y)) } }) // this.renderTime = new Date() * 1; this.worker.postMessage({ type: "render", data: workerData, width: this.canvas.width, height: this.canvas.height, time: this.renderTime }); // console.time('mapRender'); // let data = null; // let config = {}; // let w = null; // let h = null; // // 获取当前canvas的像素组 // const canvasData = new ImageData(this.canvas.width, this.canvas.height); // let loadIndex = {}; // // // 将数据转化屏幕坐标 // // const indexData = datas.map((e)=> { // // [map.pointToPixel(new window.BMapGL.Point(e.x, e.y)), this.getImages(e)]; // // }) // for (var i = datas.length - 1; i >= 0; i--) { // data = datas[i]; // const images = this.getImages(data); // if (!images) continue; // const points = this._map.pointToPixel(new window.BMapGL.Point(data.x, data.y)); // const lng = points.x - images.width / 2; // const lat = points.y - images.height / 2; // if (lng > canvasData.width || lng < 0 || lat > canvasData.height || lat < 0) { // continue; // } // // 临时变量由下面的公式分解出来的 // const cwc = this.canvas.width * 4; // const pjt = lng * 4 + lat * cwc; // for (var it of images.imageData.imageIndex) { // // 同行中如果并行的 // // const index = (points.x + it[0]) * 4 + (points.y + it[1]) * this.canvas.width * 4; // const index = pjt + it[1] * cwc + it[0] * 4; // // if (loadIndex[index]) { // // continue; // // } // if (it[2].length < canvasData.data.length - index) { // canvasData.data.set(it[2], index); // } // // 记录一下已经加载过的像素点 // loadIndex[index] = index; // } // } // this.canvas2d.putImageData(canvasData, 0, 0); // loadIndex = null; // this.clearCanvasPosition(); // console.timeEnd('mapRender'); }); } // 判断点击事件 clickMap(e) { const _x = e.clientPos.x; const _y = e.clientPos.y; const map = this._map; const innerWidth = window.innerWidth; const innerHeight = window.innerHeight; const zoom = getZoom(); const x = e.pixel.x / zoom[0]; // _x / innerWidth * map.width; const y = e.pixel.y / zoom[1]; // _y / innerHeight * map.height; const datas = this.getDatas(); // 选中的对象 const filterData = []; for (var i = 0; i < datas.length; i++) { const points = this._map.pointToPixel(new window.BMapGL.Point(datas[i].x, datas[i].y)); if (Math.abs(points.x - x) < 8 && Math.abs(points.y - y) < 8) { filterData.push(datas[i]); // return; }; } if( filterData.length > 0 ){ this.emit('click', filterData[0], filterData, e); } } // 触摸点判断 moveMap(_x, _y, event) { if (this.moveMapKey) { clearTimeout(this.moveMapKey); } this.moveMapKey = setTimeout(() => { const map = this._map; const innerWidth = window.innerWidth; const innerHeight = window.innerHeight; const zoom = getZoom(); const x = event.clientPos.x / zoom[0]; // _x / innerWidth * map.width; const y = event.clientPos.y / zoom[1]; // _y / innerHeight * map.height; const datas = this.getDatas(); for (var i = 0; i < datas.length; i++) { const points = this._map.pointToPixel(new window.BMapGL.Point(datas[i].x, datas[i].y)); if (Math.abs(points.x - x) < 8 && Math.abs(points.y - y) < 8) { // 如果当前选中得对象不是自己则触发移除事件 if (this.mouseObject !== datas[i]) { this.emit('mouseout', this.mouseObject, event); } this.mouseObject = datas[i]; this.emit('mouse', datas[i], { ...event, layerX: x, layerY: y }); return; }; } // 如果当前选中得对象不是自己则触发移除事件 if (this.mouseObject) { this.emit('mouseout', this.mouseObject, { ...event, layerX: x, layerY: y }); } // this.mouseObject = datas[i]; }, 300); } emit(type, ...arg) { this.events.forEach((eve) => { if (eve.type === type) { eve.resovle(...arg); }; }); } on(type, fn) { this.events.push({ type, resovle: fn }); } close() { this.clearEvent(); this.canvas.remove(); this.worker.terminate(); } } /** * 矩阵数据计算对象 */ class MatrixDrive { constructor(bounds = [1920, 960]) { // 可视框 this.bounds = bounds; // 计算中心点 this.center = null; } // 传入矩阵数据 /** * { pos: [x, y] , data: {} } */ setMatrix(Arrays) { this.matrix = Arrays; } setOff(b) { this.bounds = b; } /** * @param {Object} bounds * [ [ 右上角x距离, y距离 ], [左下角 x距离, y距离] ]; */ render(bounds) { const ysx = bounds[0][0]; const ysy = bounds[0][1]; const zxx = bounds[1][0]; const zxy = bounds[1][1]; // 初始化zoom // 要处理的矩阵数据 const datas = this.matrix; const boundPoint = []; const [offw, offh] = this.bounds; const width = Math.abs(zxx) + Math.abs(ysx); const height = Math.abs(zxy) + Math.abs(ysy); for (var i in datas) { const data = datas[i]; const pos = data.pos; if (zxx < pos[0] && pos[0] < ysx && zxy > pos[1] && pos[1] > ysy) { // 判断范围内的数据 // 计算范围内数据 data.position = [Math.abs(pos[0] - zxx) / width * offw, Math.abs(pos[1] - ysy) / height * offh]; boundPoint.push(data); } } // 将处理好的数据进行排列 this.renderAfter(boundPoint); return boundPoint; } // 进行渲染完毕 renderAfter(datas) { // render(this.matrix); console.log(datas.length); } } class ImageCanvasData { constructor(images) { // 像素数据 this.imageData = null; this.set(images); } set(img) { // 创建 const { canvas, context } = ImageCanvasData.getCanvas(); canvas.width = img.width; canvas.height = img.height; context.drawImage(img, 0, 0); // 获取图片的像素数据 var imageData = context.getImageData(0, 0, img.width, img.height); // 现在imageData包含了图片的所有像素数据,您可以对其进行操作 this.imageData = imageData; // 计算初始化坐标位置 this.bound = [parseInt(img.width), parseInt(img.height)]; // 获取数据的下标数组 const imageIndex = []; let tongzu = null; for (var i = 0; i * 4 < imageData.data.length; i++) { // 判断是否是透明的 if (imageData.data[i * 4 + 3] !== 0) { // 如果没有 那就初始化 if (!tongzu) { tongzu = [i % img.width, parseInt(i / img.width), null, i * 4, (i * 4) % (img.width * 4), parseInt((i * 4) / (img.width * 4))]; tongzu[2] = imageData.data.slice(tongzu[3], i * 4); imageIndex.push(tongzu); }else { // 这里需要判断是否换行了 如果已经换行了 就要结束这边并且新起一个 if( parseInt((i * 4) / (img.width * 4)) === tongzu[5] ){ tongzu[2] = imageData.data.slice(tongzu[3], i * 4); }else { tongzu = [i % img.width, parseInt(i / img.width), null, i * 4, (i * 4) % (img.width * 4), parseInt((i * 4) / (img.width * 4))]; imageIndex.push(tongzu); } } } // imageIndex.push([parseInt(i / img.width), i % img.width, imageData.data.slice(i, i + 4)]); } this.imageIndex = imageIndex; } toDatas() { // 假设您已经有一个canvas元素,并且图片已经通过drawImage方法绘制进去 var canvas = document.getElementById('myCanvas'); var context = canvas.getContext('2d'); // 绘制图片到canvas上 var image = new Image(); image.src = 'path/to/your/image.jpg'; image.onload = function () { context.drawImage(image, 0, 0); // 获取图片的像素数据 var imageData = context.getImageData(0, 0, canvas.width, canvas.height); // 现在imageData包含了图片的所有像素数据,您可以对其进行操作 console.log(imageData); }; } static getCanvas() { if (this.canvasObj) return this.canvasObj; var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); this.canvasObj = { canvas, context }; return this.canvasObj; } }
2. 计算用的worker内容
// 保存的图片数据 const images = {}; // 数据 const points = []; // canvas let canvas = null; // 绘画 let ctx = null; // 最新的一次timekey let timekey = null; // 监听消息事件 onmessage = function (e) { // 获取方式类型 const type = e.data.type; // 传入数据 if (type === "addDatas") { addDatas(e.data); } // 传入图片数据 if (type === "addImages") { addImages(e.data); } // 传入canvas if (type === "addCanvas") { addCanvas(e.data); } // 进行渲染 if (type === "render") { renderCanvas(e.data); } }; //新增数据 const addDatas = function (data) { points = data.points; }; // 渲染 const renderCanvas = function (data) { timekey = data.time; render(data); }; // 新增canvas const addCanvas = function (data) { canvas = data.canvas; ctx = canvas.getContext("2d"); }; // 新增图片 const addImages = function (data) { images[data.data.id] = data.data; }; const getImagesById = function(key){ return images[key]; } // 开始进行渲染计算 const render = function (data) { const datas = data.data; if( !datas || datas.length === 0 ){ return; } console.time('mapRender'); const width = data.width; const height = data.height; const time = data.time; // 获取当前canvas的像素组 const canvasData = new ImageData(width, height); let loadIndex = {}; for (var i = datas.length - 1; i >= 0; i--) { data = datas[i]; const images = getImagesById(data.iconkey); if (!images) continue; const points = data.p; // config = data.iconConfig || {}; // w = config.width || 24; // h = config.height || 35; // this.canvas2d.drawImage(images, points.x - w / 2, points.y - h / 2, w, h); const lng = points.x - images.w / 2; const lat = points.y - images.h / 2; if (lng > canvasData.width || lng < 0 || lat > canvasData.height || lat < 0) { continue; } // 临时变量由下面的公式分解出来的 const cwc = width * 4; const pjt = lng * 4 + lat * cwc; for (var it of images.imageIndex) { // 同行中如果并行的 // const index = (points.x + it[0]) * 4 + (points.y + it[1]) * this.canvas.width * 4; const index = pjt + it[1] * cwc + it[0] * 4; // if (loadIndex[index]) { // continue; // } if (it[2].length < canvasData.data.length - index) { canvasData.data.set(it[2], index); } // 记录一下已经加载过的像素点 loadIndex[index] = index; } } // this.canvas2d.putImageData(canvasData, 0, 0); loadIndex = null; renderMap({t: "render", d: canvasData, t: time}); // postMessage({t: "render", d: canvasData, t: time}); // this.clearCanvasPosition(); console.timeEnd('mapRender'); }; const renderMap = function(params){ setTimeout(()=>{ if( params.t === timekey ){ postMessage(params); } }, 10) }
3. 业务代码中使用的内容
// 创建告警信息数据分布 layerGJ () { const layerIcon = new MapCanvasLayer(); layerIcon.setMap(map); // 每次渲染前对数据进行过滤 layerIcon.setFilter((datas) => { // 获取选中的类型 const types = this.legend.filter((e) => e.check).map((e) => e.type); // 从数据中进行过滤 const d = datas.filter( (e) => types.indexOf(e.unitType || e.ssxtBm) > -1 ); return d; }); layerIcon.setImages({ getImages: (data) => { if (data.unitType === 'XKS') { return `/images/deviceIcon/xks_${data.lwzt || '1'}.svg`; } // 如果没有类型则选择电气 const name = reversedMapPath[data.ssxtBm]; const bjzt = data.bjzt; // 暂时返回两种状态颜色, 因为只有正常和异常两种颜色 if (bjzt === '01') { return `/images/deviceIcon/${name}_01.svg`; } else { return `/images/deviceIcon/${name}_10.svg`; } // return `/images/deviceIcon/${name}_${bjzt}.svg`; } }); layerIcon.on('click', (data) => { if (data.unitType === 'XKS') { // this.xksId = data.dwbm; this.showXksDialog = true; return; // open(); } this.$emit('deviceClick', data); }); layerIcon.on('mouse', (data, event) => { // 显示标题 this.deviceTitleConfig = { ...data, left: event.layerX + 'px', top: event.layerY - 30 + 'px', show: true }; }); layerIcon.on('mouseout', (data) => { // 显示标题 this.deviceTitleConfig = { show: false }; }); this.getLayerIconGJ = function () { return layerIcon; }; }, this.getLayerIconGJ().setData(data); // data中需要包含x, y
据目前使用来看。1W数据的渲染速度在20ms左右。10W的速度在200ms 这个速度。还是可以满足一般的业务需求的。 有疑问可以联系我。137550763
                    
                
                
            
        
浙公网安备 33010602011771号