思路解析:使用小程序的 map 地图组件 ,markers 标记点数据集合 用来生产地图上的标记,用callout 或者label 实现气泡,本文使用的是callout ,最后如何实现点击气泡更新下方展示数据,使用到的是 markers的id属性(注意一定是数字类型不可是字符串)
最终实现效果图
语法使用的是uniapp,原生小程序和uniapp实现方式大致一致
html
<template>
<view class="owarp">
<view class="head">...</view>
<!-- 地图展示区域 -->
<view class="center">
<map id="map"
:scale="scale"
:latitude="lat"
:longitude="lng"
:markers="markers"
show-location=true
@regionchange="changeRegion"
@callouttap="handleCallout"
>
</map>
</view>
<view @click="returnCur" class="gps flex column acenter jcenter">
<image class="icon44" src="/static/images/home/homesearch.png" mode=""></image>
<view class="fs20">定位</view>
</view>
<view class="foot">
<view class="flex">
<image class="imgradus" :src="roomData.main_picture" mode="aspectFill"></image>
<view class="ml20">
<view class="fs32 b">{{roomData.hotel_name}}</view>
<view class="fs24 c8c mt6 w500 ellipsis">距您约 {{roomData.distance}} km</view>
<view class="flex acenter mt6">
<image class="icon22" src="/static/images/location.png" mode=""></image>
<view class="fs24 w500 ellipsis">{{roomData.hotel_address}}</view>
</view>
<view class="mt6">
<text class="b fs24 red">¥</text>
<text class="b fs40 red">{{roomData.lowest_price}}</text>
<text class="fs24 c8c">起</text>
</view>
</view>
</view>
<scroll-view class="itemHeight mt20" scroll-x="true">
<view class="itemdata" v-for="(item,i) in roomData.room_type" :key="i">
<view class="flex h174 acenter column between">
<view class="fs28 themeColor tittop ellipsis">{{item.room_type_name}}</view>
<view class="fs24 themeColor mt7">{{item.desc}}</view>
<view class="mt7">
<text class="b fs22 red">¥</text>
<text class="b fs34 red">{{item.current_price}}</text>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
js
<script>
export default {
data(){
return{
lat:'',
lng:'',
scale:13,
roomData:'',
markers:[],
localtion:'',
mapCtx:''
}
},
onShow() {
//获取用户定位经纬度
this.localtion = uni.getStorageSync('localtion')?JSON.parse(uni.getStorageSync('localtion')):''
this.lat = this.localtion.lat
this.lng = this.localtion.lng
},
mounted(){
this.getData()
},
methods:{
getData(){ //获取数据生成markers标记
this.$http('xxx', 'POST', { //换成自己的接口
lng: this.localtion.lng,
lat:this.localtion.lat,
city_id:this.address.code
}).then((res) => {
var maplist = res.data.list
this.setMarkers(maplist)
})
},
getRoomType(markId){ //获取对应的数据渲染最下方内容
this.$http('xxx', 'POST', {
lng: this.localtion.lng,
lat:this.localtion.lng,
hotel_id:markId
}).then((res) => {
this.roomData = res.data
})
},
changeRegion(){ //中心点标记始终在地图中心位置不动
let that = this;
this.mapCtx = uni.createMapContext('map');
this.mapCtx.getCenterLocation({
success(res) {
const latitude = res.latitude
const longitude = res.longitude
that.lat=latitude
that.lng=longitude
}
})
},
handleCallout(e){ //点击气泡获取验薪数据
var markId = e.detail.markerId
this.getRoomType(markId)
},
returnCur(){ //点击定位图片 设置中心点回到最原始的位置
this.lat = this.localtion.lat
this.lng = this.localtion.lng
},
setMarkers(maplist){ //设置标记点
//具体属性含义和用法可参照官方文档
maplist.forEach((item)=>{
this.markers.push({
latitude: item.lat,
longitude: item.lng,
id:item.hotel_id, //id 要为数字类型,不能为字符串(字符串会生成其他的值和绑定值不一致)
callout:{
content:item.hotel_name+' '+'¥'+item.current_price+'起',
bgColor:'#078591',
color:'#fff',
padding:'5',
fontSize:'13',
display:'ALWAYS',
textAlign:'center',
borderRadius:'14',
padding:'7'
}
})
})
}
}
}
</script>
css
<style lang="scss" scoped>
.head{
height: 86rpx;
background: #fff;
padding: 0 30rpx;
.tobtm{
width: 10rpx;
height: 10rpx;
}
}
.mt7{
margin-top: 7rpx;
}
.w500{
width: 500rpx;
}
.fb{
color: #FB5E5E;
}
.imgradus{
width: 160rpx;
height: 160rpx;
border-radius: 9rpx;
}
.center{
width: 750rpx;
height:calc(100vh - 545rpx);
}
#map{
width: 750rpx;
height: 100%;
position: relative;
.img-map{
position: absolute;
width: 26rpx;
height: 40rpx;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
}
.gps{
position: fixed;
bottom: 550rpx;
right: 30rpx;
width: 84rpx;
height: 84rpx;
background: #FFFFFF;
border-radius: 10rpx;
border: 1px solid #ABABAB;
}
.foot{
height: 459rpx;
background: #fff;
position: fixed;
bottom: 0;
width: 100%;
border-radius: 24rpx 24rpx 0 0;
padding: 40rpx 30rpx;
box-sizing: border-box;
.itemHeight{
height: 175rpx;
width: 100%;
white-space: nowrap;
.itemdata{
width: 260rpx;
height: 174rpx;
background: #EBF5F6;
border-radius: 10rpx;
display: inline-block;
margin-right: 20rpx;
box-sizing: border-box;
}
.h174{
padding: 20rpx;
height: 174rpx;
box-sizing: border-box;
}
.tittop{
width: 220rpx;
text-align: center;
}
}
}
</style>
到此结束