赞
踩
因项目需要,在uniapp中集成使用腾讯地图,为了方便维护,希望通过一套代码实现H5和APP同时可用。H5显示相对简单,APP端比较麻烦,记录下实现过程
script标签使用renderjs,因为JavaScript Api需要调用DOM对象,APP需要使用renderjs技术,保证script运行在webview环境,才能调用DOM对象。
- <script lang="renderjs" module="test">
- </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>
下载腾讯官网的例子,改造成uniapp兼容的格式。有两种方式,
方式一:
将官网例子中 script 封装成一个个的function,定义在 vue文件的 methods 中,这样就可以直接调用。
方式二:
将官网例子中 script 代码全部拷贝到一个js文件中,再把需要调用的 function 通过 export 关键字导出,在vue文件中进行 import 调用。
腾讯官网例子都是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';
- // 自定义环状饼图 - 继承DOMOverlay
- function 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>
主要三个文件 DOMOverlay.js、loadJs.js、map.vue
一般来说先把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
- }
用来加载第三方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
- <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.js
- import {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运行效果图,与官网一致
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。