高德地图实现一个比例圆环形聚合点缩放(代码片段)

月亮出来了 月亮出来了     2022-12-25     751

关键词:

前言:碰到一个需求,效果实现一个该范围不同点数的圆环比例以及总数。比例按照对应的区域内不同内容的数量实现比例圆环比例。

查看高德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$i41`, y: `22.164$i32` );
       else 
        this.state.blueIconArr.push( x: `113.56$i11`, y: `22.132$i59` );
      
    
    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$i71`, y: `22.167$i42` );
       else 
        this.state.redIconArr.push( x: `113.54$i91`, y: `22.122$i59` );
      
    

    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;

 

地图比例尺与高德地图中的缩放级别(0-20)的映射关系与转换方法

一、概述近期基于高德地图进行了不少开发工作,期间遇到了一个与比例尺相关的问题。如何将地图比例尺与高德地图中的缩放级别(0-20)对应起来?二、映射关系[高德地图api比例尺][https://www.cnblogs.com/yesyes/p/6785705.html]三、转... 查看详情

高德地图实现动态弧线(飞线)效果(代码片段)

用高德结合echarts实现点标记,标记点连线(圆弧线),实现动态轨迹循环播放,点击显示弹窗 对应行政区划变颜色,hover显示提示信息。页面js代码粘贴出来 供参考 上图效果js<script>layui.use([‘element‘,‘jquery‘,‘fo... 查看详情

高德地图判断点的位置是否在浏览器可视区域内(代码片段)

...区域,再将地图放大到之前缩放的级别。 实现思路:高德地图有几个关系判断的API:判断点是否在线上、点是否在多边形内、面与面的几何关系,可看下方链接示例https://lbs.amap.com/api/javascript-api/example/relationship-judgment/is-point... 查看详情

高德地图使用-监听地图缩放(代码片段)

监听地图缩放事件map.on('zoomchange',()=> varzoom=map.getZoom(); console.log("缩放",zoom));map.on('zoomend',()=> console.log("缩放结束")); 查看详情

使用高德地图api实现拖动地图后重新回到原处(代码片段)

...:问题描述    我在一个有限大小的div容器内使用高德地图api定位了一个位置,并且添加了marker点,当我拖动地图查看其他位置时,有时候拖的太远,导致最开始定位那个地方不好找(找不到)。 二... 查看详情

android——高德地图实现多点连线与点击定位监听实现(代码片段)

最近开发的项目中需要使用到的功能,如下图所示:服务器会传来一个包含项数据类型为坐标与时间的数组。需要实现的功能有:1.按时间顺序对每个点进行连线。2.点击单个点会在点的上分dialog内显示时间(如下... 查看详情

高德地图的marker和markercluster的应用场景分析

参考技术A表格中每一行数据均对应地图上一个坐标点,要求:1、在表格中选中一行时,在地图上对应坐标点被同步点亮,以区别其他坐标点2、点击地图上坐标点时,在表格中对应数据行被同步选中,以区别表格中其他数据行。... 查看详情

自定义圆环形进度条实现(代码片段)

最近项目里边要用进度条,进度条中间展示进度,底部展示label,因为这个组件用的地方多,所以我就直接封装了一个通用组件。先看一下效果图:功能有:圆环的颜色和进度可以自定义;中间文字可... 查看详情

使用高德地图api实现拖动地图后重新回到原处(代码片段)

...:问题描述    我在一个有限大小的div容器内使用高德地图api定位了一个位置,并且添加了marker点,当我拖动地图查看其他位置时,有时候拖的太远,导致最开始定位那个地方不好找(找不到)。 二... 查看详情

使用高德地图api实现拖动地图后重新回到原处(代码片段)

...:问题描述    我在一个有限大小的div容器内使用高德地图api定位了一个位置,并且添加了marker点,当我拖动地图查看其他位置时,有时候拖的太远,导致最开始定位那个地方不好找(找不到)。 二... 查看详情

使用echarts实现一个可拖拽缩放的立体地图

...页需要做一个立体的中国地图,原先的平面地图使用的是高德与echarts结合,地图用高德,点用echarts,而现在要做立体的地图,并且不需要世界地图的背景,于是我直接放弃了高德直接改全部由echarts来实现。echarts5.1.2vue-echarts6.0.... 查看详情

android-------高德地图两点路线和多个点路线绘制(代码片段)

...与大家分享一下。两点路线是起点和终点两个经纬度点,高德绘制出路线,可以实现实线和虚线功能效果图:      相关属性: mPolylineOptions=newPolylineOptions();mPolylineOptions.setDottedLine(t 查看详情

高德地图使用-marker标记点(代码片段)

效果如图1.标记点列表varmarkersList=[ position:[118.922723,31.915307], icon: image:'../images/start.png', size:[30,30], , name:"监控一", position:[118.903333,31.91563], icon: image:'../i 查看详情

webgis中的比例尺实现(代码片段)

概述比例尺在地图中是一个非常重要的概念,有着辅助读图的作用。本文在ol框架下,实现webgis中的比例尺功能。实现效果概念在课本中,对其的定义是:地图上所表示的空间尺度称作比例尺。在webgis中,比例... 查看详情

vue限制高德地图缩放的层级

参考技术A由于高德的地图缩放等级并不多,这里一般用到的是12-17级,所以可以直接写死,热力点具体的半径大小需要根据显示效果慢慢调整,地图放得越大,半径就调整得越大。加入该方法后, 查看详情

qt编写安防视频监控系统25-离线地图(代码片段)

...城市进行离线地图的下载,离线地图一般使用百度的或者高德的居多,其实对于在线地图使用比较熟练的话,那些方法完全一致的,理论上厂家做成的api接口也会统一的,唯一的不同就是引入的js文件不一样,使用方法和处理流... 查看详情

玩玩flutterweb——实现高德地图插件(代码片段)

1.啰嗦几句去年写了一个功能简单的高德地图插件给flutter_deer使用,当时支持了Android与iOS两端。前一阵子有一个issue问是否会支持FlutterWeb,当时我有点懵,毕竟js我都不熟。。。不过先记下这个需求,等着有时间... 查看详情

高德地图实现标点点聚合和信息窗体

  //展示    showscenicPoints()       var icon = new AMap.Icon(        size: 查看详情