Angular封装高德地图组件实现输入框搜索,地图点击选地点

Angular封装高德地图组件实现输入框搜索,地图点击选地点(Angular17版本)

话不多说直接上代码

创建一个独立组件
在这里插入图片描述
html代码:

<div style="position: relative;"><input #searchInput nz-input placeholder="请输入地址"/><div #mapContainer style="width: 100%;height: 350px;"></div>
</div>

样式less

@import "src/styles/themes/mixin";.themeMixin({:host {position: relative;.toolbar {z-index: 9999;top: 8px;right: 8px;width: 200px;}}
});

ts代码:

import {AfterViewInit,Component,ElementRef,EventEmitter,Input,OnInit,Output, SimpleChanges,ViewChild
} from '@angular/core';
import {Observable, Observer, Subject} from "rxjs";
import {getPointsCenter} from "../../../util/gis";
import {NzInputDirective} from "ng-zorro-antd/input";
@Component({selector: 'app-site-pick',standalone: true,imports: [NzInputDirective],templateUrl: './site-pick.component.html',styleUrl: './site-pick.component.less'
})
export class SitePickComponent implements OnInit, AfterViewInit{@ViewChild('mapContainer', {static: false}) mapContainer: ElementRef@ViewChild('searchInput', {static: false}) searchInput: ElementRef@Output("inputChange") inputChange = new EventEmitter<{ lonlat: any, siteName: any, adCode: any }>();@Input() lonlat: string;@Input() locationName: string;@Input("boundary") boundary: stringmap: any;overlays: any[] = [];searchAdCode = '010'defaultCenter = [116.397755, 39.903179]currentMarker: any; // 用于存储当前标记的引用drawMapEvent = new Subject()mapLoaded = false; // 标志位,判断地图是否已加载private mapLoadSubject = new Subject<void>(); // 用于触发地图加载完成事件ngOnInit(): void {this.drawMapEvent.subscribe(next => {this.currentPosition().subscribe(center => {this.addSearchPlugin();});});}addSearchPlugin(): void {const placeSearch = new window['AMap'].PlaceSearch({map: this.map,city: this.searchAdCode});const auto = new window['AMap'].Autocomplete({input: this.searchInput.nativeElement,city: this.searchAdCode});window['AMap'].Event.addListener(auto, "select", (e) => {placeSearch.search(e.poi.name, (status, result) => {if (status === 'complete' && result.info === 'OK' && result.poiList.pois.length > 0) {const poi = result.poiList.pois[0];placeSearch.getDetails(poi.id, (detailStatus, detailResult) => {if (detailStatus === 'complete' && detailResult.poiList.pois.length > 0) {const detailedPoi = detailResult.poiList.pois[0];const adCode = [detailedPoi.pname,detailedPoi.cityname,detailedPoi.adname].filter(ac => ac);if (adCode.length === 2) {adCode.splice(1, 0, adCode[0]);}const adCodeStr = adCode.join(',');const location = detailedPoi.location;const siteName = detailedPoi.name;const lonlat = location.lng + ',' + location.lat;this.inputChange.emit({ lonlat: lonlat, siteName: siteName, adCode: adCodeStr });}});}});});}currentPosition(): Observable<any> {return new Observable<any>((observer: Observer<any>) => {new window['AMap'].Geolocation({enableHighAccuracy: false,timeout: 5000,offset: [10, 20],zoomToAccuracy: true,position: 'RB'}).getCityInfo((status, result) => {if (status == 'complete') {if (this.boundary && typeof this.boundary === 'string') {try {const center = getPointsCenter(this.boundary.split(';'));observer.next(center);} catch (e) {observer.next(this.defaultCenter);}} else {observer.next(result.position);this.searchAdCode = result.adcode;this.addSearchPlugin();}} else {console.error(result, 'Geolocation');observer.next(this.defaultCenter);}});});}ngAfterViewInit(): void {setTimeout(() => {this.map = new window['AMap'].Map(this.mapContainer.nativeElement, {resizeEnable: true,zoom: 14});this.map.on('click', (e) => {const lonlat = e.lnglat.getLng() + ',' + e.lnglat.getLat();this.resolveLocation(lonlat);});this.map.on('complete', () => {this.mapLoaded = true; // 地图加载完成this.mapLoadSubject.next(); // 触发地图加载完成事件this.initMarker();});this.drawMapEvent.next(null);}, 0);}initMarker(): void {if (!this.map) {console.error('地图尚未加载完成');return;}if (this.currentMarker) {this.map.remove(this.currentMarker);}if (this.lonlat) {const [lon, lat] = this.lonlat.split(',').map(Number);const position = new window['AMap'].LngLat(lon, lat);this.currentMarker = new window['AMap'].Marker({map: this.map,position: position});}}resolveLocation(lonlat: string): void {const [lng, lat] = lonlat.split(',').map(Number);const position = new window['AMap'].LngLat(lng, lat);const geocoder = new window['AMap'].Geocoder();geocoder.getAddress(position, (status, result) => {if (status === 'complete' && result.regeocode) {const address = result.regeocode.formattedAddress;const addressComponent = result.regeocode.addressComponent;const adCode = [addressComponent.province, addressComponent.city, addressComponent.district].map(ac => ac && typeof ac === 'object' ? ac.adcode : ac).filter(ac => ac);if (adCode.length === 2) {adCode.splice(1, 0, adCode[0]);}const adCodeStr = adCode.join(',');this.searchInput.nativeElement.value = address;this.inputChange.emit({ lonlat: lonlat, siteName: address, adCode: adCodeStr });} else {console.error('根据经纬度获取地址失败:', result);}});this.initMarker();}updateMapLocation(): Promise<void> {return new Promise((resolve, reject) => {if (!this.map) {console.error('地图尚未加载完成');return reject('地图尚未加载完成');}const [lon, lat] = this.lonlat.split(',').map(Number);const position = new window['AMap'].LngLat(lon, lat);if (this.currentMarker) {this.currentMarker.setPosition(position);} else {this.currentMarker = new window['AMap'].Marker({map: this.map,position: position});}this.map.setCenter([lon, lat]);resolve();});}getAddressFromLonLat(): void {const [lng, lat] = this.lonlat.split(',').map(Number);const geocoder = new window['AMap'].Geocoder();const position = new window['AMap'].LngLat(lng, lat);geocoder.getAddress(position, (status, result) => {if (status === 'complete' && result.regeocode) {const address = result.regeocode.formattedAddress;const addressComponent = result.regeocode.addressComponent;const adCode = [addressComponent.province, addressComponent.city, addressComponent.district].map(ac => ac && typeof ac === 'object' ? ac.adcode : ac).filter(ac => ac);if (adCode.length === 2) {adCode.splice(1, 0, adCode[0]);}const adCodeStr = adCode.join(',');this.searchInput.nativeElement.value = address;this.inputChange.emit({ lonlat: this.lonlat, siteName: address, adCode: adCodeStr });} else {console.error('根据经纬度获取地址失败:', result);}});}ngOnChanges(changes: SimpleChanges): void {if (changes['lonlat'] && this.lonlat) {if (this.mapLoaded) {this.updateMapLocation().then(() => {this.getAddressFromLonLat(); //根据 lonlat 获取地名});} else {this.mapLoadSubject.subscribe(() => { // 订阅地图加载完成事件this.updateMapLocation().then(() => {this.getAddressFromLonLat(); //根据 lonlat 获取地名});});}}}
}

如果 this.drawMapEvent.next(null); 报错改成 this.drawMapEvent.next();即可 因为我引入的 rxjs@7.5.7,

我这里对数据进行了处理:传出外部的数据类型:{ lonlat: any, siteName: any, adCode: any }

lonlat是经纬度,用",“逗号分隔
siteName是地点名
adCode是行政区code 用”,"分隔

使用

由于我做了表单的传值 可以直接在Form表单使用

      <nz-form-item><nz-form-label [nzSpan]="4" nzFor="lonlat">场地地址</nz-form-label><nz-form-control [nzSpan]="16" nzHasFeedback nzErrorTip="lonlat"><app-site-pick[lonlat]="form.get('lonlat').value"(inputChange)="inputChange($event)"></app-site-pick></nz-form-control></nz-form-item>
  /*** 地图input框选中返回lonlat+name* @param $event*/inputChange($event: any) {this.form.get('lonlat').setValue($event.lonlat);this.form.get('address').setValue($event.siteName)}

这里我只需要传入lonlat即可回显地点
inputChange()方法可以监听改变的数据,然后数据格式就自己处理吧
当然也可以通过[(ngModel)]进行绑定

还有最关键的高德地图的key,securityJsCode(自己去官网上注册)

在全局上配置写上:app.config.ts

export const appConfig: ApplicationConfig = {providers: [importProvidersFrom(HttpClientModule, NzMessageModule, NzDrawerModule, NzModalModule, NzNotificationModule,NzSwitchModule),provideAnimations(),provideRouter(appRoutes,withPreloading(PreloadSelective),withComponentInputBinding() // 开启路由参数绑定到组件的输入属性,ng16新增特性),// 初始化配置{provide: APP_INITIALIZER,useFactory: (bootstrap: BootstrapService) => () => {return bootstrap.init();},deps: [BootstrapService],multi: true,},// 国际化{provide: NZ_I18N,useFactory: (localId: string) => {switch (localId) {case 'en':return en_US;default:return zh_CN;}},deps: [LOCALE_ID]},{provide: HTTP_INTERCEPTORS, useClass: GlobalInterceptor, multi: true},{provide: AMAP_CONFIG, useValue: {securityJsCode: '9a2396b90169c48885aXXXXX6',key: 'de07643eaabaXXXXXX29284'}}]
};
{provide: AMAP_CONFIG, useValue: {securityJsCode: '9a2396b9XXX2c0c3eaf6fdb6',key: 'de07643XXXX5a5629284'}
}

这个就是

然后在你的BootstrapService 中添加启动 loadAMap

import {Inject, Injectable} from '@angular/core';
import {registerLocaleData} from "@angular/common";
import zh from "@angular/common/locales/zh";
import {NzIconService} from "ng-zorro-antd/icon";
import {load} from "@amap/amap-jsapi-loader";
import {AMAP_CONFIG, AMAPConfig} from "../config";
import {SkinService} from "./skin.service";@Injectable({providedIn: 'root'})
export class BootstrapService {constructor(private nzIconService: NzIconService,private skinService: SkinService,@Inject(AMAP_CONFIG) private amapConfig: AMAPConfig) {}init(): void {// 注册本地化语言包registerLocaleData(zh);// 注册icon// this.nzIconService.addIconLiteral('outline:clear', '')// 初始化设置主题this.skinService.loadTheme(this.skinService.localTheme()).then();// 加载地图this.loadAMap()}loadAMap(): void {window['_AMapSecurityConfig'] = {securityJsCode: this.amapConfig.securityJsCode, // 安全密钥};load({"key": this.amapConfig.key,"version": "2.0",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15"plugins": ['AMap.Geolocation','AMap.PolygonEditor','AMap.PlaceSearch','AMap.AutoComplete','AMap.Polyline','AMap.Geocoder'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等"AMapUI": {// 是否加载 AMapUI,缺省不加载"version": '1.1',// AMapUI 缺省 1.1"plugins": ['overlay/SimpleMarker'],},"Loca": { // 是否加载 Loca, 缺省不加载"version": '2.0'  // Loca 版本,缺省 1.3.2},}).then((AMap) => {window['AMap'] = AMap}).catch(e => {console.log(e);})}
}

成品展示:

在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何快速上手Python,成为一名数据分析师

如何快速上手Python&#xff0c;成为一名数据分析师 成为一名数据分析师需要掌握Python编程语言以及数据分析相关的知识和技能。以下是一些步骤和建议&#xff0c;帮助你快速上手Python并成为一名数据分析师&#xff1a; 学习Python基础知识&#xff1a;首先&#xff0c;你需要…

机器学习-聚类算法

1.有监督学习与无监督学习 有监督&#xff1a;在训练集中给的数据中有X和Y&#xff0c;根据这些数据训练出一组参数对预测集进行预测 无监督&#xff1a;在训练集中给的数据只有X没有Y&#xff0c;根据X数据找相似度参数来对预测集进行预测 2.数据间的相似度 2.1距离相似度…

前端 Web 与原生应用端 WebView 通信交互 - HarmonyOS Next

基于鸿蒙 HarmonyOS Next 与前端 Vue 通信交互相关小结; DevEco Studio NEXT Developer Preview2 Vue js 两端相互拟定好协议后,通过前端页面的点击事件,将所需的数据传输给原生移动端组件方法中,处理后将消息回传至前端. 根据官方文档的案例尝试,但没成功 ... 后经过几经尝试…

随笔——预处理详解

目录 前言预定义符号#define#define定义常量#define定义宏 带有副作用的宏参数宏替换的规则宏和函数的对比#和###运算符##运算符 命名约定#undef命令行定义条件编译头文件的包含包含方式嵌套包含 其他预处理指令完 前言 之前我们在《随笔——编译与链接》中对预处理作了大致的…

【ARM Cache 及 MMU 系列文章 6 -- Cache 寄存器 CTR_EL0 | CLIDR | CCSIDR | CSSELR 使用详解 1】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 Cache 常用寄存器Cache CSSELR 寄存器Cache CSSELR 使用场景Cache CSSELR 操作示例 Cache CLIDR 寄存器LoUU 介绍LoUU 使用 LoUIS 介绍CLIDR 使用 Cache CCSIDR 寄存器Cache CTR_EL0 C…

中科数安 |-公司办公透明加密系统,数据防泄漏软件

#数据防泄漏软件# 中科数安是一家专注于提供企业级数据防泄漏解决方案的公司&#xff0c;其办公透明加密系统是专为保护企业内部核心数据资料设计的。 PC地址&#xff1a;——www.weaem.com 该系统通过以下主要功能模块实现高效的安全防护&#xff1a; 文档透明加密&#xff1…

滴滴出行 大数据研发实习生【继任】

大数据研发实习生JD 职位描述 1、负责滴滴核心业务的数据建设&#xff0c;设计并打造适应滴滴一站式出行平台业务特点的数仓体系。 2、负责抽象核心业务流程&#xff0c;沉淀业务通用分析框架&#xff0c;开发数仓中间层和数据应用产品。 3、负责不断完善数据治理体系&#xff…

【数据结构】栈的应用

目录 0 引言 1 栈在括号匹配中的应用 2 栈在表达式求值中的应用 2.1 算数表达式 2.2 中缀表达式转后缀表达式 2.3 后缀表达式求值 3 栈在递归中的应用 3.1 栈在函数调用中的作用 3.2 栈在函数调用中的工作原理 4 总结 0 引言 栈&#xff08;Stack&#xff09;是一…

WPF视频学习-基础知识篇

1.简介WPF&#xff1a; C# 一套关于windows界面应用开发框架 2.WPF和winform的差别 &#xff0c;(WPF比较新) 创建新项目使用模板&#xff1a; WPF使用.xaml后缀&#xff0c;双击可查看操作界面和设置代码&#xff0c;其文件展开之后中有MainWindow.xaml.cs为程序交互逻辑。…

linux笔记8--安装软件

文章目录 1. PMS和软件安装的介绍2. 安装、更新、卸载安装更新ubuntu20.04更新镜像源&#xff1a; 卸载 3. 其他发行版4. 安装第三方软件5. 推荐 1. PMS和软件安装的介绍 PMS(package management system的简称)&#xff1a;包管理系统 作用&#xff1a;方便用户进行软件安装(也…

nginx mirror流量镜像详细介绍以及实战示例

nginx mirror流量镜像详细介绍以及实战示例 1.nginx mirror作用2.nginx安装3.修改配置3.1.nginx.conf3.2.conf.d目录下添加default.conf配置文件3.3.nginx配置注意事项3.3.nginx重启 4.测试 1.nginx mirror作用 为了便于排查问题&#xff0c;可能希望线上的请求能够同步到测试…

PyCharm QThread 设置断点不起作用

背景&#xff1a; 端午节回来上班第一天&#xff0c;不想干活&#xff0c;领导又再后面看着&#xff0c;突然想起一个有意思的问题&#xff0c;为啥我的程序在子进程QThread的子类里打的断点不好用呢&#xff1f;那就解决一下这个问题吧。 原因&#xff1a; 如果您的解释器上…

开发框架表单设计器办公效率高吗?

对于很多职场人来说&#xff0c;拥有一款可以提质、增效、降本的办公利器是大有裨益的。随着科技的进步和发展&#xff0c;低代码技术平台凭借可视化界面、易操作、好维护、高效率等多个优势特点&#xff0c;成为大众喜爱的办公利器。开发框架表单设计器是减少信息孤岛&#xf…

macbook本地部署 pyhive环境连接 hive用例

前言 公司的测试和生产环境中尚未提供基于Hive的客户端。若希望尝试操作Hive表&#xff0c;目前一个可行的方案是使用Python语言&#xff0c;通过借助pyhive库&#xff0c;您可以对Hive表进行各种操作。以下是一些示例记录供您参考。 一、pyhive是什么&#xff1f; PyHive是一…

从零到一建设数据中台(番外篇)- 数据中台UI欣赏

番外篇 - 数据中台 UI 欣赏 话不多说&#xff0c;直接上图。 数据目录的重要性&#xff1a; 数据目录是一种关键的信息管理工具&#xff0c;它为组织提供了一个全面的、集中化的数据资产视图。 它不仅记录了数据的存储位置&#xff0c;还详细描述了数据的结构、内容、来源、使…

细说ARM MCU的串口接收数据的实现过程

目录 一、硬件及工程 1、硬件 2、软件目的 3、创建.ioc工程 二、 代码修改 1、串口初始化函数MX_USART2_UART_Init() &#xff08;1&#xff09;MX_USART2_UART_Init()串口参数初始化函数 &#xff08;2&#xff09;HAL_UART_MspInit()串口功能模块初始化函数 2、串口…

批量申请SSL证书如何做到既方便成本又最低

假如您手头拥有1千个域名&#xff0c;并且打算为每一个域名搭建网站&#xff0c;那么在当前的网络环境下&#xff0c;您必须确保这些网站通过https的方式提供服务。这意味着&#xff0c;您将为每一个域名申请SSL证书&#xff0c;以确保网站数据传输的安全性和可信度。那么&…

面试-NLP八股文

机器学习 交叉熵损失&#xff1a; L − ( y l o g ( y ^ ) ( 1 − y ) l o g ( 1 − ( y ^ ) ) L-(ylog(\hat{y}) (1-y)log(1-(\hat{y})) L−(ylog(y^​)(1−y)log(1−(y^​))均方误差&#xff1a; L 1 n ∑ i 1 n ( y i − y ^ i ) 2 L \frac{1}{n}\sum\limits_{i1}^{n}…

【ai】openai-quickstart 配置pycharm工程

之前都是本地执行脚本【AI】指定python3.10安装Jupyter Lab环境为:C:\Users\zhangbin\AppData\Local\Programs\Python\Python310 参考之前创建的python工程 使用的是局部的私有的虚拟环境 pycharm给出的解释器 直接使用现有的,不new了 可以选择3.10 :可以选虚拟的:

Rust-02-变量与可变性

在Rust中&#xff0c;变量和可变性是两个重要的概念。 变量&#xff1a;变量是用于存储数据的标识符。在Rust中&#xff0c;变量需要声明其类型&#xff0c;例如&#xff1a; let x: i32 5; // 声明一个名为x的变量&#xff0c;类型为i32&#xff08;整数&#xff09;&#…