HarmonyOS 5.0应用开发——鸿蒙接入高德地图实现POI搜索
【高心星出品】
文章目录
- 鸿蒙接入高德地图实现POI搜索
- 运行结果:
- 准备地图
- 编写ArkUI布局来加载HTML地图
鸿蒙接入高德地图实现POI搜索
在当今数字化时代,地图应用已成为移动设备中不可或缺的一部分。随着鸿蒙系统的日益普及,如何在鸿蒙应用中接入高德地图并实现POI(兴趣点)检索功能,成为了众多开发者关注的焦点。本文将详细介绍这一过程,帮助开发者快速上手,为用户打造更优质的地图体验。
鸿蒙系统作为华为自主研发的分布式操作系统,具有高性能、低功耗等诸多优势,为智能设备提供了强大的支持。而高德地图凭借其丰富的数据资源、精准的定位功能以及多样化的地图服务,在国内地图应用领域占据重要地位。将鸿蒙与高德地图相结合,能够充分发挥双方的优势,为用户提供更加便捷、高效的地图导航和POI检索服务。
但是目前高德地图API暂不支持HarmonyOS5.0版本,需要使用鸿蒙的Web组件加载JS版高德地图。
运行结果:
准备地图
首先需要注册高德地图开发者,创建应用:https://lbs.amap.com/api/javascript-api-v2/prerequisites
准备一个基础地图。
HTML代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta
name="viewport"
content="initial-scale=1.0, user-scalable=no, width=device-width"
/>
<title>HELLO,AMAP!</title>
<style>
html,
body,
#container {
width: 100%;
height: 100%;
}
</style>
<style type="text/css">
#panel {
position: absolute;
max-height: 90%;
height:300px;
overflow-y: auto;
top: 50px;
right: 10px;
width: 180px;
}
.amap_lib_placeSearch .poibox .poi-title{
font-size:12px;
}
.amap_lib_placeSearch .poibox .poi-info p{
font-size:10px;
}
#search {
position: absolute;
background-color: transparent;
max-height: 90%;
overflow-y: auto;
top: 20px;
right: 10px;
width: 180px;
}
#search_input{
width:120px;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="panel"></div>
<div id="search">
<input id="search_input" type="text" placeholder="搜索地址">
<input id="search_sub" type="submit" value="搜索" onclick="search()">
</div>
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode: "210560c7b915b95686d9baa8b12d5a83",
};
</script>
<script src="https://webapi.amap.com/loader.js"></script>
<script type="text/javascript">
var map
AMapLoader.load({
key: "d7b81d72864f222e583d2283493cdd58", //申请好的Web端开发者 Key,调用 load 时必填
version: "2.0", //指定要加载的 JS API 的版本,缺省时默认为 1.4.15
})
.then((AMap) => {
map = new AMap.Map("container",{
zoom:10,
center: [118.832028,31.875796], //地图中心点
});
//异步加载控件
AMap.plugin('AMap.ToolBar',function(){
var toolbar = new AMap.ToolBar(); //缩放工具条实例化
map.addControl(toolbar); //添加控件
});
//异步加载控件
AMap.plugin('AMap.Scale',function(){
var scale = new AMap.Scale()
map.addControl(scale); //添加控件
});
})
.catch((e) => {
console.error(e); //加载错误提示
});
function search()
{
// 获取输入框元素
var inputElement = document.getElementById('search_input');
// 获取输入框中的文本内容
var searchText = inputElement.value;
console.log(searchText); // 在控制台输出文本内容
searchplace(searchText)
}
function searchplace(addr){
AMap.plugin(["AMap.PlaceSearch"], function () {
const placeSearch = new AMap.PlaceSearch({
pageSize: 5, //单页显示结果条数
pageIndex: 1, //页码
<!-- city: "江苏", //兴趣点城市-->
<!-- citylimit: true, //是否强制限制在设置的城市内搜索-->
selectFirst:true,
map: map, //展现结果的地图实例
panel: "panel", //参数值为你页面定义容器的 id 值<div id="my-panel"></div>,结果列表将在此容器中进行展示。
autoFitView: true, //是否自动调整地图视野使绘制的 Marker 点都处于视口的可见范围
});
placeSearch.on('selectChanged', function(e) {
console.log(JSON.stringify(e.selected.data))
postStringToApp(JSON.stringify(e.selected.data))
});
placeSearch.search(addr);
});
}
//-------------------地图展示很poi检索js代码----------------------------------
//--------------------------------与arkts通信代码--------------------------
var h5Port;
window.addEventListener('message', function(event) {
if (event.data == 'initport') {
if(event.ports[0] != null) {
h5Port = event.ports[0]; // 1. 保存从ets侧发送过来的端口
h5Port.onmessage = function(event) {
// 2. 接收ets侧发送过来的消息.
var result = event.data;
console.log('arkts发来的消息: '+result)
}
h5Port.onmessageerror = (event) => {
console.error(`发送了错误信息: ${event}`);
};
}
}
})
// 使用h5Port往ets侧发送String类型的消息.
function postStringToApp(str) {
if (h5Port) {
h5Port.postMessage(str);
} else {
console.error("In html h5port is null, please init first");
}
}
</script>
</body>
</html>
除了展示地图,还有与ArkTS通信的过程:
HTML网页会接收到ArkTS第一次发送的端口号,通过该端口号建立通道,后面就可以通过该端口号收发消息。
var h5Port;
window.addEventListener('message', function(event) {
if (event.data == 'initport') {
if(event.ports[0] != null) {
h5Port = event.ports[0]; // 1. 保存从ets侧发送过来的端口
h5Port.onmessage = function(event) {
// 2. 接收ets侧发送过来的消息.
var result = event.data;
console.log('arkts发来的消息: '+result)
}
h5Port.onmessageerror = (event) => {
console.error(`发送了错误信息: ${event}`);
};
}
}
})
// 使用h5Port往ets侧发送String类型的消息.
function postStringToApp(str) {
if (h5Port) {
h5Port.postMessage(str);
} else {
console.error("In html h5port is null, please init first");
}
}
编写ArkUI布局来加载HTML地图
加入权限
由于加载的地图需要使用网络权限,需要早module.json5中加入INTENET权限。
"module": {
'requestPermissions': [{
"name": "ohos.permission.INTERNET"
}],
....
加载地图
需要将离线的html地图放入项目的rawfile资源中。
编写ArkTS代码
这里需要在web组件加载结束后,与离线html建立通道收发消息。
import { webview } from '@kit.ArkWeb';
import { Addr } from '../../model/Addr';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
@State addrname:string=''
@State addr:string=''
private ports:webview.WebMessagePort[]=[]
private port:webview.WebMessagePort|null=null
private controller:WebviewController=new webview.WebviewController()
build() {
Column(){
Row({space:10}){
Text('地点名称:')
TextInput({text:this.addrname}).enabled(false)
.layoutWeight(1)
}.width('100%')
.padding(10)
Row({space:10}){
Text('详细地址:')
TextInput({text:this.addr}).enabled(false)
.layoutWeight(1)
}.width('100%')
.padding(10)
Web({src:$rawfile('poijiansuo.html'),controller:this.controller})
.javaScriptAccess(true)
.imageAccess(true)
.zoomAccess(true)
.margin({top:10})
.onPageEnd(()=>{
// 创建web的通道端口号
this.ports= this.controller.createWebMessagePorts()
console.log('gxxt ',JSON.stringify(this.ports))
// 将第二个端口号发送给html,做为html发送和接受arkts信息的端口号
this.controller.postMessage('initport',[this.ports[1]],'*')
//第一个端口号留给自己,作为发送和接受html信息的端口号
this.port=this.ports[0]
this.port.onMessageEventExt((result)=>{
// 接受html的结果
console.log('gxxt',JSON.stringify(result))
let data= result.getString()
let jsondata=JSON.parse(data) as Addr
this.addrname=jsondata.name
this.addr=jsondata.pname+jsondata.cityname+jsondata.adname+jsondata.address
})
})
}
.height('100%')
.width('100%')
}
}
当从地图搜索某个POI地点后,点击列表中的搜索结果,就会将具体地址信息发送给ArkTS端,然后在鸿蒙端进行解析。
Addr接口
/**
*作者:gxx
*时间:2025/2/21 16:43
*功能:
**/
export interface Addr {
"id": string
"name":string
"type":string
"location": number[],
"address":string
"tel":string
"distance":string|null
"shopinfo":string
"website":string
"pcode":string
"citycode":string
"adcode":string
"postcode":string
"pname":string
"cityname":string
"adname":string
"email":string
"photos": photos[]
"entr_location": number[]
"exit_location":string|null
"groupbuy":boolean
"discount":boolean
"indoor_map":boolean
"_idx":number
"index":number
}
interface photos
{
"title":string
"url":string
}