map.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <template>
  2. <div class="app-container">
  3. <div style="background-color: #ffffff;height:100%;">
  4. <div id="container"></div>
  5. </div>
  6. </div>
  7. </template>
  8. <script setup lang="ts">
  9. import AMapLoader from '@amap/amap-jsapi-loader';
  10. /*在Vue3中使用时,需要引入Vue3中的shallowRef方法(使用shallowRef进行非深度监听,
  11. 因为在Vue3中所使用的Proxy拦截操作会改变JSAPI原生对象,所以此处需要区别Vue2使用方式对地图对象进行非深度监听,
  12. 否则会出现问题,建议JSAPI相关对象采用非响应式的普通对象来存储)*/
  13. import { shallowRef } from '@vue/reactivity';
  14. import { ref } from "vue";
  15. import { getDicts } from '@/api/system/dict/data'
  16. import { getGpsData } from '@/api/gpsData/index'
  17. import carImage from "@/assets/images/icon/小货车.png";
  18. import { listCarInfo, getCarInfo, delCarInfo, addCarInfo, updateCarInfo } from '@/api/carInfo';
  19. import add from '@/views/car/carInfo/add.vue';
  20. import { color } from 'echarts';
  21. const props = defineProps({
  22. showMarket: {
  23. type: Boolean,
  24. default: true
  25. },
  26. darkType: {
  27. type: Boolean,
  28. default: false
  29. },
  30. })
  31. // const map = shallowRef(null);
  32. const path = ref([]);
  33. const current_position = ref([]);
  34. let mapObj = ref()
  35. let singleMarker = ref(null);
  36. const fontColor = ref('#6cb3e0')
  37. const lineObj = ref(null);
  38. const iconImage = new URL("@/assets/images/home/Point.png",import.meta.url);
  39. const getCarInfoList = () => {
  40. listCarInfo({pageSzie:1000}).then(res=>{
  41. for (var index in res.rows) {
  42. var obj = res.rows[index].location;
  43. // console.log(obj.toString())
  44. var location = formatGCJ(obj.lng,obj.lat);
  45. // console.log(location.toString())
  46. addMarker(location, res.rows[index], '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png', 'location')
  47. }
  48. })
  49. }
  50. const getDictsData = (param) => {
  51. getDicts(param).then(res => {
  52. for (var index in res.data) {
  53. var obj = res.data[index].dictValue.split(",");
  54. // console.log(obj.toString())
  55. var location = formatGCJ(Number(obj[0]), Number(obj[1]));
  56. // console.log(location.toString())
  57. addMarker(location, res.data[index], '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png', 'location')
  58. }
  59. })
  60. }
  61. const getGpsDataList = (param) => {
  62. getGpsData(param).then(res => {
  63. addLine(res.rows);
  64. if (singleMarker.value != null) {
  65. mapObj.value.remove(singleMarker.value);
  66. }
  67. var car = res.rows[res.rows.length - 1]
  68. if (car) {
  69. var location = formatGCJ(car.lng, car.lat);
  70. // addMarker(location, car, "../src/assets/images/icon/小货车.png", 'car')
  71. addMarker(location, car, carImage, 'car')
  72. }
  73. })
  74. }
  75. const setDataList = (data) => {
  76. tableData.value = data
  77. }
  78. const initMap = () => {
  79. window._AMapSecurityConfig = {
  80. securityJsCode: 'b16e0ff6d065a3b8a87e6c448e982ca4',
  81. }
  82. AMapLoader.load({
  83. key: "c60c1af6d4f39c5220f3ad36298a8830", // 申请好的Web端开发者Key,首次调用 load 时必填
  84. version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
  85. // plugins:[''], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
  86. }).then((AMap) => {
  87. const map = new AMap.Map("container", { //设置地图容器id
  88. viewMode: "3D", //是否为3D地图模式
  89. zoom: 13, //初始化地图级别
  90. center: [119.807462, 26.958413], //初始化地图中心点位置
  91. });
  92. mapObj.value = map;
  93. if (props.darkType) {
  94. var styleName = "amap://styles/8b9b98f3e261fb3096f4425490da9c5d";
  95. map.setMapStyle(styleName);
  96. }
  97. // 添加插件
  98. // AMap.plugin(["AMap.ToolBar", "AMap.Scale", "AMap.HawkEye", "AMap.Geolocation", "AMap.MapType", "AMap.MouseTool"], function () {
  99. // //异步同时加载多个插件
  100. // // 添加地图插件
  101. // // map.addControl(new AMap.ToolBar()); // 工具条控件;范围选择控件
  102. // map.addControl(new AMap.Scale()); // 显示当前地图中心的比例尺
  103. // map.addControl(new AMap.HawkEye()); // 显示缩略图
  104. // map.addControl(new AMap.Geolocation()); // 定位当前位置
  105. // // map.addControl(new AMap.MapType()); // 实现默认图层与卫星图,实时交通图层之间切换
  106. // });
  107. getCarInfoList();
  108. // if (props.showMarket) {
  109. // getDictsData("tbl_sites");
  110. // }
  111. // 单击
  112. map.on('click', (e) => {
  113. // lng ==> 经度值 lat => 维度值
  114. current_position.value = [e.lnglat.lng, e.lnglat.lat];
  115. path.value.push([e.lnglat.lng, e.lnglat.lat]);
  116. //addMarker();
  117. // addPolyLine();
  118. })
  119. // 折线
  120. function addPolyLine() {
  121. const polyline = new AMap.Polyline({
  122. path: path.value,
  123. isOutline: true,
  124. outlineColor: "#ffeeff",
  125. borderWeight: 1,
  126. strokeColor: "#3366FF",
  127. strokeOpacity: 0.6,
  128. strokeWeight: 5,
  129. // 折线样式还支持 'dashed'
  130. strokeStyle: "solid",
  131. // strokeStyle是dashed时有效
  132. // strokeDasharray: [10, 5],
  133. lineJoin: "round",
  134. lineCap: "round",
  135. zIndex: 50,
  136. });
  137. map.add([polyline]);
  138. }
  139. }).catch(e => {
  140. console.log(e);
  141. })
  142. }
  143. const addMarker = (obj, data, src, type) => {
  144. const marker = new AMap.Marker({
  145. icon: new AMap.Icon({
  146. image: iconImage,
  147. imageSize: new AMap.Size(28, 28) //图标大小
  148. }),
  149. position: obj, // 这里我们通过上面的点击获取经纬度坐标,实时添加标记
  150. // 通过设置 offset 来添加偏移量
  151. offset: new AMap.Pixel(-10, -20),
  152. });
  153. if (props.darkType) {
  154. fontColor.value = '#ffffff'
  155. }
  156. marker.setLabel({
  157. offset: new AMap.Pixel(-50, 25),
  158. content: data.carNum,
  159. });
  160. if (type == 'car') {
  161. singleMarker.value = marker
  162. }
  163. marker.setMap(mapObj.value);
  164. //给marker添加属性
  165. marker.setExtData(data)
  166. //给marker添加点击事件
  167. marker.on('click', clickMarker)
  168. }
  169. const addLine = (list) => {
  170. if (lineObj.value != null) {
  171. mapObj.value.remove([lineObj.value])
  172. }
  173. var dataList = []
  174. for (var index in list) {
  175. // console.log('转换前坐标' + [list[index].lng, list[index].lat])
  176. var location = formatGCJ(list[index].lng, list[index].lat);
  177. // console.log('转换后坐标' + [location[0], location[1]])
  178. var obj = new AMap.LngLat(location[0], location[1]);
  179. dataList.push(obj)
  180. }
  181. var polyline = new AMap.Polyline({
  182. path: dataList,
  183. strokeWeight: 2, //线条宽度
  184. strokeColor: "red", //线条颜色
  185. lineJoin: "round", //折线拐点连接处样式
  186. });
  187. // polyline.setMap(mapObj);
  188. // console.log(mapObj)
  189. lineObj.value = polyline
  190. mapObj.value.add(polyline);
  191. }
  192. const emit = defineEmits(['childToParent']);
  193. const clickMarker = (e) => {
  194. emit('childToParent', e.target.getExtData())
  195. }
  196. const formatGCJ = (lng, lat) => {
  197. const x_PI = 3.14159265358979324 * 3000.0 / 180.0
  198. const PI = 3.1415926535897932384626
  199. const a = 6378245.0
  200. const ee = 0.00669342162296594323
  201. if (outOfChina(lng, lat)) {
  202. return [lng, lat]
  203. }
  204. else {
  205. var dlat = transformlat(lng - 105.0, lat - 35.0)
  206. var dlng = transformlng(lng - 105.0, lat - 35.0)
  207. var radlat = lat / 180.0 * PI
  208. var magic = Math.sin(radlat)
  209. magic = 1 - ee * magic * magic
  210. var sqrtmagic = Math.sqrt(magic)
  211. dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
  212. dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI)
  213. const mglat = lat + dlat
  214. const mglng = lng + dlng
  215. return [mglng, mglat]
  216. }
  217. /*判断是否在国内,不在国内则不做偏移*/
  218. function transformlat(lng, lat) {
  219. var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng))
  220. ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0
  221. ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0
  222. ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0
  223. return ret
  224. }
  225. /**
  226. * 纬度转换
  227. * @param { Number } lng
  228. * @param { Number } lat
  229. */
  230. function transformlng(lng, lat) {
  231. var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
  232. ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0
  233. ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0
  234. ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0
  235. return ret
  236. }
  237. /**
  238. * 判断是否在国内,不在国内则不做偏移
  239. * @param {*} lng
  240. * @param {*} lat
  241. */
  242. function outOfChina(lng, lat) {
  243. return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false)
  244. }
  245. }
  246. initMap()
  247. console.log(props.showMarket);
  248. // getGpsDataList();
  249. defineExpose({
  250. getGpsDataList,
  251. });
  252. </script>
  253. <style>
  254. #container {
  255. padding: 0px;
  256. margin: 0px;
  257. width: 100%;
  258. height: 100%;
  259. }
  260. .amap-marker-label{
  261. border: 0px solid #00f;
  262. background-color: transparent;
  263. color: v-bind(fontColor);;
  264. }
  265. </style>