map.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <template>
  2. <view class="map-container">
  3. <map
  4. id="map"
  5. :latitude="latitude"
  6. :longitude="longitude"
  7. scale="12"
  8. show-compass
  9. show-location
  10. :markers="markers"
  11. :polyline="polyline"
  12. @markertap="markertap"
  13. style="width: 100%; height:100%;">
  14. </map>
  15. </view>
  16. </template>
  17. <script>
  18. import { getCleanWay } from '@/api/unclear.js'
  19. var QQMapWX = require('@/libs/qqmap-wx-jssdk.min.js')
  20. var qqmapsdk
  21. export default{
  22. data(){
  23. return{
  24. latitude: null, // 纬度
  25. longitude: null, // 经度
  26. markers: [], // 所有网点标注点
  27. distanceMark: [], // 按距离计算远近后的网点标注点
  28. polyline: null, // 路线
  29. }
  30. },
  31. onLoad() {
  32. // 实例化API核心类
  33. qqmapsdk = new QQMapWX({
  34. key: 'FRCBZ-IDZWW-FGDRR-O3SQM-ZW5C2-LRBDM'
  35. })
  36. },
  37. onShow() {
  38. this.getLocation()
  39. },
  40. methods: {
  41. // 获取当前位置
  42. getLocation(){
  43. const _this = this
  44. uni.getLocation({
  45. type: 'gcj02',
  46. success: function (res) {
  47. _this.latitude = res.latitude // 纬度
  48. _this.longitude = res.longitude // 经度
  49. _this.getCleanWay() // 获取个人待清运清单
  50. }
  51. })
  52. },
  53. // 标注点信息
  54. getCleanWay(){
  55. getCleanWay({ lng: this.longitude, lat: this.latitude }).then(res => {
  56. if(res.status == 200){
  57. this.markers = []
  58. res.data.map((item, index) => {
  59. if(item.lat && item.lng){ // 经纬度为空的错误数据,网点信息不在地图上显示
  60. this.markers.push({
  61. id: index+1,
  62. latitude: item.lat,
  63. longitude: item.lng,
  64. width: '60rpx',
  65. height: '60rpx',
  66. iconPath: '/static/store.png',
  67. label: {
  68. content: item.stationName || '--',
  69. bgColor: '#fff',
  70. }
  71. })
  72. }
  73. })
  74. if(this.markers.length>0){
  75. this.onCalculateDistance() // 计算距离
  76. }
  77. }
  78. })
  79. },
  80. // 将所有标注点与当前位置进行距离计算
  81. onCalculateDistance(){
  82. const _this = this
  83. const startPos = { latitude: _this.latitude, longitude: _this.longitude }
  84. let destPos = []
  85. _this.markers.map(item => {
  86. destPos.push({ latitude: item.latitude, longitude: item.longitude })
  87. })
  88. //调用距离计算接口
  89. qqmapsdk.calculateDistance({
  90. mode: 'driving', //可选值:'driving'(驾车)、'walking'(步行),不填默认:'walking',可不填
  91. //from参数不填默认当前地址
  92. //获取表单提交的经纬度并设置from和to参数(示例为string格式)
  93. from: startPos, //若起点有数据则采用起点坐标,若为空默认当前地址
  94. to: destPos, //终点坐标
  95. success: function(res) {//成功后的回调
  96. var res = res.result
  97. _this.distanceMark = []
  98. for (var i = 0; i < res.elements.length; i++) {
  99. // 将距离值加入标注点信息中
  100. _this.distanceMark.push({
  101. latitude: res.elements[i].to.lat,
  102. longitude: res.elements[i].to.lng,
  103. distance: res.elements[i].distance
  104. })
  105. }
  106. // 数组升序排序
  107. _this.distanceMark.sort(_this.compare( 'distance', true ))
  108. _this.onDirection() // 路线规划
  109. },
  110. fail: function(error) {
  111. console.error(error)
  112. },
  113. complete: function(res) {
  114. // console.log(res)
  115. }
  116. })
  117. },
  118. // 数组排序
  119. compare(property, desc){
  120. return function (a, b) {
  121. var value1 = a[property]
  122. var value2 = b[property]
  123. if(desc==true){ // 升序排列
  124. return value1 - value2
  125. }else{ // 降序排列
  126. return value2 - value1
  127. }
  128. }
  129. },
  130. // 路线规划
  131. onDirection(){
  132. const _this = this
  133. _this.polyline = []
  134. // 将所有标注点都按距离进行路线规划
  135. var position = null
  136. position = [
  137. { latitude: _this.latitude, longitude: _this.longitude },
  138. { latitude: _this.distanceMark[0].latitude, longitude: _this.distanceMark[0].longitude }
  139. ]
  140. _this.getDirection(position, 0)
  141. },
  142. // 路线规划
  143. getDirection(position, ind){
  144. const _this = this
  145. qqmapsdk.direction({
  146. mode: 'driving',//可选值:'driving'(驾车)、'walking'(步行)、'bicycling'(骑行),不填默认:'driving',可不填
  147. //from参数不填默认当前地址
  148. from: {
  149. latitude: position[0].latitude,
  150. longitude: position[0].longitude
  151. },
  152. to: {
  153. latitude: position[1].latitude,
  154. longitude: position[1].longitude
  155. },
  156. policy: 'LEAST_TIME,NAV_POINT_FIRST',
  157. success: function (res) {
  158. var ret = res
  159. var coors = ret.result.routes[0].polyline, pl = []
  160. //坐标解压(返回的点串坐标,通过前向差分进行压缩)
  161. var kr = 1000000
  162. for (var i = 2; i < coors.length; i++) {
  163. coors[i] = Number(coors[i - 2]) + Number(coors[i]) / kr;
  164. }
  165. //将解压后的坐标放入点串数组pl中
  166. for (var i = 0; i < coors.length; i += 2) {
  167. pl.push({ latitude: coors[i], longitude: coors[i + 1] })
  168. }
  169. //设置polyline属性,将路线显示出来,将解压坐标第一个数据作为起点
  170. _this.polyline.push({
  171. points: pl,
  172. arrowLine: true,
  173. width: 8,
  174. color: '#07c160'
  175. })
  176. },
  177. fail: function (error) {
  178. console.error(error)
  179. },
  180. complete: function (res) {
  181. // 腾讯地图使用限制
  182. // 为了保证我们的服务稳定,我们对每个key的每个服务接口的调用量做了如下限制:
  183. // 日调用量:1万次 / Key
  184. // 并发数:5次 / key / 秒
  185. // 递归调用避免并发限制
  186. if(ind < _this.distanceMark.length-1){
  187. let pos = [
  188. { latitude: _this.distanceMark[ind].latitude, longitude: _this.distanceMark[ind].longitude },
  189. { latitude: _this.distanceMark[ind+1].latitude, longitude: _this.distanceMark[ind+1].longitude }
  190. ]
  191. let subInd = ind
  192. subInd++
  193. setTimeout(()=>{
  194. _this.getDirection(pos, subInd)
  195. },300)
  196. }
  197. }
  198. })
  199. },
  200. // 点击标注点,调用第三方地图查看规划路线
  201. markertap(e){
  202. this.markers.map(item => {
  203. if(item.id == e.detail.markerId){
  204. uni.openLocation({
  205. latitude: item.latitude,
  206. longitude: item.longitude,
  207. success: function () {
  208. }
  209. })
  210. }
  211. })
  212. }
  213. }
  214. }
  215. </script>
  216. <style lang="scss" scoped>
  217. .map-container {
  218. width: 100%;
  219. height: 100vh;
  220. }
  221. </style>