目录
效果图
总代码
分析
1.template 页面
地图显示代码
2. onload
①经纬度
②取值
③注意
④
3.methods
① 先发送 getStationList 请求 获取 数组列表信息
② regionChange 视野发生变化时 触发 分页逻辑
③ callouttap 点击气泡时触发 查找 当前 marker id 等于 stationId 的数组
(4)style样式
使用样式穿透 可以改变输入框输入的字体颜色
效果图
这个效果是 进入当前页面显示自己的经纬度 并 根据 pageSize,pageNum 显示当前pageSize条数据,在地图视野发生改变时 进行 this.pageNum * this.pageSize >= this.total 判断,让this.pageNum++ ,让所有的数据显示在地图上
总代码
<template>
<view>
<view class="map-container">
<map style="width: 100%; height: 100vh;" :show-location='true' ref="map" id="map" :latitude="latitude"
:longitude="longitude" :markers="marker" :scale="scale" @callouttap='callouttap' @regionchange="regionChange"
v-if="mapShow">
<view class="cover-view">
<view style="margin-top: 20rpx;" @click="onControltap">
<image class="cover-image" src="/static/images/location.png"></image>
<view>定位</view>
</view>
</view>
</map>
</view>
<view class="search" :style="{top:topHeight+'px'}">
<searchBar @click="search" :city="city"></searchBar>
</view>
<cardList :stationList="markerIdClick" v-if="tag" style="position: fixed;top: 70%;"></cardList>
<tabbar :current="current"></tabbar>
</view>
</template>
<script>
export default {
data() {
return {
mapShow: false,
topHeight: 20,
tag: false,
latitude: '', //纬度
longitude: '', //经度
scale: 12, //缩放级别
current: 1,
marker: [],
pageSize: 10,
pageNum: 1,
total: 0, // 总数据量
markerIdClick: [],
mapList: [],
}
},
async onLoad() {
let userLocation = uni.getStorage({
key: 'userLocation'
})
await userLocation.then(data => {
let arr = data[1].data.split(',')
this.longitude = arr[0]
this.latitude = arr[1]
console.log(arr);
})
this.getStationList()
const {
height,
top
} = uni.getMenuButtonBoundingClientRect();
this.topHeight = height + top + 13
},
methods: {
search(searchInp) {
console.log('search页面子向父传值', searchInp);
},
regionChange() {
this.tag = false
if (this.pageNum * this.pageSize >= this.total) return
this.pageNum++
this.getStationList()
},
//定位
onControltap() {
uni.createMapContext("map", this).moveToLocation({ //moveToLocation将地图中心移动到当前定位点,需要配合map组件的show-location使用
latitude: this.latitude,
longitude: this.longitude,
});
console.log('定位');
},
//气泡点击事件
callouttap(e) {
let id = String(e.detail.markerId)
let arr = this.mapList.find(item => {
return item.stationId === id
})
this.markerIdClick = [arr]
this.tag = true
},
async getStationList() {
console.log('发送请求前 打印用户经纬度', this.latitude, this.longitude);
const {
data: {
obj,
msg,
resCode
}
} = await uni.$http.post('/uniapp/pile/queryStationInfos', {
pageSize: this.pageSize,
pageNum: this.pageNum,
stationLng: this.longitude,
stationLat: this.latitude
})
console.log('queryStationInfos,信息列表显示总数据', obj, msg, resCode);
if (resCode !== "00100000") return uni.$showMsg()
this.total = obj.total
obj.list.forEach(item => {
this.marker.push({
id: Number(item.stationId),
iconPath: '/static/images/mapStation.png', //显示的图标
title: item.stationName,
latitude: Number(item.stationLat),
longitude: Number(item.stationLng),
width: 30,
height: 30,
callout: { //气泡窗口
content: '空闲' + item.totalFree, //文本
color: '#ffffff',
fontSize: 15,
borderRadius: 15,
padding: '10',
bgColor: '#406390',
display: 'ALWAYS', //常显
}
})
})
this.mapShow = true
this.mapList = this.mapList.concat(obj.list)
console.log(this.marker);
// for (let index in obj.list) {
// let stationMarker = {
// iconPath: '/static/images/mapStation.png', //显示的图标
// id: Number(index) || 0,
// title: this.mapList[index].stationName || '',
// latitude: Number(this.mapList[index].stationLat),
// longitude: Number(this.mapList[index].stationLng),
// width: 30,
// height: 30,
// callout: { //气泡窗口
// content: '空闲' + this.mapList[index].totalFree, //文本
// color: '#ffffff', //文字颜色
// fontSize: 15, //文本大小
// borderRadius: 15, //边框圆角
// padding: '10',
// bgColor: '#406390', //背景颜色
// display: 'ALWAYS', //常显
// }
// }
// // console.log(stationMarker, 'stationMarker');
// this.marker.push(stationMarker)
// }
}
}
}
</script>
<style scoped lang="scss">
/deep/ .uni-searchbar__box-search-input {
color: #fff !important;
}
.search {
position: fixed;
width: 80%;
}
.map-container {
margin-top: -40rpx;
position: relative;
overflow: hidden;
border-radius: 50rpx 50rpx 0 0;
.cover-view {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* width: 80rpx;
height: 160rpx; */
padding: 42rpx 22rpx;
color: #4F575F;
font-weight: 400;
background-color: #fff;
background-size: 120rpx 120rpx;
background-position: center center;
position: absolute;
top: 150rpx;
right: 32rpx;
border-radius: 15rpx;
}
.cover-image {
display: inline-block;
width: 50rpx;
height: 50rpx;
}
}
</style>
分析
1.template 页面
(1)
<tabbar :current="current"></tabbar> current:1 此页面是自定义tab栏
(2)
<view class="search" :style="{top:topHeight+'px'}">
<searchBar @click="search" :city="city"></searchBar>
</view>
动态style 就是为了 让输入框 在 胶囊下侧的位置,searchBar是我封装的组件
效果图
(3)
<cardList :stationList="markerIdClick" v-if="tag" style="position: fixed;top: 70%;"></cardList>
是我封装的组件, v-if=“tag” 默认不显示,当我点击气泡时出现的 卡片信息
(4)
地图显示代码
<view class="map-container">
<map style="width: 100%; height: 100vh;" :show-location='true' ref="map" id="map" :latitude="latitude"
:longitude="longitude" :markers="marker" :scale="scale" @callouttap='callouttap' @regionchange="regionChange"
v-if="mapShow">
<view class="cover-view">
<view style="margin-top: 20rpx;" @click="onControltap">
<image class="cover-image" src="/static/images/location.png"></image>
<view>定位</view>
</view>
</view>
</map>
</view>
在 map组件 中,我只使用到了 下面那两种方法
①@regionchange
当视野发生改变时,里面进行分页处理,
②@callouttap
点击标记点时 出现卡片内容
2. onload
此页面一进来
首先就是要 获取经纬度 使用这种方法获取 是因为 前面使用高德 amap-wx.130.js,这个文件帮我们把用户的经纬度存储起来了,我们只需 取就行 (注意在 amap-wx.130.js 文件中 将里面所以的 wx,替换为 uni )
①经纬度
let userLocation = uni.getStorage({
key: 'userLocation'
})
②取值
打印 userLocation 它的结果为 promise
因此我们要 使用promise。then的方法取值 并赋值
③注意
最开始在onload 里 下面的
this.getStationList() 这个请求先执行,后打印经纬度,这时请求里的经纬度 就为空,
因此 加 async await,可以先获取经纬度 然后在拿经纬度发送请求
④
this.topHeight = height + top + 13
这个 13 可加可不加 根据你们原型图高度来定
async onLoad() {
let userLocation = uni.getStorage({
key: 'userLocation'
})
await userLocation.then(data => {
let arr = data[1].data.split(',')
this.longitude = arr[0]
this.latitude = arr[1]
console.log(arr);
})
this.getStationList()
const {
height,
top
} = uni.getMenuButtonBoundingClientRect();
this.topHeight = height + top + 13
// console.log(this.topHeight, '高度');
},
3.methods
① 先发送 getStationList 请求 获取 数组列表信息
先获取到 obj.list (列表数组)创建一个新的 marker数组
这里要注意 先获取到 obj.list (列表数组)创建一个新的 marker数组 后 要先 forEach,push (或 for ,push)返回一个 marker数组
这里的id 不能使用 index 代替 ,还有 id 、latitude 、longitude 必须是 Number类型 因为我这数据是用分页处理 若是 使用index,会有重复的id,会导致在缩放地图时 有些 marker 消失,
obj.list.forEach(item => {
// console.log(item, 'foreach');
this.marker.push({
id: Number(item.stationId),
iconPath: '/static/images/mapStation.png', //显示的图标
title: item.stationName,
latitude: Number(item.stationLat),
longitude: Number(item.stationLng),
width: 30, //宽
height: 30, //高
callout: { //自定义标记点上方的气泡窗口 点击有效
content: '空闲' + item.totalFree, //文本
color: '#ffffff', //文字颜色
fontSize: 15, //文本大小
borderRadius: 15, //边框圆角
padding: '10',
bgColor: '#406390', //背景颜色
display: 'ALWAYS', //常显
}
})
})
后合并obj.list 数组 并赋值
this.mapList = this.mapList.concat(obj.list) (视野范围方法里需要使用 )
async getStationList() {
console.log('发送请求前 打印用户经纬度', this.latitude, this.longitude);
const {
data: {
obj,
msg,
resCode
}
} = await uni.$http.post('/uniapp/pile/queryStationInfos', {
pageSize: this.pageSize,
pageNum: this.pageNum,
stationLng: this.longitude,
stationLat: this.latitude
})
console.log('queryStationInfos,查询充电站信息列表显示总数据', obj, msg, resCode);
if (resCode !== "00100000") return uni.$showMsg()
this.total = obj.total
// console.log('充电站信息列表 mapList', obj.list);
obj.list.forEach(item => {
// console.log(item, 'foreach');
this.marker.push({
id: Number(item.stationId),
iconPath: '/static/images/mapStation.png', //显示的图标
title: item.stationName,
latitude: Number(item.stationLat),
longitude: Number(item.stationLng),
width: 30, //宽
height: 30, //高
callout: { //自定义标记点上方的气泡窗口 点击有效
content: '空闲' + item.totalFree, //文本
color: '#ffffff', //文字颜色
fontSize: 15, //文本大小
borderRadius: 15, //边框圆角
padding: '10',
bgColor: '#406390', //背景颜色
display: 'ALWAYS', //常显
}
})
})
this.mapShow = true
this.mapList = this.mapList.concat(obj.list)
console.log(this.marker);
// for (let index in this.mapList) {
// let stationMarker = {
// iconPath: '/static/images/mapStation.png', //显示的图标
// id: Number(index) || 0,
// title: this.mapList[index].stationName || '',
// latitude: Number(this.mapList[index].stationLat),
// longitude: Number(this.mapList[index].stationLng),
// width: 30, //宽
// height: 30, //高
// callout: { //自定义标记点上方的气泡窗口 点击有效
// content: '空闲' + this.mapList[index].totalFree, //文本
// color: '#ffffff', //文字颜色
// fontSize: 15, //文本大小
// borderRadius: 15, //边框圆角
// padding: '10',
// bgColor: '#406390', //背景颜色
// display: 'ALWAYS', //常显
// }
// }
// // console.log(stationMarker, 'stationMarker');
// this.marker.push(stationMarker)
// }
}
② regionChange 视野发生变化时 触发 分页逻辑
regionChange() {
this.tag = false
if (this.pageNum * this.pageSize >= this.total) return
this.pageNum++
this.getStationList()
},
③ callouttap 点击气泡时触发 查找 当前 marker id 等于 stationId 的数组
这里要注意下类型的一个转换 e.detail.markerId --> 是 marker id 它是数字类型
而 mapList 里面的 stationId 为 字符串 类型 ,因此这要做个类型转换,若不转换的话,点击所有的 气泡,卡片上面的内容 是显示一样的
callouttap(e) {
let id = String(e.detail.markerId)
// console.log(this.mapList, id);
let arr = this.mapList.find(item => {
return item.stationId === id
})
this.markerIdClick = [arr]
// console.log('点击id', id, '数组', this.markerIdClick);
this.tag = true
},
(4)style样式
/deep/ .uni-searchbar__box-search-input {
color: #fff !important;
}
输入框默认 黑色