index.jsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. import { defineComponent, onMounted, ref, reactive, watch } from 'vue';
  2. import { useRoute, useRouter } from 'vue-router';
  3. import './index.scss';
  4. import Map from '@/components/MapView';
  5. import { ElButton } from 'element-plus';
  6. /** @ts-ignore */
  7. import icon_location_svg1 from "@/assets/images/location1.png";
  8. /** @ts-ignore */
  9. import icon_location from '@/assets/images/icon_map_location@2x.png';
  10. import { cloneDeep } from 'lodash';
  11. export default defineComponent({
  12. name: 'MapSelect',
  13. props: {
  14. formv: {
  15. type: Object,
  16. default: { addr: '', locations: '' },
  17. },
  18. editable: {
  19. type: String,
  20. default:true
  21. }
  22. },
  23. setup(props, ctx) {
  24. const form = ref({ addr: '', locations: '' });
  25. const route = useRoute();
  26. const map = ref(null);
  27. const state = reactive({
  28. // map: map.value,
  29. _marker: null ,
  30. loading: false,
  31. });
  32. const mapselect = ref(false);
  33. const setlocation = () => {
  34. if (window.map) {
  35. form.value = props.formv;
  36. if (form.value.locations !== '') {
  37. setpoint(
  38. Number(form.value.locations.split(',')[0]),
  39. Number(form.value.locations.split(',')[1]),
  40. form.value.addr);
  41. } else {
  42. mapselect.value = true;
  43. var clearallmark = () => {
  44. state._marker?.remove();
  45. if (allmark.length > 0) {
  46. allmark.map((item) => {
  47. item.remove();
  48. });
  49. allmark = [];
  50. }
  51. };
  52. clearallmark();
  53. }
  54. }
  55. }
  56. watch(
  57. () => props.formv.locations,
  58. () => {
  59. if (window.map == undefined) {
  60. setTimeout(() => {
  61. setlocation();
  62. }, 1500);
  63. }
  64. setlocation();
  65. },
  66. );
  67. onMounted(() => {
  68. if (props.formv.locations) {
  69. mapselect.value = false;
  70. setlocation();
  71. } else {
  72. mapselect.value = true;
  73. }
  74. });
  75. let allmark = [];
  76. const selectpoint = () => {
  77. if (mapselect.value) {
  78. var center = window.map.getCenter();
  79. getlocalname(center.lng.toFixed(6) + ',' + center.lat.toFixed(6));
  80. } else {
  81. mapselect.value = true;
  82. state._marker?.remove();
  83. }
  84. };
  85. const setpoint = (longitude, latitude, name) => {
  86. if (state._marker) {
  87. state._marker.remove();
  88. }
  89. // var el = document.createElement('div');
  90. // el.id = 'marker';
  91. // el.style.backgroundImage = `url(${icon_location})`;
  92. // el.style.backgroundSize = 'cover';
  93. // el.style.width = '24px';
  94. // el.style.height = '24px';
  95. // el.style.borderRadius = '50%';
  96. var icon = new AMap.Icon({
  97. size: new AMap.Size(40, 50), // 图标尺寸
  98. image: '/icon_map_location@2x.png', // Icon的图像
  99. imageSize: new AMap.Size(20, 20) // 根据所设置的大小拉伸或压缩图片
  100. });
  101. state._marker = new AMap.Marker({
  102. position: new AMap.LngLat(longitude, latitude),
  103. offset: new AMap.Pixel(-10, -10),
  104. icon: icon,
  105. })
  106. state._marker.setLabel({
  107. direction:'top',
  108. offset: new AMap.Pixel(0, -10), //设置文本标注偏移量
  109. content: `<div class='info'>${name}</div>`, //设置文本标注内容
  110. });
  111. window.map.add(state._marker)
  112. window.map.setZoomAndCenter(14,
  113. [longitude, latitude]
  114. )
  115. // .setLngLat([longitude, latitude])
  116. // .setPopup(popup)
  117. // .addTo(map.value);
  118. // map.value.flyTo({
  119. // center: [longitude, latitude],
  120. // zoom: 14,
  121. // bearing: 0,
  122. // pitch: 0,
  123. // duration: 2000,
  124. // });
  125. // state._marker.togglePopup();
  126. form.value.addr = name;
  127. form.value.locations = longitude + ',' + latitude;
  128. // whdata.value.longitude = longitude;
  129. mapselect.value = false;
  130. props.formv = form.value;
  131. ctx.emit('update:formv', form.value);
  132. };
  133. const searchaddr = (name) => {
  134. mapselect.value = false;
  135. fetch(
  136. `https://restapi.amap.com/v5/place/text?region=南宁市&keywords=${name}&key=${"1c7f1c8eda2ccbe7d0e125a7e2fc2a61"}`,
  137. // `${
  138. // import.meta.env.VITE_MAP_SERVER
  139. // }/service/lbs/search/v1/keywords?keywords=${name}&city=宿迁&citylimit=true&page_idx=1&page_size=10&key=${
  140. // window.key
  141. // }`,
  142. )
  143. .then((res) => res.json())
  144. .then((data) => {
  145. // console.log(data.pois)
  146. var clearallmark = () => {
  147. state._marker?.remove();
  148. if (allmark.length > 0) {
  149. allmark.map((item) => {
  150. item.remove();
  151. });
  152. allmark = [];
  153. }
  154. };
  155. clearallmark();
  156. var top = [];
  157. var bottom = [];
  158. data.pois.map((item) => {
  159. // console.log(item)
  160. if (top.length < 1) {
  161. top = [
  162. Number(item.location.split(',')[0]),
  163. Number(item.location.split(',')[1]),
  164. ];
  165. bottom = [
  166. Number(item.location.split(',')[0]),
  167. Number(item.location.split(',')[1]),
  168. ];
  169. }
  170. var icon = new AMap.Icon({
  171. size: new AMap.Size(40, 50), // 图标尺寸
  172. image: '/icon_map_location@2x.png', // Icon的图像
  173. imageSize: new AMap.Size(20, 20) // 根据所设置的大小拉伸或压缩图片
  174. });
  175. var marker = new AMap.Marker({
  176. position: new AMap.LngLat( Number(item.location.split(',')[0]), Number(item.location.split(',')[1])),
  177. offset: new AMap.Pixel(-10, -10),
  178. icon: icon,
  179. })
  180. var address = item.pname+item.cityname+item.adname+item.address+`(${item.name})`
  181. marker.setLabel({
  182. direction:'top',
  183. offset: new AMap.Pixel(0, -10), //设置文本标注偏移量
  184. content: `<div class='info'>${address}</div>`, //设置文本标注内容
  185. });
  186. marker.on("click", () => {
  187. clearallmark();
  188. setpoint(
  189. Number(item.location.split(',')[0]),
  190. Number(item.location.split(',')[1]),
  191. address,
  192. );
  193. })
  194. window.map.add(marker)
  195. // window.map.setZoomAndCenter(14,
  196. // [longitude, latitude]
  197. // )
  198. allmark.push(marker);
  199. if (top[0] < Number(item.location.split(',')[0])) {
  200. top[0] = Number(item.location.split(',')[0]);
  201. }
  202. if (top[1] > Number(item.location.split(',')[1])) {
  203. top[1] = Number(item.location.split(',')[1]);
  204. }
  205. if (bottom[0] > Number(item.location.split(',')[0])) {
  206. bottom[0] = Number(item.location.split(',')[0]);
  207. }
  208. if (bottom[1] < Number(item.location.split(',')[1])) {
  209. bottom[1] = Number(item.location.split(',')[1]);
  210. }
  211. });
  212. window.map.setBounds( new AMap.Bounds(top, bottom));
  213. });
  214. };
  215. const getlocationaddr=(location,backcall) => {
  216. fetch(
  217. `https://restapi.amap.com/v3/geocode/regeo?location=${location}&key=1c7f1c8eda2ccbe7d0e125a7e2fc2a61`
  218. ).then((res) => res.json())
  219. .then((data) => {
  220. if (backcall) {
  221. backcall(data);
  222. }
  223. })
  224. }
  225. const getlocalname = (location) => {
  226. fetch(
  227. `https://restapi.amap.com/v3/geocode/regeo?location=${location}&key=1c7f1c8eda2ccbe7d0e125a7e2fc2a61`,
  228. // `${
  229. // import.meta.env.VITE_MAP_SERVER as string
  230. // }/service/lbs/reverse/v1/regeo?location=${location}&key=${window.key}`,
  231. )
  232. .then((res) => res.json())
  233. .then((data) => {
  234. setpoint(
  235. Number(location.split(',')[0]),
  236. Number(location.split(',')[1]),
  237. data.regeocode.formatted_address,
  238. );
  239. });
  240. };
  241. const getLocation = () => {
  242. if (navigator.geolocation) {
  243. navigator.geolocation.getCurrentPosition(
  244. (location1) => {
  245. var lat = null;
  246. var lon = null;
  247. var iserror = false;
  248. try {
  249. lat = location1.coords.latitude;
  250. lon = location1.coords.longitude;
  251. if (lat === null || lat === undefined) iserror = true;
  252. } catch (e) {
  253. iserror = true;
  254. }
  255. if (!iserror) {
  256. // debugger
  257. var location = `${lon},${lat}`;
  258. getlocalname(location);
  259. // setpoint(lon,lat,data.regeocodes[0].formatted_address)
  260. } else {
  261. // Notify({
  262. // type: 'danger',
  263. // message: 'App不支持地理定位。',
  264. // });
  265. }
  266. },
  267. (error) => {
  268. switch (error.code) {
  269. case error.PERMISSION_DENIED:
  270. alert('定位失败,用户拒绝请求地理定位');
  271. break;
  272. case error.POSITION_UNAVAILABLE:
  273. alert('定位失败,位置信息是不可用');
  274. break;
  275. case error.TIMEOUT:
  276. alert('定位失败,请求获取用户位置超时');
  277. break;
  278. }
  279. },
  280. );
  281. } else {
  282. alert('浏览器不支持地理定位。');
  283. }
  284. // api_getusergps().then((res) => {
  285. // var lat = null;
  286. // var lon = null;
  287. // var iserror = false;
  288. // try {
  289. // lat = res.result[0].lat;
  290. // lon = res.result[0].lon;
  291. // if (lat === null || lat === undefined) iserror = true;
  292. // } catch (e) {
  293. // iserror = true;
  294. // }
  295. // if (!iserror) {
  296. // // debugger
  297. // var location = `${lon},${lat}`;
  298. // getlocalname(location);
  299. // // setpoint(lon,lat,data.regeocodes[0].formatted_address)
  300. // } else {
  301. // // Notify({
  302. // // type: 'danger',
  303. // // message: 'App不支持地理定位。',
  304. // // });
  305. // }
  306. // });
  307. };
  308. return {
  309. map,
  310. mapselect,
  311. searchaddr,
  312. selectpoint,
  313. getLocation,
  314. getlocationaddr,
  315. };
  316. },
  317. render() {
  318. return (
  319. <div class={"mapselect-c"}>
  320. <Map
  321. v-model:map={this.map}
  322. style={{
  323. borderRadius: "2px",
  324. boxShadow: "0px 0px 0px 1px #d9d9d9;",
  325. height: "300px",
  326. }}
  327. />
  328. <ElButton
  329. type="primary"
  330. size="small"
  331. onClick={this.selectpoint}
  332. style={`position:absolute;right:10px;top:10px;${
  333. this.editable ? "" : "display:none"
  334. }`}
  335. >
  336. {this.mapselect ? "确定" : "选点"}
  337. </ElButton>
  338. <ElButton
  339. type="text"
  340. // size="large"
  341. onClick={this.getLocation}
  342. style={`position:absolute;right:10px;bottom:10px;${
  343. this.editable ? "" : "display:none"
  344. }`}
  345. >
  346. <el-icon size="25">
  347. <img src={icon_location_svg1} style={ 'width:30px'}></img>
  348. </el-icon>
  349. </ElButton>
  350. <img
  351. style={
  352. "width:20px;position:absolute;top:48%;left:48%;" +
  353. `${this.mapselect ? "" : "display:none"}`
  354. }
  355. src={icon_location}
  356. />
  357. </div>
  358. );
  359. }
  360. });