高德地图撒点组件

请添加图片描述

一、引入amap地图库 - public/index.html

<script type="text/javascript">window._AMapSecurityConfig = {securityJsCode: '地图密钥' }</script><scripttype="text/javascript"src="https://webapi.amap.com/maps?v=1.4.8&key=111111111111111111111111"></script>

二、组件 - DzvScatterMap

<template><div class="container-box"><div id="container"></div></div>
</template>
<script>
import { containerType, getLocation } from '@/utils/alipay'
import locationImg from '@/assets/images/location.png'const { AMap } = windowconst iconSize = 56
const defaultZoom = 12export default {name: 'DzvScatterMap',props: {lngLat: {type: Array,default: () => []},// 点位列表list: {type: Array,default: () => []},// 样式列表styles: {type: Array,default: () => []}},data() {return {map: null,cluster: null,mass: null,styleList: []}},watch: {lngLat: function(value) {if (value && value.length > 0) {this.initAMap()}},list: {deep: true,handler: function(newVal) {if (this.map) {this.markerMyPosition(this.lngLat)}}},styles: {deep: true,handler: function(newVal) {this.styleList = newVal?.map(it => ({...it,url: it?.src,anchor: new AMap.Pixel(6, 6),size: new AMap.Size(iconSize, 56),zIndex: 3}))}}},created() {},mounted() {this.initAMap()},methods: {// 初始化地图initAMap() {this.map = new AMap.Map('container', {zoom: defaultZoom, // 级别resizeEnable: true,center: [113.67621, 34.74499], // 默认中心点坐标viewMode: '2D' // 使用2D视图,使用3D在amap2.0中会旋转})this.markerMyPosition(this.lngLat)},// 标记自己的位置markerMyPosition(lngLat) {if (lngLat && lngLat.length > 0) {if (this.locationMarker) {this.map.remove(this.locationMarker)}this.locationMarker = new AMap.Marker({offset: new AMap.Pixel(-10, -10),position: new AMap.LngLat(lngLat[0], lngLat[1]),zoom: 13,content: `<div style="background-size: 100% 100%; height: 30px; width: 30px; background-image:url(${locationImg});"></div>`})if (this.map) {this.map.add(this.locationMarker) // 添加位置markerthis.map.setCenter(lngLat) // 设置中心this.map.setZoom(defaultZoom) // 重置缩放this.panBy() // 设置地图平移量,将marker移到中心}}// 地图加载完成后,进行撒点this.asyncMarker()},// 地图的平移panBy() {const refList = document.getElementById('refList')const height = refList?.offsetHeightif (height > 50) {// 地图中心点平移this.map.panTo(this.lngLat)// 像素值平移this.map.panBy(0, -height / 2)}},// 撒点getMarkerList(allPoints = {}, currentType = '') {// 洒点之前清除上次的洒点if (this.mass) this.mass.clear()if (this.list) {const serviceHall = this.list.map(item => {return {...item,lnglat: [item.siteCoordinateY, item.siteCoordinateX],style: item.typeId}})this.mass = new AMap.MassMarks(serviceHall, {opacity: 0.8,zIndex: 111,cursor: 'pointer',style: this.styleList})this.mass.on('click', this.markerClick)this.mass.setMap(this.map)this.$forceUpdate()}},// 类型和全部定位数据修改的时候进行延迟撒点,展示列表中的loading效果asyncMarker() {const _this = thissetTimeout(() => {const { allPoints, currentType } = _this_this.getMarkerList(allPoints, currentType)}, 5)},// 点击事件markerClick(e) {// const curentPoint = e.target.getExtData() || {}const currentPoint = e.data || {}this.$emit('changePoint', currentPoint)},// 获取当前位置async location() {if (containerType() === 'xcx' || containerType() === 'wechat') {// this.$emit('changeLngLat', this.lngLat)this.markerMyPosition(this.lngLat)} else {const lngLat = await getLocation()// this.$emit('changeLngLat', lngLat)this.markerMyPosition(lngLat)}}}
}
</script>
<style lang="scss" scoped>
.container-box {padding: 0px;margin: 0px;width: 100vw;height: calc(100vh - 50px);position: relative;
}
#container {padding: 0px;margin: 0px;width: 100%;height: 100%;position: absolute;
}
.location-icon {width: 40px;height: 40px;background: $white;border-radius: 10px;display: flex;justify-content: center;align-items: center;position: absolute;z-index: 20;right: 10px;top: 10px;
}
h3 {position: absolute;left: 10px;z-index: 2;color: white;
}
::v-deep {.amap-logo {z-index: -1;}.amap-copyright {z-index: -1;}
}
</style>

三、使用

2.1.home/index.vue

<template><div><HomePickers:types="types"@updateInfo="updateInfo":class="{ 'home-pickers': true, 'fade-out-picker': fadeOutPicker, 'fade-in-picker': fadeInPicker }"/><DzvScatterMapref="map":isInit="isInit":lngLat="lngLat":styles="styles":list="itemList"@changePoint="changePoint"><div id="container" slot="container"></div></DzvScatterMap><HomeBtns @btn="btnClick" ref="refList" id="refList" /><HomeSearch :class="{ 'home-search': true, 'fade-out-search': fadeOutSearch, 'fade-in-search': fadeInSearch }" /><HomeModal v-if="showModal" @changeShow="changeShow" :item="currentPoint" /></div>
</template><script>
import { getItemListApi, getClassListApi } from '@/api/home'
import { getLocation, checkAppPermissionHandler } from '@/utils/alipay'
import { countDistance } from '@/utils/index'
import HomePickers from './@component/pickers'
import HomeBtns from './@component/btns'
import HomeSearch from './@component/searches'
import HomeModal from './@component/modal'export default {components: { HomePickers, HomeBtns, HomeSearch, HomeModal },data() {return {isInit: true,currentPoint: null, // 当前点击的点位itemList: [],types: [], // 分类类型styles: [], // 地图撒点样式类型lngLat: null, // 自身params: {},pickerInfo: {},fadeOutPicker: false,fadeInPicker: false,fadeOutSearch: false,fadeInSearch: false,showModal: false // 是否显示选中区域模态框}},computed: {},created() {this.getClassList() // 查询分类this.getItemList() // 查询点位,郑州市不传areaCodethis.location() // 获取当前位置},mounted() {},methods: {getClassList() {getClassListApi().then(res => {if (res?.code === 0) {const types = res?.data?.map(it => ({ text: it?.name, value: it?.id }))types?.unshift({ text: '全部类型', value: undefined })this.types = typesthis.styles = res?.datathis.$refs.map.initAMap(this.lngLat) // 初始化地图}})},// 获取分类下10公里以内的数据,地图滑动重新请求getItemList() {checkAppPermissionHandler({ allowLocation: 'must' }, ({ status, location }) => {// const { longitude, latitude } = locationconst longitude = 113.58762const latitude = 37.86236getItemListApi({ ...this.params, longitude, latitude }).then(res => {if (res?.code === 0) {this.itemList = Object.freeze(res?.data.map(item => {const { meter, result } = countDistance(longitude, latitude, item.siteCoordinateY, item.siteCoordinateX)return {...item,distance: result,meter}}))this.$refs.map.initAMap(this.lngLat) // 初始化地图} else {this.$toast(res.message)}})})},changeShow() {this.showModal = !this.showModal},// 修改分类切换updateInfo(item) {this.params = { ...item }this.getItemList()},// 修改定位async changeLngLat(lngLat) {this.lngLat = lngLatthis.$forceUpdate()},// 获取当前定位并设置自己的位置async location() {getLocation(res => {const longitude = 113.77855const latitude = 34.759108const lngLat = [longitude, latitude]this.changeLngLat(lngLat)})},changePoint(val) {this.currentPoint = valthis.showModal = true},btnClick(val) {// 淡出if (val === 1) {this.fadeOutPicker = truethis.fadeOutSearch = truethis.fadeInPicker = falsethis.fadeInSearch = false}// 淡入if (val === 2) {this.fadeInPicker = truethis.fadeInSearch = truethis.fadeOutPicker = falsethis.fadeOutSearch = false}if (val === 3) {console.log('val', this.$refs.map.panBy, this.lngLat)// 回到当前位置this.$refs.map.panBy(this.lngLat)}}}
}
</script>
<style lang="scss" scoped>
.home-pickers {width: 100%;position: absolute;top: 0;z-index: 1000;
}
.home-search {width: 100%;position: absolute;bottom: 0;z-index: 999;
}
.fade-out-picker {animation: fadeOutPicker 1s ease forwards;
}@keyframes fadeOutPicker {0% {opacity: 1;transform: translateY(0);}100% {opacity: 0;transform: translateY(-100%);}
}.fade-out-search {animation: fadeOutSearch 1s ease forwards;
}@keyframes fadeOutSearch {0% {opacity: 1;transform: translateY(0);}100% {opacity: 0;transform: translateY(100%);}
}.fade-in-picker {animation: fadeInPicker 1s ease forwards;
}@keyframes fadeInPicker {0% {opacity: 0;transform: translateY(-100%);}100% {opacity: 1;transform: translateY(0);}
}
.fade-in-search {animation: fadeInSearch 1s ease forwards;
}@keyframes fadeInSearch {0% {opacity: 0;transform: translateY(100%);}100% {opacity: 1;transform: translateY(0);}
}
</style>

2.2.顶部选择器 - home/@component/pickers/index.vue

<template><div class="pickers"><van-dropdown-menu active-color="#2689FF"><van-dropdown-item v-model="area" :options="areas" @change="menuChange" /><van-dropdown-item v-model="type" :options="types" @change="menuChange" /><van-dropdown-item v-model="charge" :options="charges" @change="menuChange" /></van-dropdown-menu></div>
</template>
<script>
import { charges, areas } from '@/utils/constant'export default {name: 'HomePickers',props: {types: {type: Array,default: () => []}},data() {return {area: undefined,type: undefined,charge: undefined,areas,charges}},created() {},methods: {// 修改信息menuChange() {this.$emit('updateInfo', { area: this.area, type: this.type, charge: this.charge })}}
}
</script>
<style lang="scss">
.pickers {.van-dropdown-menu {.van-dropdown-menu__bar {background: linear-gradient(360deg, #d6fcff 0%, #ffffff 100%);box-shadow: 0px 2px 6px 0px rgba(129, 163, 203, 0.15);}.van-ellipsis {font-size: 16px;font-weight: 400;color: yellow;line-height: 22px;text-shadow: 0px 2px 12px rgba(100, 101, 102, 0.08);background: linear-gradient(307deg, #32b6ff 0%, #3562fe 100%);font-family: MaokenZhuyuanTi;-webkit-background-clip: text;-webkit-text-fill-color: transparent;}.van-dropdown-menu__title::after {border-color: transparent transparent #32b6ff #32b6ff;}}
}
</style>

2.3.底部搜索页 - home/@component/search/index.vue

<template><div class="searches"><div class="searches-box"><div class="search" @click="onSearch"><van-image width="18" height="18" :src="require('@/assets/images/search.png')" /><span class="text">搜索</span></div><div class="item"><div v-for="it in item" :key="it.value"><div class="it" @click="onJump(it)"><van-image :src="it.icon" width="50" height="50" /><span class="text">{{ it.text }}</span></div></div></div></div></div>
</template>
<script>
export default {name: 'HomeSearch',data() {return {item: [{ value: 1, text: '我要去', icon: require('@/assets/images/go.png'), url: '/go' },{ value: 2, text: '动态资讯', icon: require('@/assets/images/info.png'), url: '/news' },{ value: 3, text: '疫苗预约', icon: require('@/assets/images/vaccinum.png'), url: '' },{ value: 4, text: '入驻服务', icon: require('@/assets/images/enter.png'), url: '' }]}},created() {},methods: {onSearch() {this.$router.push({ path: '/search' })},onJump(item) {if (['http', 'https'].includes(item?.path?.split(':')?.[0])) {window.open(item.url)} else {this.$router.push({ path: item?.url })}}}
}
</script>
<style lang="scss">
.searches {height: 266px;width: 100%;background-image: url('~@/assets/images/search-bg.png');background-repeat: no-repeat;background-size: 100% 100%;&-box {width: 100%;height: 141px;margin-top: 125px;background: linear-gradient(360deg, #d6fcff 0%, #ffffff 100%);box-shadow: 0px 2px 6px 0px rgba(129, 163, 203, 0.15);border-radius: 24px 24px 0px 0px;.search {position: relative;top: 8px;margin: 0 17px;display: flex;align-items: center;justify-content: center;padding: 8px 0;background: rgba(67, 191, 243, 0.1);border-radius: 18px;border: 1px solid #43bff3;.text {margin-left: 4px;font-size: 14px;font-weight: 400;color: #43bff3;line-height: 20px;}}.item {position: relative;top: 12px;display: flex;justify-content: space-between;align-items: center;padding: 0 32px;.it {display: flex;justify-content: center;align-items: center;flex-direction: column;.text {font-size: 13px;font-weight: 700;color: #3562fe;line-height: 19px;background: linear-gradient(307deg, #32b6ff 0%, #3562fe 100%);-webkit-background-clip: text;-webkit-text-fill-color: transparent;}}}}
}
</style>

2.4.按钮 - home/@component/btns/index.vue

放大,缩小,当前位置定位

<template><div class="btns"><van-image:src="require('@/assets/images/enlarge.png')"width="67"height="67"@click="btnClick(1)":style="{ display: show ? 'block' : 'none' }"/><van-image:src="require('@/assets/images/lessen.png')"width="67"height="67"@click="btnClick(2)":style="{ display: !show ? 'block' : 'none' }"/><van-image :src="require('@/assets/images/focus.png')" width="67" height="67" @click="btnClick(3)" /></div>
</template>
<script>
export default {name: 'HomeBtns',data() {return {show: true}},methods: {btnClick(val) {if (val === 1 || val === 2) {this.show = !this.show}this.$emit('btn', val)}}
}
</script>
<style lang="scss">
.btns {position: absolute;bottom: 212px;z-index: 1100;right: 10px;display: flex;flex-direction: column;
}
</style>

2.5.home/@component/modal/index.vue

点击地图撒点目标点位弹框展示

<template><div class="modal"><van-overlay :show="true" class="overlay" @click="showModal"><div class="wrapper" @click="showModal"><div class="content"><div class="img"><van-image width="287" height="161" :src="item.url" /></div><div :class="{ text: true, name: true }">{{ item.name }}</div><div :class="{ text: true, intro: true }">{{ item.intro }}</div><div class="btn"><div class="bg" @click.stop="onCall(item.phone)">打电话</div><div class="bg" @click.stop="onMap(_, { ...item, lng: 30, lat: 113, siteName: '郑州东站' })">去这里</div></div></div></div></van-overlay></div>
</template>
<script>
import { onCall, onMap } from '@/utils/index'
export default {name: 'HomeModal',props: {item: {type: Object,default: () => ({ url: '' })}},data() {return { onCall, onMap }},methods: {showModal(val) {this.$emit('changeShow')}}
}
</script>
<style lang="scss">
.modal {.overlay {z-index: 1999;display: flex;justify-content: center;align-items: center;}.wrapper {width: 389px;height: 457px;background: url('~@/assets/images/modal_bg.png') -12px center / auto 100% no-repeat;.content {display: flex;justify-content: center;align-items: center;flex-direction: column;margin-top: 133px;.img {background: #d8d8d8;border-radius: 8px;overflow: hidden;}.text {font-family: PingFangSC-Medium, PingFang SC;max-width: 263px;}.name {font-size: 16px;font-weight: 500;color: #323233;line-height: 22px;margin: 12px 0 8px 0;}.intro {font-size: 14px;font-weight: 400;color: #969799;line-height: 20px;text-overflow: ellipsis;overflow: hidden;display: -webkit-box; /* 将此元素作为弹性伸缩盒模型展示 */-webkit-line-clamp: 2; /* 块级元素显示文本行数 */-webkit-box-orient: vertical; /* 设置或检索弹性伸缩盒子对象子元素的排列方式 */word-break: break-all; /* 文本存在英文单词时进行换行拆分 */}.btn {display: flex;justify-content: space-between;align-items: center;.bg {display: flex;justify-content: center;align-items: center;width: 154px;height: 61px;background: url('~@/assets/images/btn_bg.png') center center / auto 100% no-repeat;font-size: 16px;font-family: KingnamBobo-Bold, KingnamBobo;font-weight: bold;color: #ffffff;line-height: 25px;text-shadow: 0px 2px 4px rgba(101, 191, 255, 0.3), 0px 2px 2px rgba(18, 68, 221, 0.52);}}}}
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/163594.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

双通道 H 桥电机驱动芯片AT8833,软硬件兼容替代DRV8833,应用玩具、打印机等应用

上期小编给大家分享了单通道 H 桥电机驱动芯片&#xff0c;现在来讲一讲双通道的驱动芯片。 双通道 H 桥电机驱动芯片能通过控制电机的正反转、速度和停止等功能&#xff0c;实现对电机的精确控制。下面介绍双通道H桥电机驱动芯片的工作原理和特点。 一、工作原理 双通道 H 桥电…

计算机视觉基础——基于yolov5-face算法的车牌检测

文章目录 车牌检测算法检测实现1.环境布置2.数据处理2.1 CCPD数据集介绍2.1.1 ccpd2019及20202.1.2 文件名字解析 2.2数据集处理2.2.1 CCPD数据处理2.2.2 CRPD数据集处理 2.3 检测算法2.3.1 数据配置car_plate.yaml2.3.2 模型配置2.3.3 train.py2.3.4 训练结果 2.4 部署2.4.1 p…

Nat. Commun.:碱土亚胺负载催化剂的多反应途径高效合成氨

探索高效、低成本的合成氨催化剂需要反应途径的可调性&#xff0c;但由于比例关系的限制而还存在困难。基于此&#xff0c;上海交通大学叶天南教授、日本东京工业大学Hideo Hosono和Masaaki Kitano等人报道了碱土亚胺&#xff08;AeNH&#xff09;与过渡金属&#xff08;TMFe、…

读完大呼过瘾的计算机书籍

目录 一导论 二《算法导论》 三《深入理解计算机系统》 四《代码大全》 五《设计模式&#xff1a;可复用面向对象软件的基础》 六《人月神话》 七总结 一导论 作为一个计算机专业的爱好者&#xff0c;我发现计算机科学和技术领域充满了无穷无尽的可能性。在探索这个世界…

欧洲卖家注意,多个平台收紧欧盟合规要求,合规要抓紧!!!

作为跨境电商的老牌消费市场&#xff0c;欧洲市场有着旺盛的需求&#xff0c;对卖家来说非常重要&#xff1b;但同时&#xff0c;近年来欧洲对合规的要求也越来越严格。 近期各大平台都收到了欧盟合规要求&#xff0c;从亚马逊、eBay、再到SHEIN、速卖通、Temu等&#xff0c;从…

缓存-Spring Cache 缓存抽象

缓存-Spring Cache 缓存抽象 Spring从版本3.1开始提供非侵入的将Cache集成到Spring应用的方式。Spring Cache提供Cache的统一抽象&#xff0c;支持集成各种不同的缓存解决方案。从4.1版本开始&#xff0c;提供了注解和更多的定制参数。 Spring Cache 抽象提供了对Java方法的缓存…

APM建设踩了哪些坑?去哪儿旅行分布式链路追踪系统实践

一分钟精华速览 分布式链路追踪系统在企业的APM体系中扮演着重要的角色。本文分享了去哪儿旅行构建分布式链路追踪系统的实践经验。从APM整体架构设计入手&#xff0c;讲述了日志收集、Kafka传输和Flink任务处理等环节的性能优化实践和踩坑经验。 同时&#xff0c;作者结合丰…

持续集成交付CICD:安装Jenkins Slave(从节点)

目录 一、实验 1.安装Jenkins Slave&#xff08;从节点&#xff09; 二、问题 1.salve节点启动jenkins报错 2.终止命令行后jenkins从节点状态不在线 一、实验 1.安装Jenkins Slave&#xff08;从节点&#xff09; &#xff08;1&#xff09;查看jenkins版本 Version 2.…

技术干货 | GreatDB新一代读写分离架构,如何炼就近乎0损耗的性能?

优化数据库性能并降低成本是每位架构师和DBA都必须面对的挑战。其中&#xff0c;读写分离是一种常见方法&#xff1a;即通过将读操作和写操作分发到不同的数据库实例&#xff0c;实现多副本负载和性能提升。 传统的中间件方案&#xff0c;例如基于Proxysql、HAProxy、MySQL Ro…

【hcie-cloud】【1】华为云Stack解决方案介绍、华为文档获取方式 【上】

文章目录 华为文档获取方式前言云计算发展背景国家政策、社会发展驱动数字经济开启新时代深化数字化转型提升效率&#xff0c;国家数字主权云进入落地阶段从Cloud-Based到Cloud-Native&#xff0c;两种模式长期并存适合政企智能升级的云华为云Stack&#xff0c;政企智能升级首选…

Spring Boot 统一处理功能

目录 1.用户登陆权限验证 1.1 每个方法验证 1.2 Spring AOP 用户统一登陆验证 1.3 拦截器 1.3.1 自定义拦截器 1.3.2 将自定义拦截器配置到系统设置中&#xff0c;并且设置拦截规则 1.3.3 排除所有的静态资源 1.4 登录拦截器&#xff08;练习&#xff09; 1.5 拦截器原…

在Windows或Mac上安装并运行LLAMA2

LLAMA2在不同系统上运行的结果 LLAMA2 在windows 上运行的结果 LLAMA2 在Mac上运行的结果 安装Llama2的不同方法 方法一&#xff1a; 编译 llama.cpp 克隆 llama.cpp git clone https://github.com/ggerganov/llama.cpp.git 通过conda 创建或者venv. 下面是通过conda 创建…