地图 - 实现有多条定位,显示多条定位,并且使用一个圆形遮罩层将多条定位进行覆盖

首先,需要在你的index.html模板页面头部加载百度地图JavaScript API代码,密钥可去百度地图开放平台官网申请

<script type="text/javascript" src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥"></script>

然后,使用npm方式安装react组件库,然后通过es模块加载

npm install react-bmapgl --save

在需要显示地图的页面中编写

import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { Map, Marker, Circle } from 'react-bmapgl';

export default function ShopMapPage() {
  const location = useLocation();
  const record = location.state || {};  // 接收上个页面传递过来的地区数据,以便定位的显示

  useEffect(() => {
    // 加载百度地图脚本
    const loadMapScript = () => {
      return new Promise<void>((resolve, reject) => {
        const script = document.createElement('script');
        script.src =
          'http://api.map.baidu.com/api?v=1.0&type=webgl&ak=您的密钥';
        script.onload = resolve;
        script.onerror = reject;
        document.body.appendChild(script);
      });
    };

    const geocode = (address: string) => {
      return new Promise<BMapGL.Point>((resolve, reject) => {
        const geocoder = new BMapGL.Geocoder();
        // 将地区转换为经纬度
        geocoder.getPoint(address, function (point) {
          if (point) {
            resolve(point);
          } else {
            reject('无法获取该地区的坐标');
          }
        });
      });
    };

    // 计算当前两个标记点之间的距离
    const getDistance = (point1: BMapGL.Point, point2: BMapGL.Point) => {
      const { lng: lng1, lat: lat1 } = point1;
      const { lng: lng2, lat: lat2 } = point2;
      // 在经纬度坐标系统中,经度和纬度通常以度(°)为单位表示。但是在计算距离或执行其他数学计算时,可能需要将角度转换为弧度(radian)来进行更准确的计算
      const radLng1 = lng1 * (Math.PI / 180); // lng1 是经度的值,乘以 (Math.PI / 180) 可以将其从度转换为弧度
      const radLat1 = lat1 * (Math.PI / 180);
      const radLng2 = lng2 * (Math.PI / 180);
      const radLat2 = lat2 * (Math.PI / 180);
      const a = Math.sin(radLat1) * Math.sin(radLat2); //调用 Math.sin() 方法计算出它们的正弦值,然后将两个正弦值相乘,即可得到参数 a 的值
      const b =
        Math.cos(radLat1) * Math.cos(radLat2) * Math.cos(radLng2 - radLng1);
      const distance = 6378137 * Math.acos(a + b); //调用 Math.acos() 方法,可以计算出两个点之间的弧度差,并将其乘以地球半径,就可以得到两个点之间的球面距离。
      return distance;
    };

    loadMapScript().then(() => {
      const map = new BMapGL.Map('mapContainer');

      // 地图放大缩写实现
      map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
      const scaleCtrl = new BMapGL.ScaleControl(); // 添加比例尺控件
      map.addControl(scaleCtrl);
      const zoomCtrl = new BMapGL.ZoomControl(); // 添加缩放控件(按钮)
      map.addControl(zoomCtrl);

      // const addresses = ['北京市海淀区', '北京市丰台区', '广州市天河区']; // 待转换的地区名称列表
      const addresses = [];
      if (record.length) {
        record.map((item: { city: string }) => {
          const result = item.city.replace(/\s/g, ''); // 使用正则表达式替换空格
          addresses.push(result);
        });
      } else {
        const result = record.city.replace(/\s/g, ''); // 使用正则表达式替换空格
        addresses.push(result);
      }

      Promise.all(addresses.map((address) => geocode(address)))
        .then((points) => {
          points.forEach((point) => {
            const marker = new BMapGL.Marker(point);
            map.addOverlay(marker);
          });

          // 如果地区有多条时,就出现遮罩层并且会根据多条定位调整位置并且缩放
          if (addresses.length > 1) {
            // 创建圆形遮罩层
            // 1. 使用 reduce() 方法将所有地理坐标点的经度 (lng) 和纬度 (lat) 分别累加。最终得到的 center 对象包含了所有点的经度和纬度之和。
            const center = points.reduce(
              (acc, point) => {
                return {
                  lng: acc.lng + point.lng,
                  lat: acc.lat + point.lat
                };
              },
              { lng: 0, lat: 0 }
            );
            // 2. 通过将经度和纬度分别除以标记点的数量 points.length,可以得到平均值,即标记点的中心坐标。
            center.lng /= points.length;
            center.lat /= points.length;
            // 3. 通过比较距离大小,找到最大的距离,将其存储在 maxDistance 变量中
            let maxDistance = 0;
            for (let i = 0; i < points.length; i++) {
              for (let j = i + 1; j < points.length; j++) {
                const distance = getDistance(points[i], points[j]); // getDistance()方法计算当前两个标记点之间的距离
                // 如果这个距离比目前的最大距离 maxDistance 要大,就将它赋值给 maxDistance
                if (distance > maxDistance) {
                  maxDistance = distance; //在所有的标记点对中,最终得到的 maxDistance 就是所有标记点之间的最大距离。
                }
              }
            }
            // 创建 BMapGL.Circle 对象时,需要传入三个参数:圆心坐标、半径和样式选项
            const circle = new BMapGL.Circle(center, maxDistance, {
              fillColor: '#454399', // 填充颜色
              // strokeColor: '#000', // 边框颜色
              strokeWeight: 1, // 边框宽度
              strokeOpacity: 0.8, // 边框透明度
              fillOpacity: 0.3 // 填充透明度
            });
            map.addOverlay(circle);

            const viewport = map.getViewport(points); //将地图的视野调整为适合包含所有标记点的最佳范围
            map.setViewport(viewport);
          } else {
            // 如果地区只有一条的时候,就将此定位设为中心并且设置缩放大小
            map.centerAndZoom(points[0], 11); //centerAndZoom() 是百度地图 API 中的一个方法,用于将地图中心点设置为指定的坐标,并设置地图的缩放级别。
          }
        })
        .catch((error) => {
          console.error(error);
        });
    });
  }, []);

  return (
    <div id="mapContainer" style={{ height: '45vw', width: '100%' }}></div>
  );
}

根据搜索的地区显示相对应的地图展示

根据单条信息点击时对应显示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/340214.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

消息队列之王——Kafka

Zookeeper 在学习kafka之前&#xff0c;我们需要先学习Zookeeper&#xff0c;那Zookeeper是什么呢&#xff1f;Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目。 Zookeeper 工作机制 Zookeeper从设计模式角度来理解&#xff1a;是一个基于观…

VUE---插槽

一、插槽的作用&场景 1、在封装组件的时候&#xff0c;将可变的结构设计为插槽&#xff08;<slot></slot>&#xff09; 2、使用上述组件的时候&#xff0c;可以按需为插槽提供自定义的结构&#xff0c;以达到复用组件且高度自定的效果 二、基本语法 1、组件内…

2024年【广东省安全员B证第四批(项目负责人)】新版试题及广东省安全员B证第四批(项目负责人)作业模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 广东省安全员B证第四批&#xff08;项目负责人&#xff09;新版试题参考答案及广东省安全员B证第四批&#xff08;项目负责人&#xff09;考试试题解析是安全生产模拟考试一点通题库老师及广东省安全员B证第四批&…

在CentOS 7中配置 RAID服务

实验过程 Xnode1克隆虚拟机raid ps&#xff1a; 阿里云盘Xnode1获取 xnode1 https://www.alipan.com/s/HgLXfoeBWG2 提取码: eb70 编辑虚拟机 添加2硬盘 CRT连接&#xff08;root密码&#xff1a;000000&#xff09; 创建raid 0 [rootdemo ~]# lsblk 安装mdadm [rootdemo…

Facebook直播指南:教你如何轻松控评

Facebook直播在促进互动、扩大影响力、实时报道、创造内容和商业机会等方面都可以发挥很好的效果。无论是企业推广产品还是个人博主提升人气&#xff0c;Facebook直播都是一个值得尝试的渠道。 但是在刚开始直播的时候&#xff0c;可能会遇到以下情况&#xff1a;想要通过Face…

Java项目:ssm框架基于spring+springmvc+mybatis框架的民宿预订管理系统设计与实现(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm827基于SSM框架的民宿预订管理系统设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调…

【数据结构与算法】之字符串系列-20240122

这里写目录标题 一、383. 赎金信二、387. 字符串中的第一个唯一字符三、389. 找不同四、392. 判断子序列五、409. 最长回文串 一、383. 赎金信 简单 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果…

2、Line Charts折线图

可视化时间趋势 现在你已经熟悉了编码环境,是时候学习如何制作自己的图表了! 在本教程中,您将学习足够的Python来创建专业外观的折线图。然后,在接下来的练习中,您将使用您的最新技能处理真实世界的数据集。 本课程数据集夸克网盘下载链接:https://pan.quark.cn/s/a235ac…

微信公众号怎么申请超过2个

一般可以申请多少个公众号&#xff1f;目前公众号申请数量的规定是从2018年底开始实施的&#xff0c;至今没有变化。规定如下&#xff1a;1、个人可以申请1个个人主体的公众号&#xff1b;2、企业&#xff08;有限公司&#xff09;可以申请2个公众号&#xff1b;3、个体户可以申…

记录 js 过滤到tree上面的多余的数据

代码如下&#xff08;示例&#xff09;&#xff1a; filterTree(arr, ids,firsttrue) {if(first){//首次传入深度克隆数据防止修改源数据arrJSON.parse(JSON.stringify(arr))}let emptyArr [];for (let item of arr) {if (ids.includes(item.id)) {if (item.children &&am…

友元、隐式类型转化

友元提供了一种突破封装的方式&#xff0c;有时提供了便利。但是友元会增加耦合度&#xff0c;破坏了封装&#xff0c;所以友元不宜多用。 友元分为&#xff1a;友元函数和友元类 &#xff08;一&#xff09;友元函数 友元函数可以直接访问类的私有成员&#xff0c;它是定义在…

L1-058 6翻了(Java)

“666”是一种网络用语&#xff0c;大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字“9”&#xff0c;意思是“6翻了”&#xff0c;实在太厉害的意思。如果你以为这就是厉害的最高境界&#xff0c;那就错啦 —— 目前的最高境界是数字“27”&#xff0c;因为这…

JVM系列-1.初识JVM

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理&#x1f525;如果感觉博主的文…

【QT+QGIS跨平台编译】之二:【zlib+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、zlib介绍二、文件下载三、文件分析四、pro文件五、编译实践 一、zlib介绍 zlib是一套通用的解压缩开源库&#xff0c;提供了内存&#xff08;in-memory&#xff09;压缩和解压函数。zlib是一套通用的解压缩开源库&#xff0c;提供了内存&#xff08;in-memory&am…

JavaScript DOM表单相关操作之表单相关事件

1、焦点事件 焦点事件就是鼠标的光标事件&#xff0c;点到输入框中&#xff0c;叫做获得焦点事件&#xff0c;当鼠标离开这个输入框时叫做失去焦点事件。 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>知数SEO_专注搜…

计算机网络安全——密码学入门

网络安全是指在网络领域、专业领域的网络安全包括在基础计算机网络基础设施中所做的规定&#xff0c;网络管理员采取的策略来保护网络及网络可访问资源免受未经授权的访问&#xff0c;以及对其有效性&#xff08;或缺乏&#xff09;的持续不断的监控和测量的结合。 1. 密码学的…

什么是网络安全?网络安全概况

网络安全涉及保护我们的计算机网络、设备和数据免受未经授权的访问或破坏。 这个领域包括多种技术、过程和控制措施&#xff0c;旨在保护网络、设备和数据免受攻击、损害或未授权访问。网络安全涉及多个方面&#xff0c;包括但不限于信息安全、应用程序安全、操作系统安全等 …

K8S搭建(centos)二、服务器设置

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

“gradle project sync failed”

很久没打开AndroidStudio了&#xff0c;打开电脑发现这个软件都没了。重新安装后创建项目不成功&#xff0c;就提示了这个错误。 错误原因 “gradle project sync failed”&#xff1a;gradle没有配置成功。在安卓项目下找到目标文件&#xff1a;gradle --> wrapper -->…

HarmonyOS 发送http网络请求

好 本文 我们来说 http请求 首先 我们要操作网络内容 需要申请权限 项目中找到 main目录下的module.json5 最下面加上 "requestPermissions": [{"name": "ohos.permission.INTERNET"} ]这里 我在本地写了一个get接口 大家可以想办法 弄一个后…