在index.html中引入百度地图API
<script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=你的秘钥">
在vue3中引用
<template>
<div id="container" style="width: 100vw;height:100vh"></div>
</template>
<script setup>
import {ref,onMounted,inject} from "vue"
let axios=inject("$axios")
const BMapGL = window.BMapGL;
onMounted(() => {
getTu()
})
const getTu = () => {
const cityname = JSON.parse(sessionStorage.getItem('cityName'))
console.log(cityname);
const name = cityname.name
const code = cityname.code
const map = new BMapGL.Map("container");
//创建地址解析器实例
var myGeo = new BMapGL.Geocoder();
myGeo.getPoint(name, function (point) {
if (point) {
// 地图初始化,同时设置地图展示级别
map.centerAndZoom(point, 11);
// 5.添加控件
const scaleCtrl = new BMapGL.ScaleControl(); // 添加比例尺控件
map.addControl(scaleCtrl);
const zoomCtrl = new BMapGL.ZoomControl(); // 添加缩放控件
map.addControl(zoomCtrl);
renderOverlays(code, map)
}
}, name)
}
// 房源覆盖物的样式
const labelStyle =ref( {
border: 0,
background: "rgba(12, 181, 106, 0.9)",
color: 'black'
})
// 封装渲染房源覆盖物的方法
const renderOverlays = async (code,map) => {
// 调用接口获取房源数据
// console.log(code,map);
const {data} = await axios.get('http://shiyansong.cn:8080/area/map?id=' + code);
console.log(data);
const { type, nextZoom } = getTypeAndZoom(map);
data.body.forEach(item => {
createOverlays(item, type, nextZoom, map)
})
}
// 封装计算类型和获取地图缩放级别的方法
const getTypeAndZoom = (map) => {
// 获取当前地图的缩放级别
// let map = new BMapGL.Map("container");
const zoom = map.getZoom();
// console.log(1, zoom)
let type, nextZoom;
if (zoom >= 0 && zoom < 12) { // 区
type = 'circle'
// 下一次的缩放级别
nextZoom = 13;
} else if (zoom >= 12 & zoom < 14) { // 镇
type = 'circle'
// 下一次的缩放级别
nextZoom = 15;
} else if (zoom >= 14 && zoom < 16) { // 小区
type = 'rect';
}
return { type, nextZoom, map }
}
// 封装创建覆盖物的方法
const createOverlays = (data, type, zoom, map) => {
// 为每一条数据创建房源覆盖物
const { label: areaName, value, coord: { longitude, latitude }, count } = data;
// 根据指定经纬度创建坐标点
const areaPoint = new BMapGL.Point(longitude, latitude)
if (type === 'circle') { // 区、镇
createCircle(areaPoint, areaName, value, count, zoom, map)
} else {
createRect(areaPoint, areaName, value, count, map);
}
}
// 创建区镇的覆盖物
const createCircle = (areaPoint, areaName, value, count, zoom, map) => {
// 1. 创建文房源覆盖物
const label = new BMapGL.Label('', { // 创建文本儿标注
position: areaPoint, // 设置文本标注的坐标
offset: new BMapGL.Size(10, 20) // 设置文本标注的偏移量
})
// 2. 给label对象添加一个唯一标识
label.id = value;
// 3. 调用setContent方法设置文本标注的内容
label.setContent(`
<div class="bubble">
<p class="name">${areaName}</p>
<p>${count}套</p>
</div>
`)
// 4. 将标注添加到地图中
map.addOverlay(label);
// 5. 修改文本标注的样式
label.setStyle(labelStyle.value)
// 6.监听标注事件
label.addEventListener('click', () => {
renderOverlays(label.id, map)
// 7. 以当前点为中心放大地图
map.centerAndZoom(areaPoint, zoom)
// 8. 调用clearOverlay方法清除所有覆盖物
map.clearOverlays();
})
}
// 创建小区的覆盖物
const createRect = (areaPoint, areaName, value, count, map) => {
// 1. 创建文房源覆盖物
const label = new BMapGL.Label('', { // 创建文本儿标注
position: areaPoint, // 设置文本标注的坐标
offset: new BMapGL.Size(10, 20) // 设置文本标注的偏移量
})
// 2. 调用setContent方法设置文本标注的内容
label.setContent(`
<div class="housewrapper">
<span class="housename">${areaName}</span>
<span class="housecount">${count}套</span>
<i class="arrow"></i>
</div>
`)
// 3. 将标注添加到地图中
map.addOverlay(label);
// 4. 修改文本标注的样式
label.setStyle(labelStyle.value)
// 5.监听标注事件
label.addEventListener('click', (ev) => {
console.log('点击了小区的覆盖物')
getHouseList(value)
// 获取到经纬度
const { lng, lat } = ev.target.point.latLng;
// 将经纬度转换成像素坐标
const { x, y } = map.pointToPixel(new BMapGL.Point(lng, lat))
// 调用panBy方法移动地图到中心位置
map.panBy(
(window.innerWidth / 2) - x,
(window.innerHeight - 330) / 2 - y
)
})
// 给地图添加移动事件隐藏房源列表
map.addEventListener('movestart', () => {
setIsShow(false);
})
}
// 封装获取小区的房源数据的方法
const getHouseList = async id => {
const {data} = await axios.get('http://shiyansong.cn:8080/houses?cityId=' + id);
// setHouseList(data.body.list)
// 将isShow的值设置成true,执行动画显示房源列表
// setIsShow(true)
}
// 封装渲染小区房源数据的方法
const renderHouseList = () => {
// return (
// houseList.map(item => (
// <li className='house-list-item' key={item.houseCode}>
// <img src={"http://shiyansong.cn:8080" + item.houseImg} alt="" />
// <div className="right">
// <h3 className="title">{item.title}</h3>
// <div className="desc">{item.desc}</div>
// {
// item.tags.map((tag, index) => (
// <span key={tag} className={['tag', 'tag' + (index + 1)].join(' ')}>{tag}</span>
// ))
// }
// <div className="price-wrapper">
// <span className='price'>{item.price}</span>
// <span>元/月</span>
// </div>
// </div>
// </li>
// ))
// )
}
</script>
<style lang="scss" scoped>
.map-wrapper {
height: 100%;
display: flex;
flex-direction: column;
.container {
flex: 1;
}
}
.bubble {
display: inline-block;
position: absolute;
width: 70px;
height: 70px;
background: rgba(12, 181, 106, 0.9);
border: 2px solid #fff;
border-radius: 50%;
font-size: 12px;
text-align: center;
line-height: 1;
overflow: hidden;
.name {
padding: 18px 0 6px
}
}
.housewrapper {
position: absolute;
padding: 0 3px;
width: 100px;
height: 20px;
line-height: 19px;
background:rgba(12, 181, 106, 0.9);
border-radius: 3px;
text-align: center;
.housename {
display: inline-block;
width: 70px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: middle;
}
.housecount {
display: inline-block;
width: 20px;
}
.arrow {
display: block;
margin: 0 auto;
width: 0;
height: 0;
border: 4px solid transparent;
border-top-color: #00a75b;
}
}
// 小区房源列表
.house-container {
position: fixed;
bottom: 0;
left: 0;
z-index: 99;
display: flex;
flex-direction: column;
width: 100%;
max-height: 330px;
transform: translate3d(0, 100%, 0);
background: #fff;
transition: all 1s;
&.show-house {
transform: translate3d(0, 0, 0);
}
.house-title-wrapper {
padding: 0 10px;
height: 44px;
display: flex;
justify-content: space-between;
align-items: center;
background: #C0C0C2;
h3 {
font-size: 16px;
}
span {
padding-right: 5px;
color: #1e1e1e;
}
}
.house-list-wrapper {
flex: 1;
overflow: auto;
.house-list {
padding: 0 10px;
.house-list-item {
padding: 20px 0;
display: flex;
border-bottom: 1px solid #e5e5e5;
img {
width: 106px;
height: 80px;
}
.right {
margin-left: 10px;
flex: 1;
overflow: hidden;
.title {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: #394043;
}
.desc {
margin: 5px 0;
font-size: 12px;
color: #afb2b3;
}
.tag {
padding: 4px 5px;
margin-right: 5px;
font-size: 12px;
border-radius: 2px;
&.tag1 {
background: #e1f5f8;
color: #39becd;
}
&.tag2 {
background: #e1f5fd;
color: #3fc28c;
}
&.tag3 {
background: #e6f2ff;
color: #5aabfd;
}
}
.price-wrapper {
margin-top: 5px;
color: #fa5741;
.price {
font-size: 16px;
font-weight: bolder;
}
}
}
}
}
}
}
</style>