uniapp腾讯地图JavaScript Api,H5端和原生APP端可用

        因项目需要,在uniapp中集成使用腾讯地图,为了方便维护,希望通过一套代码实现H5和APP同时可用。H5显示相对简单,APP端比较麻烦,记录下实现过程

一、集成步骤

1.使用 renderjs

script标签使用renderjs,因为JavaScript Api需要调用DOM对象,APP需要使用renderjs技术,保证script运行在webview环境,才能调用DOM对象。

<script lang="renderjs" module="test">
</script>

2.引用地图script


导入腾讯地图JS脚本,因为腾讯地图js不是按照uniapp格式编写,所以不能直接import导入,需要包装成一个js插件,使用 Promise,js加载成功,调用resolve,js加载失败,调用reject。

创建loadJs.js 文件

function loadJs(src) {return new Promise((resolve,reject)=>{let script = document.createElement('script');script.type = "text/javascript";script.src= src;document.body.appendChild(script);script.onload = ()=>{resolve();}script.onerror = ()=>{reject();}}).catch((e) => {})
}export default loadJs


在页面中使用

<script lang="renderjs" module="test">import loadJs from "../../common/loadJs.js"export default {data() {return {}},mounted(){console.log('renderjs初始化完毕')loadJs('https://map.qq.com/api/gljs?v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77').then(()=>{// 加载成功,进行后续操作})},methods: {}}
</script>

3.修改js,兼容uniapp

下载腾讯官网的例子,改造成uniapp兼容的格式。有两种方式,

方式一:

将官网例子中 script 封装成一个个的function,定义在 vue文件的 methods 中,这样就可以直接调用。

方式二:

将官网例子中 script 代码全部拷贝到一个js文件中,再把需要调用的 function 通过 export 关键字导出,在vue文件中进行 import 调用。

4.修改监听事件

腾讯官网例子都是web端的,点击事件都是click,H5端运行需要改成touchend,否则点击无响应

Web端

svg.addEventListener('click', this.onClick); web端用click事件

H5端

svg.addEventListener('touchend', this.onClick); // H5端用touchend事件

二、示例

腾讯官网例子

以自定义覆盖物 -> DOMOverlay 为例,实操下

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>DOMOverlay</title>
</head>
<script charset="utf-8" src="https://map.qq.com/api/gljs?libraries=tools&v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77"></script>
<style type="text/css">html,body {height: 100%;margin: 0px;padding: 0px;}#container {width: 100%;height: 100%;}
</style><body onload="initMap()"><div id="container"></div><script>var SVG_NS = 'http://www.w3.org/2000/svg';// 自定义环状饼图 - 继承DOMOverlayfunction Donut(options) {TMap.DOMOverlay.call(this, options);}Donut.prototype = new TMap.DOMOverlay();// 初始化Donut.prototype.onInit = function(options) {this.position = options.position;this.data = options.data;this.minRadius = options.minRadius || 0;this.maxRadius = options.maxRadius || 50;};// 销毁时需解绑事件监听Donut.prototype.onDestroy = function() {if (this.onClick) {this.dom.removeEventListener(this.onClick);}};// 创建DOM元素,返回一个DOMElement,使用this.dom可以获取到这个元素Donut.prototype.createDOM = function() {let svg = document.createElementNS(SVG_NS, 'svg');svg.setAttribute('version', '1.1');svg.setAttribute('baseProfile', 'full');let r = this.maxRadius;svg.setAttribute('viewBox', [-r, -r, r * 2, r * 2].join(' '));svg.setAttribute('width', r * 2);svg.setAttribute('height', r * 2);svg.style.cssText = 'position:absolute;top:0px;left:0px;';let donut = createDonut(this.data, this.minRadius, this.maxRadius);svg.appendChild(donut);// click事件监听this.onClick = () => {// DOMOverlay继承自EventEmitter,可以使用emit触发事件this.emit('click');};// pc端注册click事件,移动端注册touchend事件svg.addEventListener('click', this.onClick);return svg;};// 更新DOM元素,在地图移动/缩放后执行Donut.prototype.updateDOM = function() {if (!this.map) {return;}// 经纬度坐标转容器像素坐标let pixel = this.map.projectToContainer(this.position);// 使饼图中心点对齐经纬度坐标点let left = pixel.getX() - this.dom.clientWidth / 2 + 'px';let top = pixel.getY() - this.dom.clientHeight / 2 + 'px';this.dom.style.transform = `translate(${left}, ${top})`;};// 使用SVG创建环状饼图function createDonut(data, minRadius, maxRadius) {const colorList = ['#7AF4FF','#67D7FF','#52B5FF','#295BFF'];let sum = data.reduce((prev, curr) => prev + curr, 0);let angle = 0;let group = document.createElementNS(SVG_NS, "g");data.forEach((d, i) => {let delta = d / sum * Math.PI * 2;color = colorList[i],r = maxRadius,startAngle = angle,endAngle = angle + delta;angle += delta;// 对每个数据创建一个扇形let fanShape = document.createElementNS(SVG_NS, 'path');fanShape.setAttribute('style', `fill: ${color};`);fanShape.setAttribute('d', ['M0 0',`L${r * Math.sin(startAngle)} ${-r * Math.cos(startAngle)}`,`A${r} ${r} 0 ${delta > Math.PI ? 1 : 0} 1 ${r * Math.sin(endAngle)} ${-r * Math.cos(endAngle)}`,].join(' ') + ' z');group.appendChild(fanShape);});// 在中心创建一个圆形let circleShape = document.createElementNS(SVG_NS, 'circle');circleShape.setAttribute('style', 'fill: #FFFFFF');circleShape.setAttribute('cx', 0);circleShape.setAttribute('cy', 0);circleShape.setAttribute('r', minRadius);group.appendChild(circleShape);// 绘制文字let textShape = document.createElementNS(SVG_NS, 'text');textShape.setAttribute('x', 0);textShape.setAttribute('y', '0.3em');textShape.setAttribute('text-anchor', 'middle');textShape.innerHTML = sum;group.appendChild(textShape);return group;}window.Donut = Donut;</script><script type="text/javascript">var map;function initMap() {// 初始化地图map = new TMap.Map("container", {zoom:12, // 设置地图缩放级别center: new TMap.LatLng(39.984104, 116.307503) // 设置地图中心点坐标});let donutList = [new Donut({map,position: new TMap.LatLng(39.96030543872138, 116.25809083213608),data: [12, 24],minRadius: 13,maxRadius: 20}),new Donut({map,position: new TMap.LatLng(39.9986945980902, 116.33598362780685),data: [23, 99, 101, 400],minRadius: 25,maxRadius: 35}),new Donut({map,position: new TMap.LatLng(40.02906301748584, 116.25499991104516),data: [18, 41, 50],minRadius: 20,maxRadius: 28})];donutList.forEach((donut, index) => {donut.on('click', () => {console.log(`第${index}个环形图被点击,位置为${donut.position}`);});});}</script>
</body></html>

适配后uniapp代码

主要三个文件 DOMOverlay.js、loadJs.js、map.vue

DOMOverlay.js 

一般来说先把script 全部复制到一个单独js文件,然后直接运行,运气好直接正常使用,运气不好就哪里报错改哪里,DOMOverlay.js文件修改过我都加了注释“适配uniapp修改过的”

var SVG_NS = 'http://www.w3.org/2000/svg';
// 自定义环状饼图 - 继承DOMOverlay
function Donut(options) {TMap.DOMOverlay.call(this, options);
}/** * ----------------适配uniapp修改过的----------------* * 因为 TMap 对象依赖于 https://map.qq.com/api/gljs?v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77 * 所以要封装一个方法,在加载完依赖脚本后,再运行*/
function initDonut(){Donut.prototype = new TMap.DOMOverlay();// 初始化Donut.prototype.onInit = function(options) {this.position = options.position;this.data = options.data;this.minRadius = options.minRadius || 0;this.maxRadius = options.maxRadius || 50;};// 销毁时需解绑事件监听Donut.prototype.onDestroy = function() {if (this.onClick) {this.dom.removeEventListener(this.onClick);}};// 创建DOM元素,返回一个DOMElement,使用this.dom可以获取到这个元素Donut.prototype.createDOM = function() {let svg = document.createElementNS(SVG_NS, 'svg');svg.setAttribute('version', '1.1');svg.setAttribute('baseProfile', 'full');let r = this.maxRadius;svg.setAttribute('viewBox', [-r, -r, r * 2, r * 2].join(' '));svg.setAttribute('width', r * 2);svg.setAttribute('height', r * 2);svg.style.cssText = 'position:absolute;top:0px;left:0px;';let donut = createDonut(this.data, this.minRadius, this.maxRadius);svg.appendChild(donut);// click事件监听this.onClick = () => {// DOMOverlay继承自EventEmitter,可以使用emit触发事件this.emit('click');};// ----------------适配uniapp修改过的----------------// pc端注册click事件,移动端注册touchend事件// svg.addEventListener('click', this.onClick); web端用click事件svg.addEventListener('touchend', this.onClick); // H5端用touchend事件return svg;};// 更新DOM元素,在地图移动/缩放后执行Donut.prototype.updateDOM = function() {if (!this.map) {return;}// 经纬度坐标转容器像素坐标let pixel = this.map.projectToContainer(this.position);// 使饼图中心点对齐经纬度坐标点let left = pixel.getX() - this.dom.clientWidth / 2 + 'px';let top = pixel.getY() - this.dom.clientHeight / 2 + 'px';this.dom.style.transform = `translate(${left}, ${top})`;};
}// 使用SVG创建环状饼图
function createDonut(data, minRadius, maxRadius) {const colorList = ['#7AF4FF','#67D7FF','#52B5FF','#295BFF'];let sum = data.reduce((prev, curr) => prev + curr, 0);let angle = 0;let group = document.createElementNS(SVG_NS, "g");data.forEach((d, i) => {let delta = d / sum * Math.PI * 2;let color = colorList[i],r = maxRadius,startAngle = angle,endAngle = angle + delta;angle += delta;// 对每个数据创建一个扇形let fanShape = document.createElementNS(SVG_NS, 'path');fanShape.setAttribute('style', `fill: ${color};`);fanShape.setAttribute('d', ['M0 0',`L${r * Math.sin(startAngle)} ${-r * Math.cos(startAngle)}`,`A${r} ${r} 0 ${delta > Math.PI ? 1 : 0} 1 ${r * Math.sin(endAngle)} ${-r * Math.cos(endAngle)}`,].join(' ') + ' z');group.appendChild(fanShape);});// 在中心创建一个圆形let circleShape = document.createElementNS(SVG_NS, 'circle');circleShape.setAttribute('style', 'fill: #FFFFFF');circleShape.setAttribute('cx', 0);circleShape.setAttribute('cy', 0);circleShape.setAttribute('r', minRadius);group.appendChild(circleShape);// 绘制文字let textShape = document.createElementNS(SVG_NS, 'text');textShape.setAttribute('x', 0);textShape.setAttribute('y', '0.3em');textShape.setAttribute('text-anchor', 'middle');textShape.innerHTML = sum;group.appendChild(textShape);return group;
}window.Donut = Donut;var map;
function initMap() {// ----------------适配uniapp修改过的----------------// 调用封装后的initDount()initDonut()// 初始化地图map = new TMap.Map("mapContainer", {zoom:12, // 设置地图缩放级别center: new TMap.LatLng(39.984104, 116.307503) // 设置地图中心点坐标});let donutList = [new Donut({map,position: new TMap.LatLng(39.96030543872138, 116.25809083213608),data: [12, 24],minRadius: 13,maxRadius: 20}),new Donut({map,position: new TMap.LatLng(39.9986945980902, 116.33598362780685),data: [23, 99, 101, 400],minRadius: 25,maxRadius: 35}),new Donut({map,position: new TMap.LatLng(40.02906301748584, 116.25499991104516),data: [18, 41, 50],minRadius: 20,maxRadius: 28})];donutList.forEach((donut, index) => {donut.on('click', () => {console.log(`第${index}个环形图被点击,位置为${donut.position}`);alert(`第${index}个环形图被点击,位置为${donut.position}`)});});
}/*** ----------------适配uniapp修改过的----------------* 导出initMap方法*/ 
export {initMap
}
loadJs.js

用来加载第三方js

function loadJs(src) {return new Promise((resolve,reject)=>{let script = document.createElement('script');script.type = "text/javascript";script.src= src;document.body.appendChild(script);script.onload = ()=>{resolve();}script.onerror = ()=>{reject();}}).catch((e) => {})
}export default loadJs
map.vue
<template><view id="mapContainer" style="height: 100%;" @click="log"></view>
</template><script>export default {data() {return {}},mounted() {}}
</script><script lang="renderjs" module="test">import loadJs from "../../common/loadJs.js"// 导入适配后的 DOMOverlay.jsimport {initMap} from "../../common/DOMOverlay.js"export default {data() {return {}},mounted(){console.log("mounted") loadJs('https://map.qq.com/api/gljs?v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77').then(()=>{// 调用初始化地图方法initMap()})},methods: {}, created() {}}
</script><style></style>

三、适配效果

APP运行效果图,与官网一致

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

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

相关文章

一文了解LM317T的引脚介绍、参数解读

LM317T是一种线性稳压器件&#xff0c;它具有稳定输出电压的特性。LM317T可以通过调整其输出电阻来确保输出电压的稳定性&#xff0c;因此被广泛应用于各种电子设备中。 LM317T引脚图介绍 LM317T共有3个引脚&#xff0c;分别是&#xff1a; 输入引脚&#xff08;输入电压V_in&…

软件应用场景,物流货运配货单打印模板软件单据打印查询管理系统软件教程

软件应用场景&#xff0c;物流货运配货单打印模板软件单据打印查询管理系统软件教程 一、前言 以下软件以 佳易王物流快运单打印查询管理系统软件V17.1 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、打印模式可以分为 直打模式和套打模式 直打模…

MySQL-----多表操作

介绍 实际开发中&#xff0c;一个项目通常需要很多张表才能完成。例如:一个商城项目就需要分类表(category)、商品表(products)、订单表(orders)等多张表。且这些表的数据之间存在一定的关系&#xff0c;接下来我们将在单表的基础上&#xff0c;一起学习多表方面的知识。 一 多…

使用HiveMQ实现Android MQTT

MQTT官网&#xff1a;https://mqtt.org/ 百度Android MQTT&#xff0c;或者B站上搜索&#xff0c;发现大多使用https://github.com/eclipse/paho.mqtt.android&#xff0c;这是Eclipse的一个Android MQTT客户端实现库&#xff0c;但是我发现这个库在运行到高版本的手机上时报错…

Rust核心:【所有权】相关知识点

rust在内存资源管理上采用了&#xff08;先进优秀&#xff1f;算吗&#xff09;但特立独行的设计思路&#xff1a;所有权。这是rust的核心&#xff0c;贯穿在整个rust语言的方方面面&#xff0c;并以此为基点来重新思考和重构软件开发体系。 涉及到的概念点&#xff1a;借用&am…

使用Postman和JMeter进行signature签名

一、前言 ​ 有些接口的请求会带上sign&#xff08;签名&#xff09;进行请求&#xff0c;各接口对sign的签名内容、方式可能不一样&#xff0c;但一般都是从接口的入参中选择部分内容组成一个字符串&#xff0c;然后再进行签名操作, 将结果赋值给sign; 完整规范的接口文档都会…

Spring Boot与HikariCP:性能卓越的数据库连接池

点击下载《Spring Boot与HikariCP&#xff1a;性能卓越的数据库连接池》 1. 前言 本文将详细介绍Spring Boot中如何使用HikariCP作为数据库连接池&#xff0c;包括其工作原理、优势分析、配置步骤以及代码示例。通过本文&#xff0c;读者将能够轻松集成HikariCP到Spring Boot…

六、回归与聚类算法 - 模型保存与加载

目录 1、API 2、案例 欠拟合与过拟合线性回归的改进 - 岭回归分类算法&#xff1a;逻辑回归模型保存与加载无监督学习&#xff1a;K-means算法 1、API 2、案例

vue : 无法加载文件 C:\Program Files\nodejs\node_global\vue.ps1,因为在此系统上禁止运行脚本。

解决方法&#xff1a; 打开PowerShell&#xff0c;在命令框输入set-ExecutionPolicy RemoteSigned 在PowerShell中输入会出现如下图&#xff0c;输入y即可。

RabbitMQ 部署方式选择

部署模式 RabbitMQ支持多种部署模式&#xff0c;可以根据应用的需求和规模选择适合的模式。以下是一些常见的RabbitMQ部署模式&#xff1a; 单节点模式&#xff1a; 最简单的部署方式&#xff0c;所有的RabbitMQ组件&#xff08;消息存储、交换机、队列等&#xff09;都运行在…

第九节HarmonyOS 常用基础组件28-Select

1、描述 提供下拉选择菜单&#xff0c;可以让用户在多个选项之间选择。 2、接口 Select(options:Array<SelectOption>) 3、SelectOption对象说明 参数名 参数类型 必填 描述 value ResourceStr 是 下拉选项内容。 icon ResourceStr 否 下拉选项图标。 4…

【前端素材】推荐优质后台管理系统Sneat平台模板(附源码)

一、需求分析 后台管理系统是一种用于管理网站、应用程序或系统的工具&#xff0c;它通常作为一个独立的后台界面存在&#xff0c;供管理员或特定用户使用。下面详细分析后台管理系统的定义和功能&#xff1a; 1. 定义 后台管理系统是一个用于管理和控制网站、应用程序或系统…

浏览器录屏技术:探索网页内容的视觉记录之道

title: 浏览器录屏技术&#xff1a;探索网页内容的视觉记录之道 date: 2024/2/23 14:32:49 updated: 2024/2/23 14:32:49 tags: 浏览器录屏技术原理Web API应用场景用户体验在线教育产品演示 在当今数字化时代&#xff0c;浏览器录屏技术已经成为了一种强大的工具&#xff0c;…

​LeetCode解法汇总2583. 二叉树中的第 K 大层和

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一棵二叉树的根节点 root 和一个正整…

Microsoft 365自定义安装软件

如图&#xff0c;在安装类型的步骤的时候&#xff0c;可以勾选自己想要的软件&#xff08;而非一股脑儿的安装一大堆自己不需要的&#xff09;。

HTB pwn Dragon Army

逆向分析 程序使用了alloca函数扩大了栈区 此处可以泄露libc的地址 程序主要功能在下面 while ( 1 ){while ( 1 ){fflush(stdin);fflush(_bss_start);fprintf(_bss_start, "\n%sDragons: [%d/%d]%s\n\n", "\x1B[1;34m", v5, 13LL, "\x1B[1;37m"…

挑战30天学完Python:Day18 正则表达式

&#x1f4d8; Day 18 &#x1f389; 本系列为Python基础学习&#xff0c;原稿来源于 30-Days-Of-Python 英文项目&#xff0c;大奇主要是对其本地化翻译、逐条验证和补充&#xff0c;想通过30天完成正儿八经的系统化实践。此系列适合零基础同学&#xff0c;或仅了解Python一点…

测试开源C#人脸识别模块DlibDotNet

百度“C# 换脸”找到参考文献4&#xff0c;发现其中使用DlibDotNet检测并识别人脸&#xff08;之前主要用的是ViewFaceCore&#xff09;&#xff0c;DlibDotNet是Dlib的.net封装版本&#xff0c;后者为开源C工具包&#xff0c;支持机器学习算法、图像处理等算法以支撑各类高级应…

CVE-2023-44313 Apache ServiceComb Service-Center SSRF 漏洞研究

本次项目基于go语言&#xff08;本人不精通&#xff09;&#xff0c;虽不是java web框架了 &#xff0c;但搭建web服务的框架一些思想理念却是通用的&#xff0c;我们由此可以得到一些蛛丝马迹....... 目录 漏洞简介 漏洞分析 漏洞复现 漏洞简介 Apache ServiceComb Servi…

应用感知型网络性能管理

网络基础设施似乎日益复杂和先进&#xff0c;迫使网络管理员抛弃传统的管理方法。应用感知型网络性能管理是一种用于监控网络性能的新型整体方法&#xff0c;它为管理员提供了强大的 IT 资源管理功能。应用感知型网络性能管理为 IT 管理员带来了精细视图、动态资源分配、主动故…