高德地图实现一个比例圆环形聚合点缩放
Posted 月亮出来了
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高德地图实现一个比例圆环形聚合点缩放相关的知识,希望对你有一定的参考价值。
前言:碰到一个需求,效果实现一个该范围不同点数的圆环比例以及总数。比例按照对应的区域内不同内容的数量实现比例圆环比例。
查看高德api只有点聚合效果,我们可以根据他的基础api来增加实现更高级的效果改造。
先上效果图
1、最低层级时候效果:(这里就是打点而已)
2、缩放时候:(这时候将红色和蓝色圆环缩放在一个区域,我们绘制出来圆环显示对应数值3个红色和4个蓝色)
3、继续缩放时候效果(注意:红色和蓝色是该区域内的比例,所占比例是一样的,总数是7)
附上代码:可以直接复制黏贴使用
该功能核心是将canvas绘制的圆环通过base64转为图片,然后传给高德api渲染
(比较粗略,但是这个实现基础,有其他需求可以自行修改。点个赞评论再走,不要白嫖)
import React from \'react\'; import { connect } from \'dva\'; import styles from \'./index.less\'; import iconAddress from \'../../static/dir-marker.png\'; import { Button } from \'antd\'; /** * 全局变量 * **/ const AMap = window.AMap; class LBSMap extends React.Component { state = { mapLang: (localStorage.getItem(\'lang\') === \'TC\' || localStorage.getItem(\'lang\') === \'CHS\') ? \'zh_cn\' : \'en\', //en:英文,zh_en:中英文对照 aaa: null, blueIconArr: [], redIconArr: [], markers: [], }; componentDidMount() { this.renderRing(); } /********************************************使用renderClusterMarker属性实现聚合点的完全自定义绘制*****************************************/ renderRing = (blueIconArr = []) => { const markers = []; /*** * 创建地图实例 * **/ const map = new AMap.Map(\'lbsMap\', { zoom: 13,//级别 center: [113.55891, 22.17059],//中心点坐标 // lang: this.state.mapLang, expandZoomRange: true, }); /*** * 异步同时加载多个插件 * AMap.MarkerClusterer点聚合插件、AMap.CircleEditor圆编辑插件、AMap.ElasticMarker灵活点标记, * 可以随着地图级别改变样式和大小的 Marker、AMap.AdvancedInfoWindow高级信息窗体 * **/ AMap.plugin([\'AMap.ToolBar\', \'AMap.MarkerClusterer\'], function() { var toolbar = new AMap.ToolBar(); map.addControl(toolbar); }); /****** * 蓝色的点模拟数据 * ****/ // 创建一个 蓝色Icon const blueIcon_3d93fd = new AMap.Icon({ size: new AMap.Size(25, 34),// 图标尺寸 image: iconAddress, // 图标的取图地址 imageSize: new AMap.Size(135, 40),// 图标所用图片大小 imageOffset: new AMap.Pixel(-9, -3), // 图标取图偏移量 }); for (let i = 0; i < 7; i++) { if (i % 2 === 0) { this.state.blueIconArr.push({ x: `113.57${i}41`, y: `22.164${i}32` }); } else { this.state.blueIconArr.push({ x: `113.56${i}11`, y: `22.132${i}59` }); } } const redIcon_f34234 = new AMap.Icon({ size: new AMap.Size(25, 34), image: iconAddress, imageSize: new AMap.Size(135, 40), imageOffset: new AMap.Pixel(-96, -3), }); for (let i = 0; i < 6; i++) { if (i % 2 === 0) { this.state.redIconArr.push({ x: `113.55${i}71`, y: `22.167${i}42` }); } else { this.state.redIconArr.push({ x: `113.54${i}91`, y: `22.122${i}59` }); } } this.state.blueIconArr.forEach(item => { markers.push(new AMap.Marker({ position: new AMap.LngLat(item.x, item.y), icon: blueIcon_3d93fd, offset: new AMap.Pixel(-15, -20), type: \'blueIcon_3d93fd\', })); }); this.state.redIconArr.forEach(item => { markers.push(new AMap.Marker({ position: new AMap.LngLat(item.x, item.y), icon: redIcon_f34234, offset: new AMap.Pixel(-15, -20), type: \'redIcon_f34234\', })); }); var _renderClusterMarker = function(mapContext) { console.log(\'context\', mapContext.markers); /*************计算颜色在圆的比例为多少*************/ const orangeColorRing = []; const yellowColorRing = []; const greenColorRing = []; mapContext.markers.forEach(item => { const itemColorType = item.De.type; if (itemColorType === \'greenBlueIcon_0ccae7\') { orangeColorRing.push(itemColorType); } if (itemColorType === \'redIcon_f34234\') { yellowColorRing.push(itemColorType); } if (itemColorType === \'blueIcon_3d93fd\') { greenColorRing.push(itemColorType); } }); const orangeNumber = orangeColorRing.length; const yellowNumber = yellowColorRing.length; const greenNumber = greenColorRing.length; const total = orangeNumber + yellowNumber + greenNumber; const orangePer = orangeNumber / total; const yellowPer = yellowNumber / total; const greenPer = greenNumber / total; const ringPerInTotal = orangePer + yellowPer + greenPer; const perInTotal1 = (orangePer / ringPerInTotal) * 2; const perInTotal2 = (yellowPer / ringPerInTotal) * 2; const perInTotal3 = (greenPer / ringPerInTotal) * 2; function process() { const ring = arguments[0]; const canvas = document.getElementById(ring.canvasId); const context = canvas.getContext(\'2d\'); const centerX = ring.canvasW / 2; const centerY = ring.canvasH / 2; const borderWidth = ring.bdWidth; const radius = ring.canvasW / 2 - borderWidth / 2; canvas.width = ring.canvasW; canvas.height = ring.canvasH; //绘制内圈 context.save(); context.beginPath(); context.arc(centerX, centerY, radius, 0, 360, false); context.fillStyle = \'rgba(255, 255, 255, 0.75)\'; context.fill(); context.stroke(); context.restore(); //圆环中文字 context.save(); context.beginPath(); context.font = \'18px Georgia\'; context.textAlign = \'center\'; context.fillStyle = \'black\'; context.fillText(mapContext.count, centerX, centerY + 6); context.restore(); const ringFunction1 = (start, end, color) => { context.save(); context.beginPath(); context.lineWidth = borderWidth; context.arc(centerX, centerY, radius, start, end, false); context.strokeStyle = color; context.stroke(); context.closePath(); //路径结束 context.restore(); }; const rad = Math.PI; const rad1 = -Math.PI / 2 + perInTotal1 * rad; const rad2 = -Math.PI / 2 + (perInTotal1 + perInTotal2) * rad; const rad3 = -Math.PI / 2 + (perInTotal1 + perInTotal2 + perInTotal3) * rad; ringFunction1(-Math.PI / 2, rad1, \'#0ccae7\'); ringFunction1(rad1, rad2, \'#f34234\'); ringFunction1(rad2, rad3, \'#3d93fd\'); } /*********************调用方法*************************/ const canvasDiv = document.getElementById(\'canvasDiv\'); const canvasW = canvasDiv.offsetWidth; const canvasH = canvasDiv.offsetWidth; process({ canvasId: \'canvasDiv\', //canvas的Id canvasW: canvasW, //canvas的width canvasH: canvasH, //canvas的height bdWidth: 6, //圆环的宽 }); /***************将绘制的canvas转化为img交给高德***********/ const dataURL = canvasDiv.toDataURL(); const img = document.createElement(\'img\'); img.src = dataURL; img.alt = \'\'; const count = markers.length; const size = Math.round(30 + Math.pow(mapContext.count / count, 1 / 5) * 20); //设置图像偏移量 mapContext.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2)); mapContext.marker.setContent(img); }; /**********************运行高德地图自定义实例***************/ var cluster = new AMap.MarkerClusterer(map, markers, { gridSize: 80, renderClusterMarker: _renderClusterMarker, }); }; addRed = () => { this.setState({ blueIconArr: [] }); //this.state.blueIconArr.push({x: `113.53331`, y: `22.1644332`}) // 创建一个红色 icon const redIcon_f34234 = new AMap.Icon({ size: new AMap.Size(25, 34), image: iconAddress, imageSize: new AMap.Size(135, 40), imageOffset: new AMap.Pixel(-96, -3), }); // 创建一个青色 icon const greenBlueIcon_0ccae7 = new AMap.Icon({ size: new AMap.Size(25, 34), image: iconAddress, imageSize: new AMap.Size(135, 40), imageOffset: new AMap.Pixel(-51, -3), }); }; render() { console.log(\'state\', this.state.blueIconArr); return ( <React.Fragment> <div id="lbsMap" className={styles.LBSMap}> <canvas id="canvasDiv" width="56" height="56"></canvas> </div> </React.Fragment> ); } } export default LBSMap;
以上是关于高德地图实现一个比例圆环形聚合点缩放的主要内容,如果未能解决你的问题,请参考以下文章