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

首先,需要在你的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>
  );
}

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

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

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的实现: 1. 新建一个Qt Widgets应用程序工程。 2. 在mainwindow.ui中添加一个QSlider(用于控制颜色的R、G、B值)和一个QLabel(用于显示颜色),并设置QSlider的最小值为0,最大值为255,步长为1。 3. 在mainwindow.cpp中实现以下代码: ```c++ #include "mainwindow.h" #include "ui_mainwindow.h" #include <QColor> #include <QPainter> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect(ui->slider, SIGNAL(valueChanged(int)), this, SLOT(updateColor(int))); } MainWindow::~MainWindow() { delete ui; } void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); int width = ui->label->width(); int height = ui->label->height(); int r = ui->slider->value(); int g = ui->slider->value(); int b = ui->slider->value(); QColor color1(0, r, g, b); QColor color2(r, 0, g, b); QColor color3(r, g, 0, b); // 渲染圆形渐变颜色 QRadialGradient gradient(width / 2, height / 2, width / 3, width / 2, height / 2); gradient.setColorAt(0.0, color1); gradient.setColorAt(0.5, color2); gradient.setColorAt(1.0, color3); painter.setBrush(QBrush(gradient)); painter.drawEllipse(0, 0, width, height); } void MainWindow::updateColor(int value) { // 更新颜色 update(); } ``` 4. 运行程序,拖动QSlider,即可看到圆形滑动条显示的RGB渐变颜色。 说明: 在paintEvent函数中,我们根据QSlider的值生成三种颜色,并使用QRadialGradient渲染圆形渐变颜色。 在updateColor函数中,我们使用update函数来实时更新颜色。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值