当前位置:   article > 正文

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

uniapp使用腾讯地图

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

一、集成步骤

1.使用 renderjs

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

  1. <script lang="renderjs" module="test">
  2. </script>

2.引用地图script


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

创建loadJs.js 文件

  1. function loadJs(src) {
  2.   return new Promise((resolve,reject)=>{
  3.     let script = document.createElement('script');
  4.     script.type = "text/javascript";
  5.     script.src= src;
  6.     document.body.appendChild(script);
  7.       
  8.     script.onload = ()=>{
  9.       resolve();
  10.     }
  11.     script.onerror = ()=>{
  12.       reject();
  13.     }
  14.   }).catch((e) => {})
  15. }
  16.  
  17. export default loadJs


在页面中使用

  1. <script lang="renderjs" module="test">
  2.     import loadJs from "../../common/loadJs.js"
  3.     
  4.     export default {
  5.         data() {
  6.             return {
  7.                 
  8.             }
  9.         },
  10.         mounted(){
  11.             console.log('renderjs初始化完毕')
  12.             loadJs('https://map.qq.com/api/gljs?v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77').then(()=>{
  13.                 // 加载成功,进行后续操作
  14.             })
  15.         },
  16.          methods: {
  17.         }
  18.     }
  19. </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 为例,实操下

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>DOMOverlay</title>
  8. </head>
  9. <script charset="utf-8" src="https://map.qq.com/api/gljs?libraries=tools&v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77"></script>
  10. <style type="text/css">
  11. html,
  12. body {
  13. height: 100%;
  14. margin: 0px;
  15. padding: 0px;
  16. }
  17. #container {
  18. width: 100%;
  19. height: 100%;
  20. }
  21. </style>
  22. <body onload="initMap()">
  23. <div id="container"></div>
  24. <script>
  25. var SVG_NS = 'http://www.w3.org/2000/svg';
  26. // 自定义环状饼图 - 继承DOMOverlay
  27. function Donut(options) {
  28. TMap.DOMOverlay.call(this, options);
  29. }
  30. Donut.prototype = new TMap.DOMOverlay();
  31. // 初始化
  32. Donut.prototype.onInit = function(options) {
  33. this.position = options.position;
  34. this.data = options.data;
  35. this.minRadius = options.minRadius || 0;
  36. this.maxRadius = options.maxRadius || 50;
  37. };
  38. // 销毁时需解绑事件监听
  39. Donut.prototype.onDestroy = function() {
  40. if (this.onClick) {
  41. this.dom.removeEventListener(this.onClick);
  42. }
  43. };
  44. // 创建DOM元素,返回一个DOMElement,使用this.dom可以获取到这个元素
  45. Donut.prototype.createDOM = function() {
  46. let svg = document.createElementNS(SVG_NS, 'svg');
  47. svg.setAttribute('version', '1.1');
  48. svg.setAttribute('baseProfile', 'full');
  49. let r = this.maxRadius;
  50. svg.setAttribute('viewBox', [-r, -r, r * 2, r * 2].join(' '));
  51. svg.setAttribute('width', r * 2);
  52. svg.setAttribute('height', r * 2);
  53. svg.style.cssText = 'position:absolute;top:0px;left:0px;';
  54. let donut = createDonut(this.data, this.minRadius, this.maxRadius);
  55. svg.appendChild(donut);
  56. // click事件监听
  57. this.onClick = () => {
  58. // DOMOverlay继承自EventEmitter,可以使用emit触发事件
  59. this.emit('click');
  60. };
  61. // pc端注册click事件,移动端注册touchend事件
  62. svg.addEventListener('click', this.onClick);
  63. return svg;
  64. };
  65. // 更新DOM元素,在地图移动/缩放后执行
  66. Donut.prototype.updateDOM = function() {
  67. if (!this.map) {
  68. return;
  69. }
  70. // 经纬度坐标转容器像素坐标
  71. let pixel = this.map.projectToContainer(this.position);
  72. // 使饼图中心点对齐经纬度坐标点
  73. let left = pixel.getX() - this.dom.clientWidth / 2 + 'px';
  74. let top = pixel.getY() - this.dom.clientHeight / 2 + 'px';
  75. this.dom.style.transform = `translate(${left}, ${top})`;
  76. };
  77. // 使用SVG创建环状饼图
  78. function createDonut(data, minRadius, maxRadius) {
  79. const colorList = [
  80. '#7AF4FF',
  81. '#67D7FF',
  82. '#52B5FF',
  83. '#295BFF'
  84. ];
  85. let sum = data.reduce((prev, curr) => prev + curr, 0);
  86. let angle = 0;
  87. let group = document.createElementNS(SVG_NS, "g");
  88. data.forEach((d, i) => {
  89. let delta = d / sum * Math.PI * 2;
  90. color = colorList[i],
  91. r = maxRadius,
  92. startAngle = angle,
  93. endAngle = angle + delta;
  94. angle += delta;
  95. // 对每个数据创建一个扇形
  96. let fanShape = document.createElementNS(SVG_NS, 'path');
  97. fanShape.setAttribute('style', `fill: ${color};`);
  98. fanShape.setAttribute('d', [
  99. 'M0 0',
  100. `L${r * Math.sin(startAngle)} ${-r * Math.cos(startAngle)}`,
  101. `A${r} ${r} 0 ${delta > Math.PI ? 1 : 0} 1 ${r * Math.sin(endAngle)} ${-r * Math.cos(endAngle)}`,
  102. ].join(' ') + ' z');
  103. group.appendChild(fanShape);
  104. });
  105. // 在中心创建一个圆形
  106. let circleShape = document.createElementNS(SVG_NS, 'circle');
  107. circleShape.setAttribute('style', 'fill: #FFFFFF');
  108. circleShape.setAttribute('cx', 0);
  109. circleShape.setAttribute('cy', 0);
  110. circleShape.setAttribute('r', minRadius);
  111. group.appendChild(circleShape);
  112. // 绘制文字
  113. let textShape = document.createElementNS(SVG_NS, 'text');
  114. textShape.setAttribute('x', 0);
  115. textShape.setAttribute('y', '0.3em');
  116. textShape.setAttribute('text-anchor', 'middle');
  117. textShape.innerHTML = sum;
  118. group.appendChild(textShape);
  119. return group;
  120. }
  121. window.Donut = Donut;
  122. </script>
  123. <script type="text/javascript">
  124. var map;
  125. function initMap() {
  126. // 初始化地图
  127. map = new TMap.Map("container", {
  128. zoom:12, // 设置地图缩放级别
  129. center: new TMap.LatLng(39.984104, 116.307503) // 设置地图中心点坐标
  130. });
  131. let donutList = [
  132. new Donut({
  133. map,
  134. position: new TMap.LatLng(39.96030543872138, 116.25809083213608),
  135. data: [12, 24],
  136. minRadius: 13,
  137. maxRadius: 20
  138. }),
  139. new Donut({
  140. map,
  141. position: new TMap.LatLng(39.9986945980902, 116.33598362780685),
  142. data: [23, 99, 101, 400],
  143. minRadius: 25,
  144. maxRadius: 35
  145. }),
  146. new Donut({
  147. map,
  148. position: new TMap.LatLng(40.02906301748584, 116.25499991104516),
  149. data: [18, 41, 50],
  150. minRadius: 20,
  151. maxRadius: 28
  152. })
  153. ];
  154. donutList.forEach((donut, index) => {
  155. donut.on('click', () => {
  156. console.log(`第${index}个环形图被点击,位置为${donut.position}`);
  157. });
  158. });
  159. }
  160. </script>
  161. </body>
  162. </html>

适配后uniapp代码

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

DOMOverlay.js 

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

  1. var SVG_NS = 'http://www.w3.org/2000/svg';
  2. // 自定义环状饼图 - 继承DOMOverlay
  3. function Donut(options) {
  4. TMap.DOMOverlay.call(this, options);
  5. }
  6. /**
  7. * ----------------适配uniapp修改过的----------------
  8. *
  9. * 因为 TMap 对象依赖于 https://map.qq.com/api/gljs?v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77
  10. * 所以要封装一个方法,在加载完依赖脚本后,再运行
  11. */
  12. function initDonut(){
  13. Donut.prototype = new TMap.DOMOverlay();
  14. // 初始化
  15. Donut.prototype.onInit = function(options) {
  16. this.position = options.position;
  17. this.data = options.data;
  18. this.minRadius = options.minRadius || 0;
  19. this.maxRadius = options.maxRadius || 50;
  20. };
  21. // 销毁时需解绑事件监听
  22. Donut.prototype.onDestroy = function() {
  23. if (this.onClick) {
  24. this.dom.removeEventListener(this.onClick);
  25. }
  26. };
  27. // 创建DOM元素,返回一个DOMElement,使用this.dom可以获取到这个元素
  28. Donut.prototype.createDOM = function() {
  29. let svg = document.createElementNS(SVG_NS, 'svg');
  30. svg.setAttribute('version', '1.1');
  31. svg.setAttribute('baseProfile', 'full');
  32. let r = this.maxRadius;
  33. svg.setAttribute('viewBox', [-r, -r, r * 2, r * 2].join(' '));
  34. svg.setAttribute('width', r * 2);
  35. svg.setAttribute('height', r * 2);
  36. svg.style.cssText = 'position:absolute;top:0px;left:0px;';
  37. let donut = createDonut(this.data, this.minRadius, this.maxRadius);
  38. svg.appendChild(donut);
  39. // click事件监听
  40. this.onClick = () => {
  41. // DOMOverlay继承自EventEmitter,可以使用emit触发事件
  42. this.emit('click');
  43. };
  44. // ----------------适配uniapp修改过的----------------
  45. // pc端注册click事件,移动端注册touchend事件
  46. // svg.addEventListener('click', this.onClick); web端用click事件
  47. svg.addEventListener('touchend', this.onClick); // H5端用touchend事件
  48. return svg;
  49. };
  50. // 更新DOM元素,在地图移动/缩放后执行
  51. Donut.prototype.updateDOM = function() {
  52. if (!this.map) {
  53. return;
  54. }
  55. // 经纬度坐标转容器像素坐标
  56. let pixel = this.map.projectToContainer(this.position);
  57. // 使饼图中心点对齐经纬度坐标点
  58. let left = pixel.getX() - this.dom.clientWidth / 2 + 'px';
  59. let top = pixel.getY() - this.dom.clientHeight / 2 + 'px';
  60. this.dom.style.transform = `translate(${left}, ${top})`;
  61. };
  62. }
  63. // 使用SVG创建环状饼图
  64. function createDonut(data, minRadius, maxRadius) {
  65. const colorList = [
  66. '#7AF4FF',
  67. '#67D7FF',
  68. '#52B5FF',
  69. '#295BFF'
  70. ];
  71. let sum = data.reduce((prev, curr) => prev + curr, 0);
  72. let angle = 0;
  73. let group = document.createElementNS(SVG_NS, "g");
  74. data.forEach((d, i) => {
  75. let delta = d / sum * Math.PI * 2;
  76. let color = colorList[i],
  77. r = maxRadius,
  78. startAngle = angle,
  79. endAngle = angle + delta;
  80. angle += delta;
  81. // 对每个数据创建一个扇形
  82. let fanShape = document.createElementNS(SVG_NS, 'path');
  83. fanShape.setAttribute('style', `fill: ${color};`);
  84. fanShape.setAttribute('d', [
  85. 'M0 0',
  86. `L${r * Math.sin(startAngle)} ${-r * Math.cos(startAngle)}`,
  87. `A${r} ${r} 0 ${delta > Math.PI ? 1 : 0} 1 ${r * Math.sin(endAngle)} ${-r * Math.cos(endAngle)}`,
  88. ].join(' ') + ' z');
  89. group.appendChild(fanShape);
  90. });
  91. // 在中心创建一个圆形
  92. let circleShape = document.createElementNS(SVG_NS, 'circle');
  93. circleShape.setAttribute('style', 'fill: #FFFFFF');
  94. circleShape.setAttribute('cx', 0);
  95. circleShape.setAttribute('cy', 0);
  96. circleShape.setAttribute('r', minRadius);
  97. group.appendChild(circleShape);
  98. // 绘制文字
  99. let textShape = document.createElementNS(SVG_NS, 'text');
  100. textShape.setAttribute('x', 0);
  101. textShape.setAttribute('y', '0.3em');
  102. textShape.setAttribute('text-anchor', 'middle');
  103. textShape.innerHTML = sum;
  104. group.appendChild(textShape);
  105. return group;
  106. }
  107. window.Donut = Donut;
  108. var map;
  109. function initMap() {
  110. // ----------------适配uniapp修改过的----------------
  111. // 调用封装后的initDount()
  112. initDonut()
  113. // 初始化地图
  114. map = new TMap.Map("mapContainer", {
  115. zoom:12, // 设置地图缩放级别
  116. center: new TMap.LatLng(39.984104, 116.307503) // 设置地图中心点坐标
  117. });
  118. let donutList = [
  119. new Donut({
  120. map,
  121. position: new TMap.LatLng(39.96030543872138, 116.25809083213608),
  122. data: [12, 24],
  123. minRadius: 13,
  124. maxRadius: 20
  125. }),
  126. new Donut({
  127. map,
  128. position: new TMap.LatLng(39.9986945980902, 116.33598362780685),
  129. data: [23, 99, 101, 400],
  130. minRadius: 25,
  131. maxRadius: 35
  132. }),
  133. new Donut({
  134. map,
  135. position: new TMap.LatLng(40.02906301748584, 116.25499991104516),
  136. data: [18, 41, 50],
  137. minRadius: 20,
  138. maxRadius: 28
  139. })
  140. ];
  141. donutList.forEach((donut, index) => {
  142. donut.on('click', () => {
  143. console.log(`第${index}个环形图被点击,位置为${donut.position}`);
  144. alert(`第${index}个环形图被点击,位置为${donut.position}`)
  145. });
  146. });
  147. }
  148. /**
  149. * ----------------适配uniapp修改过的----------------
  150. * 导出initMap方法
  151. */
  152. export {
  153. initMap
  154. }
loadJs.js

用来加载第三方js

  1. function loadJs(src) {
  2.   return new Promise((resolve,reject)=>{
  3.     let script = document.createElement('script');
  4.     script.type = "text/javascript";
  5.     script.src= src;
  6.     document.body.appendChild(script);
  7.       
  8.     script.onload = ()=>{
  9.       resolve();
  10.     }
  11.     script.onerror = ()=>{
  12.       reject();
  13.     }
  14.   }).catch((e) => {})
  15. }
  16.  
  17. export default loadJs
map.vue
  1. <template>
  2. <view id="mapContainer" style="height: 100%;" @click="log">
  3. </view>
  4. </template>
  5. <script>
  6. export default {
  7. data() {
  8. return {
  9. }
  10. },
  11. mounted() {
  12. }
  13. }
  14. </script>
  15. <script lang="renderjs" module="test">
  16. import loadJs from "../../common/loadJs.js"
  17. // 导入适配后的 DOMOverlay.js
  18. import {initMap} from "../../common/DOMOverlay.js"
  19. export default {
  20. data() {
  21. return {
  22. }
  23. },
  24. mounted(){
  25. console.log("mounted")
  26. loadJs('https://map.qq.com/api/gljs?v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77').then(()=>{
  27. // 调用初始化地图方法
  28. initMap()
  29. })
  30. },
  31. methods: {
  32. },
  33. created() {
  34. }
  35. }
  36. </script>
  37. <style>
  38. </style>

三、适配效果

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/495808
推荐阅读
相关标签
  

闽ICP备14008679号