@amap/amap-jsapi-loader 实现高德地图中添加多边围栏,并可编辑,编辑后获得围栏各个点的经纬度

先上一张效果图 看看是不是大家想要的效果~ ❤️
希望其中的小点能帮助大家,主要看怎么绘制在地图上的代码即可
在这里插入图片描述

1.第一步要加入项目package.json中或者直接yarn install它都可以
想必大家应该都会

 "@amap/amap-jsapi-loader": "0.0.7"

2.加入项目中

import React, { PureComponent } from 'react';
import { Radio, Checkbox, Input, Button, message as AntMessage } from 'antd';
import AMapLoader from '@amap/amap-jsapi-loader';
import { services } from '@comall-backend-builder/core';
import './index.less';

const { api } = services;
type Geofence = {
    /**
     * 圆形围栏中心点,格式:longitude,latitude
     */
    center?: string;
    /**
     * 围栏名称
     */
    name: string;
    /**
     * 多边形围栏坐标点,格式:lon1,lat1;lon2,lat2;lon3,lat3
     */
    points: string;
    /**
     * 圆形围栏半径,单位:米。范围0~5000
     */
    radius?: number;
};
type GeofenceValue = {
    geofences: Array<Geofence>;
    scope: string;
    isEdit?: boolean;
};
const DEFAULTSCOPE = 'CUSTOM';
const DEFAULTNAME = '默认区域';
interface GeofencesProps {
    onChange: (data: GeofenceValue) => void;
    /**
     * 当前值
     */
    value: GeofenceValue;
    row: any;
}

interface GeofencesStates {
    /**
     * 当前地图实例
     */
    map: any;
    /**
     * 地图api
     */
    AMap: any;
    /**
     * 多边形对象集合
     */
    polygons: any;
    /**
     * 门店位置标记
     */
    marker: any;
    /**
     * 当前的门店维度
     */
    centerPosition: any;
    /**
     * 当前的门店名称
     */
    subsiteName: string;
}

export class Geofences extends PureComponent<GeofencesProps, GeofencesStates> {
    constructor(props: any) {
        super(props);

        this.state = {
            map: undefined,
            AMap: undefined,
            polygons: undefined,
            marker: undefined,
            centerPosition: undefined,
            subsiteName: '',
        };
    }

    componentDidMount() {
        this.initMap();
    }

    initMap = () => {
        api.get({}, { apiPath: '/admin/amap/config' }).then((result: any) => {
            AMapLoader.load({
                key: result.key, // 申请好的Web端开发者Key,首次调用 load 时必填
                version: '1.4.15', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
                plugins: ['AMap.Marker', 'AMap.Polygon', 'AMap.PolyEditor'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
            })
                .then((AMap: any) => {
                    let map = new AMap.Map('mapContainer', {
                        zoom: 13,
                    });
                    this.initSubsiteCenterPosition(AMap, map);
                    this.setState({ AMap, map });
                })
                .catch((e: any) => {
                    console.log(e);
                });
        });
    };

    initSubsiteCenterPosition = (AMap: any, map: any) => {
        const result = {
            longitude: 150.644,
            latitude: -34.397
        }
        //以上是我们项目接口返回的一个点的经纬度,在此我就简单设置了
        let centerPosition = new AMap.LngLat(result.longitude, result.latitude); // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
        this.setState(
            {
                centerPosition: centerPosition,
            },
            () => {
                this.initGeofrences(AMap, map);
            }
        );
    };

    initGeofrences = (AMap: any, map: any) => {
        const { centerPosition, subsiteName } = this.state;
        //移除所有覆盖物
        const { polygons, marker } = this.state;
        if (polygons) {
            map.remove(polygons);
        }
        if (marker) {
            map.remove(marker);
        }

        // 创建一个 Marker 实例:
        let newMarker = new AMap.Marker({
            position: centerPosition,
            title: subsiteName,
            zIndex: 101,
            bubble: true,
        });
        // 将创建的点标记添加到已有的地图实例:
        map.add(newMarker);

        let newPolygons = [];
        const path = [
            centerPosition.offset(-1500, 1500),
            centerPosition.offset(1500, 1500),
            centerPosition.offset(1500, -1500),
            centerPosition.offset(-1500, -1500),
        ];

        let polygon = new AMap.Polygon({
            path: path,
            strokeColor: '#1791fc',
            strokeWeight: 6,
            strokeOpacity: 0.2,
            fillOpacity: 0.4,
            fillColor: '#1791fc',
            zIndex: 100,
            bubble: true,
        });
        newPolygons.push(polygon);

        map.add(newPolygons);
        // 缩放地图到合适的视野级别
        map.setFitView(newPolygons);

        //开启多边形编辑
        newPolygons.forEach((newPolygon, index) => {
            let newPolyEditor = new AMap.PolyEditor(map, newPolygon);
            newPolyEditor.open();

            newPolyEditor.on('addnode', () => {
                this.onPolygonChange(index);
            });

            newPolyEditor.on('adjust', () => {
                this.onPolygonChange(index);
            });

            newPolyEditor.on('removenode', () => {
                this.onPolygonChange(index);
            });
        });

        this.setState({
            map,
            polygons: newPolygons,
            marker: newMarker,
        });
        //回传默认值
        let points = this.getPoints(path);
        let newValue: GeofenceValue = {
            scope: DEFAULTSCOPE,
            geofences: [
                {
                    name: DEFAULTNAME,
                    points,
                },
            ],
        };
        this.onChange(newValue);
    };

    onChange = (data: GeofenceValue) => {
        const { onChange } = this.props;
        onChange(data);
    };

    onPolygonChange = (index: number) => {
        let { value } = this.props;
        const { polygons } = this.state;
        let geofences;
        let geofence;
        if (value) {
            geofences = value.geofences;
            geofence = geofences[index];

            let points;
            if (polygons && polygons[index]) {
                points = this.getPoints(polygons[index].getPath());
            }
            geofence = { ...geofence, points };

            geofences.splice(index, 1, geofence);

            value = { ...value, geofences: geofences };
            this.onChange(value);
        }
    };

    onChangeScope = () => {};

    onNameChange = (event: any, index: number) => {
        let { value } = this.props;
        let geofences;
        let geofence;
        if (value) {
            geofences = value.geofences;
            geofence = geofences[index];
            geofence = { ...geofence, name: event.target.value };

            geofences.splice(index, 1, geofence);

            value = { ...value, geofences: geofences };
            this.onChange(value);
        }
    };

    getPoints = (path: any) => {
        return path
            .map((point: any) => {
                return point.lng + ',' + point.lat;
            })
            .join(';');
    };

    addPolygon = () => {
        const { AMap, map, centerPosition } = this.state;
        const { value } = this.props;
        if (value && value.geofences && value.geofences.length >= 10) {
            AntMessage.warning('仅支持最多配置10个自定义范围');
            return;
        }
        if (AMap && map && centerPosition) {
            const path = [
                centerPosition.offset(-1500, 1500),
                centerPosition.offset(1500, 1500),
                centerPosition.offset(1500, -1500),
                centerPosition.offset(-1500, -1500),
            ];
            const points = this.getPoints(path);
            let geofences = value.geofences;
            geofences.push({
                name: DEFAULTNAME,
                points,
            });
            value.geofences = geofences;
            this.onChange(value);
            setTimeout(() => {
                this.initGeofrences(AMap, map);
            }, 1000);
        }
    };

    deletePolygon = (index: number) => {
        let { value } = this.props;
        const { AMap, map } = this.state;
        if (value && map) {
            const newGeofences = value.geofences.slice();
            newGeofences.splice(index, 1);
            value.geofences = newGeofences;
            this.onChange(value);
            setTimeout(() => {
                map.clearMap();
                this.initGeofrences(AMap, map);
            }, 1000);
        }
    };

    render() {
        const { value } = this.props;

        const geofences = value && value.geofences ? value.geofences : [];
        const scope = value && value.scope ? value.scope : DEFAULTSCOPE;
        return (
            <div className="geofences">
                <Radio.Group onChange={this.onChangeScope} value={scope}>
                    <Radio value={'CUSTOM'}>自定义配送范围</Radio>
                </Radio.Group>
                <div className="scope-tip">
                    可以自定义半径5公里内的区域,收货地址在配送范围外的买家,不可以选择下单
                </div>
                <div className="geofences-wrap">
                    <div className="map-container" id="mapContainer"></div>

                    {geofences && geofences.length > 0 && (
                        <div className="setting-wrap">
                            <div className="setting-geofences-wrap">
                                {geofences.map((geofence, index) => {
                                    return (
                                        <Checkbox key={index} checked>
                                            <Input
                                                onChange={(e) => {
                                                    this.onNameChange(e, index);
                                                }}
                                                style={{ width: 145 }}
                                                value={geofence.name}
                                                maxLength={10}
                                            />
                                            {index !== 0 && (
                                                <span
                                                    className="setting-delete"
                                                    onClick={this.deletePolygon.bind(this, index)}
                                                >
                                                    {services.language.getText('common.delete')}
                                                </span>
                                            )}
                                        </Checkbox>
                                    );
                                })}
                            </div>
                            <Button type="default" className="add-btn" onClick={this.addPolygon}>
                                添加配送区域
                            </Button>
                        </div>
                    )}
                </div>
            </div>
        );
    }
}

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

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

相关文章

深圳合规新动向,这个关键环节要做好

随着全球商业环境的日益复杂化&#xff0c;企业合规管理已成为维护公司稳健运营和市场竞争力的核心要素。特别是对于位于创新前沿的深圳市&#xff0c;有效的合规管理系统不仅是满足法律和监管要求的必须&#xff0c;更是企业可持续发展的关键。 深圳市在全国率先探索并成功实…

卡尔曼滤波Q和R怎么调

卡尔曼滤波器是一种有效的估计算法&#xff0c;主要用于在存在噪声的环境中估计动态系统的状态。它通过结合预测模型&#xff08;系统动态&#xff09;和观测数据&#xff08;包括噪声&#xff09;来实现这一点。在卡尔曼滤波中&#xff0c;调整过程噪声协方差矩阵 ( Q ) 和测量…

uboot run命令基本使用

run 命令可以用于运行环境变量的中定义的命令,run bootcmd 可以运行bootcmd中启动命令 作用:可以运行我们自定义的环境变量 include/command.h common/cli.c /*** board_run_command() - Fallback function to execute a command** When no command line features are enabled …

自然语言处理学习--3

对自然语言处理领域相关文献进行梳理和总结&#xff0c;对学习的文献进行梳理和学习记录。希望和感兴趣的小伙伴们一起学习。欢迎大家在评论区进行学习交流&#xff01; 论文&#xff1a;《ChineseBERT: Chinese Pretraining Enhanced by Glyph and Pinyin Information》 下面…

软件确认测试和系统测试包括哪些测试内容?有什么区别?

一、软件确认测试 软件确认测试&#xff0c;顾名思义&#xff0c;是为了确认软件的正确性和完整性而进行的测试过程。它旨在验证软件是否符合用户需求和软件开发规范。测试内容包括&#xff1a; 1、功能确认&#xff1a;通过对软件各项功能进行测试&#xff0c;验证其是否按照…

商用车水箱浮球液位开关

商用车水箱浮球液位开关概览 商用车水箱浮球液位开关是一种用于监测商用车辆水箱液位的设备&#xff0c;它可以有效地控制和监控水箱中的水位&#xff0c;确保车辆的正常运作。这种液位开关通常安装在水箱内部&#xff0c;通过浮球和磁性原理来感知液位的变化&#xff0c;并通…

AI墓地:738个倒闭AI项目的启示

近年来&#xff0c;人工智能技术迅猛发展&#xff0c;然而&#xff0c;不少AI项目却在市场上悄然消失。根据AI工具聚合网站“DANG”的统计&#xff0c;截至2024年6月&#xff0c;共有738个AI项目停运或停止维护。本文将探讨这些AI项目失败的原因&#xff0c;并分析当前AI初创企…

商务视频推广打造有吸引力的7个秘诀-华媒舍

商务视频推广是现代企业发展的重要工具&#xff0c;它能够帮助企业吸引更多的目标客户&#xff0c;提升品牌知名度&#xff0c;增加销售量。但是&#xff0c;如何打造一部有吸引力的商务视频推广呢&#xff1f;本文将为您介绍7个秘诀&#xff0c;帮助您在商务视频推广中取得成功…

【Unity navmeshaggent 组件】

【Unity navmeshaggent 组件】 组件概述&#xff1a; NavMeshAgent是Unity AI系统中的一个组件&#xff0c;它允许游戏对象&#xff08;通常是一个角色或AI&#xff09;在导航网格&#xff08;NavMesh&#xff09;上自动寻路。 组件属性&#xff1a; Radius&#xff1a;导航…

100个名人的家,娄艺潇的家:大美国色,浪漫栖居

冠珠瓷砖「100个名人的家」&#xff0c;大美筑家&#xff0c;中国冠珠2024大美筑家之旅&#xff0c;冠珠瓷砖「100个名人的家」&#xff0c;探索中国人的烟火浪漫与美学追求。从中国家文化、人文居所、人生底蕴层面&#xff0c;发掘大美人居的故事&#xff0c;以中国瓷砖、空间…

无人机测绘需要注意什么?

无人机测绘是一项高精度的测量工作&#xff0c;需要注意以下四点&#xff1a; 一、作业前准备&#xff1a;沟通相关事宜&#xff0c;现场勘查&#xff0c;飞行环境检查等&#xff1b; 二、航线规划与像控点布设&#xff1a;航线规划是任务规划的核心内容&#xff0c;需要综合…

工业智能网关在现代工业生产中的重要性-天拓四方

工业智能网关是一款具备挖掘工业设备数据并接入到自主开发的云平台的智能嵌入式网络设备。它具备数据采集、协议解析、边缘计算&#xff0c;以及4G/5G/WiFi数据传输等功能&#xff0c;并能接入工业云平台。这种网关不仅支持采集PLC、传感器、仪器仪表和各种控制器&#xff0c;还…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(二十一)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 31 节&#xff09; P31《30.数据持久化-关系型数据库》 上一节中学习了使用用户首选项的方式实现数据持久化&#xff0c;但用户首…

航空数据管控系统-①项目准备阶段:任务2:项目技术预研(技术架构)

任务描述 掌握项目的总体功能&#xff0c;及实现流程。预习项目中所使用到的技术和知识点。 任务指导 一、项目效果展示 图1-数据统计大屏页面 图2-航空实时监控页面 二、项目架构 1、总体架构&#xff1a; 2、技术架构 技术清单&#xff1a; 功能 组件 说明 消息中间件…

用增之Facebook(二)

事件上报&#xff1a; SDK集成参考上一篇文章&#xff0c;代码的调用就一个方法 AppEventsLogger mLogger AppEventsLogger.newLogger(context); 例如&#xff0c;普通事件上传 mLogger.logEvent(“event_name”, bundle); 支付事件比较特殊 Currency curr Currency.getIns…

猫咖老板教你一招解决猫浮毛问题,质量好的猫用空气净化器分享

作为一名猫咖店老板&#xff0c;我经常被朋友问到关于宠物空气净化器的各种问题。有人认为这是个神器&#xff0c;而有人则认为这完全是花钱买智商税。其实我刚开始对购买宠物空气净化器也持怀疑态度&#xff0c;心想这么多钱花下去真的有效吗&#xff1f;但使用后&#xff0c;…

针对SVN、GIT版本管理工具进行源代码加密保护

针对SVN、GIT版本管理工具进行源代码加密保护 在软件开发过程中&#xff0c;版本管理工具如SVN和GIT是不可或缺的组成部分&#xff0c;它们帮助团队管理源代码的变更和版本。然而&#xff0c;这些工具也面临着源代码泄露的安全风险。如果不针对数据进行加密保护&#xff0c;很…

qt QTreeView的简单使用(多级子节点)

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);setWindowTitle("QTreeView的简单使用");model new QStandardItemModel;model->setHorizontalHeaderLabels(QStringList() << "left&q…

元宇宙虚拟实景展馆树立客户对企业的信任和好感

在数字化浪潮的推动下&#xff0c;企业迎来了前所未有的营销新机遇——3D数字展厅。3D数字展厅作为现代营销中的新型工具&#xff0c;不仅是企业与客户互动、传递信息的桥梁&#xff0c;更是企业展示实力、彰显品牌魅力的舞台。 辽宁3D数字展厅制作以其独特的设计理念和先进的制…

航空数据管控系统-①项目准备阶段:任务1:项目需求描述

任务描述 从用户的角度阐述项目的开发背景、使用范围及功能需求&#xff0c;从而指导学生独立完成项目的设计与开发。 任务指导 目录 标题 内容 备注 1. 项目概述 1.1 项目背景介绍 &#xff08;1&#xff09;说明产品是什么&#xff0c;什么用途 &#xff08;2&#xff…