GeoMap.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <template>
  2. <div id="container" class="amap-wrapper">
  3. <el-amap
  4. class="amap-box"
  5. :vid="'amap-vue'"
  6. :amap-manager="amapManager"
  7. :zoom="zoom"
  8. :center="mapCenter"
  9. :plugin="plugins"
  10. :events="mapEvents"
  11. >
  12. <el-amap-marker
  13. v-for="(marker, index) in markers"
  14. :key="index"
  15. :position="marker.position"
  16. :label="marker.label"
  17. :events="markerEvents"
  18. :ext-data="marker.extData"
  19. />
  20. </el-amap>
  21. <!-- marker 内容弹窗 -->
  22. <el-dialog
  23. append-to-body
  24. :visible.sync="showMarkerDialog"
  25. :before-close="handleDialogClose"
  26. width="30%"
  27. center
  28. >
  29. <el-card class="box-card">
  30. <div slot="header" class="clearfix">
  31. <el-button
  32. v-clipboard:copy="earthPoint.lat + ' ' + earthPoint.lng"
  33. v-clipboard:success="onCopy"
  34. v-clipboard:error="onCopyError"
  35. type="text"
  36. >GoogleEarth 坐标</el-button>
  37. </div>
  38. <div class="text item">
  39. <el-image v-if="markerInfo.photoUrl !== null" :src="markerInfo.photoUrl" min-width="40" height="30" />
  40. <div v-if="markerInfo.type === 3">
  41. <el-row>
  42. <el-row>
  43. ID
  44. <a style="text-decoration-line: none" target="_blank" :href="`https://item.taobao.com/item.htm?id=${markerInfo.itemId}`">
  45. <span style="color: blue">{{ markerInfo.itemId }}</span>
  46. </a>
  47. </el-row>
  48. <el-row>
  49. SKU <span style="color: blue" v-text="markerInfo.sku" />
  50. </el-row>
  51. <el-row>
  52. 评论 <span style="color: blue" v-text="markerInfo.replyContent" />
  53. </el-row>
  54. </el-row>
  55. </div>
  56. <div v-if="markerInfo.type === 2">
  57. <el-row>
  58. <el-row>
  59. ID
  60. <router-link style="text-decoration-line: none" target="_blank" :to="`/image/${markerInfo.itemId}`">
  61. <span style="color: blue">{{ markerInfo.itemId }}</span>
  62. </router-link>
  63. </el-row>
  64. </el-row>
  65. </div>
  66. </div>
  67. </el-card>
  68. </el-dialog>
  69. </div>
  70. </template>
  71. <script>
  72. import { getMarkerInfo, getCupMap } from '@/api/map'
  73. import Vue from 'vue'
  74. import VueAMap from 'vue-amap'
  75. Vue.use(VueAMap)
  76. VueAMap.initAMapApiLoader({
  77. key: 'your amap key',
  78. plugin: [
  79. 'AMap.Autocomplete', 'AMap.PlaceSearch', 'AMap.Scale', 'AMap.OverView', 'AMap.ToolBar',
  80. 'AMap.MapType', 'AMap.PolyEditor', 'AMap.CircleEditor', 'AMap.MassMarks', 'AMap.Size',
  81. 'AMap.Pixel'
  82. ],
  83. // 默认高德 sdk 版本为 1.4.4
  84. v: '1.4.15'
  85. })
  86. import { AMapManager, lazyAMapApiLoaderInstance } from 'vue-amap'
  87. const amapManager = new AMapManager()
  88. export default {
  89. name: 'GeoMap',
  90. data() {
  91. return {
  92. amap: null,
  93. plugins: ['Scale'],
  94. mapCenter: [108.337237, 33.881985],
  95. // zoom=6 的比例尺为 100km
  96. // zoom=5 的比例尺为 200km
  97. // zoom=4 的比例尺为 500km
  98. zoom: 4,
  99. markers: [],
  100. markerEvents: {
  101. click: (e) => {
  102. const id = e.target.getExtData().id
  103. const position = e.target.getPosition()
  104. const item = {
  105. id: id,
  106. position: {
  107. lng: position.lng,
  108. lat: position.lat
  109. }
  110. }
  111. this.getMarkerInfoWrapper(item)
  112. }
  113. },
  114. /* 海量点 */
  115. massMarks: null,
  116. amapManager,
  117. mapEvents: {
  118. init: this.mapInit,
  119. zoomchange: this.zoomchange
  120. },
  121. // 弹框数据
  122. showMarkerDialog: false,
  123. markerInfo: {
  124. itemId: null,
  125. sku: null,
  126. replyId: null,
  127. replyContent: null,
  128. appendContent: null,
  129. photoUrl: null
  130. },
  131. earthPoint: {
  132. lat: null,
  133. lng: null
  134. }
  135. }
  136. },
  137. created() {
  138. document.title = 'CupMap'
  139. },
  140. methods: {
  141. mapInit(o) {
  142. this.amap = o
  143. lazyAMapApiLoaderInstance.load().then(() => {
  144. // 图标样式
  145. var styleObject = {
  146. url: '//webapi.amap.com/theme/v1.3/markers/n/mark_b.png', // 图标地址
  147. size: new AMap.Size(11, 11), // 图标大小
  148. anchor: new AMap.Pixel(5, 5) // 图标显示位置偏移量,基准点为图标左上角
  149. }
  150. // 海量点样式
  151. const massMarks = new AMap.MassMarks([], {
  152. zIndex: 5, // 海量点图层叠加的顺序
  153. zooms: [3, 10], // 在指定地图缩放级别范围内展示海量点图层
  154. style: styleObject // 设置样式对象
  155. })
  156. // 将海量标点添加至地图实例
  157. massMarks.setMap(o)
  158. // 海量标点点击事件
  159. massMarks.on('click', (e) => {
  160. console.log('massMark 点击事件')
  161. const id = e.data.id
  162. const item = {
  163. id: id,
  164. position: {
  165. lng: e.data.lnglat.lng,
  166. lat: e.data.lnglat.lat
  167. }
  168. }
  169. this.getMarkerInfoWrapper(item)
  170. })
  171. // 设置海量点
  172. this.massMarks = massMarks
  173. // 获取 mark 数据
  174. this.getPhotoMarksWrapper()
  175. // this.getPhotoMarksWrapper1()
  176. })
  177. },
  178. zoomchange(e) {
  179. console.log('当前缩放级别: ' + this.amap.getZoom())
  180. },
  181. getPhotoMarksWrapper() {
  182. this.markers = []
  183. getCupMap().then(res => {
  184. if (res.code === 0) {
  185. this.$notify({
  186. message: '加载了 ' + res.data.length + ' 条数据',
  187. type: 'warning',
  188. duration: 1000
  189. })
  190. for (const item of res.data) {
  191. this.markers.push({
  192. position: [item.position.lng, item.position.lat],
  193. label: { content: item.title, offset: [0, 0] },
  194. extData: { id: item.id }
  195. })
  196. }
  197. } else {
  198. this.$notify({
  199. message: res.msg,
  200. type: 'warning',
  201. duration: 1000
  202. })
  203. }
  204. }).catch(error => {
  205. this.$notify({
  206. message: error.message,
  207. type: 'warning',
  208. duration: 1000
  209. })
  210. })
  211. },
  212. // 获取数据渲染海量点
  213. getPhotoMarksWrapper1() {
  214. this.massMarks.setData([])
  215. getCupMap().then(res => {
  216. if (res.code === 0) {
  217. this.$notify({
  218. message: '加载了 ' + res.data.length + ' 条数据',
  219. type: 'warning',
  220. duration: 1000
  221. })
  222. const massMarkers = []
  223. for (const item of res.data) {
  224. massMarkers.push({
  225. lnglat: [item.position.lng, item.position.lat],
  226. id: item.id
  227. })
  228. }
  229. this.massMarks.setData(massMarkers)
  230. this.zoom = 5
  231. } else {
  232. this.$notify({
  233. message: res.msg,
  234. type: 'warning',
  235. duration: 1000
  236. })
  237. }
  238. }).catch(error => {
  239. this.$notify({
  240. message: error.message,
  241. type: 'warning',
  242. duration: 1000
  243. })
  244. })
  245. },
  246. getMarkerInfoWrapper(item) {
  247. this.earthPoint = item.position
  248. this.showMarkerDialog = true
  249. this.markerInfo = {
  250. itemId: null,
  251. sku: null,
  252. replyId: null,
  253. replyContent: null,
  254. appendContent: null,
  255. photoUrl: null
  256. }
  257. getMarkerInfo(item.id).then(res => {
  258. if (res.code === 0) {
  259. this.markerInfo = res.data
  260. } else {
  261. this.showMarkerDialog = false
  262. }
  263. }).catch(error => {
  264. this.showMarkerDialog = false
  265. console.log(error)
  266. })
  267. },
  268. /* 弹出框 */
  269. handleDialogClose(done) {
  270. this.showMarkerDialog = false
  271. this.earthPoint = { lat: null, lng: null }
  272. done()
  273. },
  274. onCopy(e) {
  275. this.$notify({
  276. message: 'GoogleEarth 坐标已复制, 快到 GoogleEarth 中去找这个地方吧~',
  277. type: 'warning',
  278. duration: 1000
  279. })
  280. },
  281. onCopyError(e) {
  282. this.$notify({
  283. message: '复制 GoogleEarth 坐标失败!',
  284. type: 'error',
  285. duration: 1000
  286. })
  287. }
  288. }
  289. }
  290. </script>
  291. <style>
  292. .amap-wrapper {
  293. width: 100%;
  294. height: 100%;
  295. }
  296. </style>