前言
在写react中需要使用地图的一个定位功能,vue是有这个入口文件的,在umi里面默认没有这个入口文件,所以需要通过自己创建ejs文件,插件结合的方式进行实现
一、用插件把链接添加到页面上
1.在在src/page下 ,新建文件 plugins/mapPlugin.js
export default (api, opts) => {
// 在HTML尾部添加脚本
api.addHTMLScripts(() => {
return [
{
// 百度地图
src: '//api.map.baidu.com/api?v=3.0&ak=AK码',
},
];
});
};
2.在umirc.ts中导入本地新建的插件文件mapPlugin.js
/**
umi 的路由文件
*/
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [],
fastRefresh: {},
plugins:['./src/pages/plugins/mapPlugin.js']
});
二、手动添加ejs模板引擎
<!Doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta name="format-detection" content="telephone=no"/>
<meta name="format-detection" content="email=no"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<title> </title>
<script src="//api.map.baidu.com/api?v=3.0&ak=AK码"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
// Map组件
import { Navbar, Popup } from 'tdesign-mobile-react';
// import { ChevronLeftIcon } from 'tdesign-icons-react';
import { getMap } from '@/utils/api/home.js'
import { useEffect, useState } from 'react';
import './index.less'
import { useLocation } from 'umi';
export default function MapPage() {
const location = useLocation()
let [isShow, setIsShow] = useState(false)
const [visible, setVisible] = useState(false)
const handleVisibleChange = (visible: any) => {
setVisible(visible);
}
useEffect(() => {
initMap()
}, [])
const initMap = () => {
// 获取当前定位城市
// JSON.parse(sessionStorage.getItem('hkzf_city')||'') |||window.sessionStorage.getItem('currentCity')
const { label, value } = JSON.parse(JSON.stringify({ label: "北京", value: "AREA|88cff55c-aaa4-e2e0", pinyin: "beijing", short: "bj" }))
// 初始化地图实例
var map = new BMap.Map("container");
// 创建地址解析器实例
var myGeo = new BMap.Geocoder();
// 将地址解析结果显示在地图上,并调整地图视野
myGeo.getPoint(label, async (point: any) => {
if (point) {
//缩放
map.centerAndZoom(point, 11);
//添加标记
map.addOverlay(new BMap.Marker(point))
//添加控件
map.addControl(new BMap.ScaleControl())
// map.addControl(new BMap.ZoomControl())
renderOverLays(value, 11, map, point)
} else {
alert('您选择的地址没有解析到结果!');
}
}, label)
map.addEventListener('movestart', () => {
if (isShow) {
setIsShow(false)
}
})
}
// 创建区, 镇覆盖物
const createCircle = (item: any, zoom: any, map: any, point: any) => {
const { coord: { longitude, latitude }, label: areaName, count, value } = item
const areaPoint = new BMap.Point(longitude, latitude)
//添加文本覆盖物
const opts = {
position: areaPoint,
offset: new BMap.Size(30, -30)
}
//注意:设置setContent以后,第一个参数中设置的文本内容就失效了,因此直接清空即可
const label = new BMap.Label('', opts)
//设置房源覆盖物内容
label.setContent(`
<div class="contest-box" key=${value}>
<p class="text-bxo">${areaName}</p>
<p class="text-bxo">${count}套</p>
</div>
`)
//设置样式
const labelStyle = {
cursor: 'pointer',
border: '2px solid white',
whiteSpace: 'nowrap',
fontSize: '12px',
textAlign: 'center',
borderRadius: '50%',
width: '65px',
height: '65px',
background: 'rgba(38, 191, 110, 0.9)'
}
label.setStyle(labelStyle)
zoom += 2
if (zoom >= 15) {
zoom = 15
}
// 添加单击事件
label.addEventListener('click', () => {
// 调用 renderOverlays 方法,获取该区域下的房源数据
renderOverLays(item.value, zoom, map, point)
// 放大地图,以当前点击的覆盖物为中心放大地图
map.centerAndZoom(areaPoint, zoom)
// 解决清除覆盖物时,百度地图API的JS文件自身报错的问题
setTimeout(() => {
// 清除当前覆盖物信息
map.clearOverlays()
}, 0)
})
map.addOverlay(label)
}
// 熏染覆盖物 接收id参数获取区域房源数据 或覆盖类型以及下级地图的缩放级别
const renderOverLays = async (id: any, zoom: any, map: any, point: any) => {
let data = await getMap()
let result = data.body
console.log(zoom);
result.forEach((item: any) => {
// 创建覆盖物
createOverlays(item, zoom, map, point)
})
}
const createReact = (item: any, zoom: any, map: any, point: any) => {
const { coord: { longitude, latitude }, label: areaName, count, value } = item
const areaPoint = new BMap.Point(longitude, latitude)
//添加文本覆盖物
const opts = {
position: areaPoint,
offset: new BMap.Size(30, -30)
}
//注意:设置setContent以后,第一个参数中设置的文本内容就失效了,因此直接清空即可
const label = new BMap.Label('', opts)
//设置房源覆盖物内容
label.setContent(`
<div>
<p>
${areaName} ${count}套
</p>
</div>
`)
//设置样式
const labelStyle = {
border: 'none',
cursor: 'pointer',
whiteSpace: 'nowrap',
fontSize: '12px',
textAlign: 'center',
height: '20px',
background: 'rgba(38, 191, 110, 0.9)'
}
label.setStyle(labelStyle)
zoom++
// 添加单击事件
label.addEventListener('click', () => {
// 调用 renderOverlays 方法,获取该区域下的房源数据
renderOverLays(item.value, zoom, map, point)
// 放大地图,以当前点击的覆盖物为中心放大地图
map.centerAndZoom(areaPoint, zoom)
// 解决清除覆盖物时,百度地图API的JS文件自身报错的问题
setTimeout(() => {
// 清除当前覆盖物信息
map.clearOverlays()
}, 0)
})
map.addOverlay(label)
}
// 创建覆盖物 根据传入的数据调用对应的方法 创建覆盖物
const createOverlays = (item: any, zoom: any, map: any, point: any) => {
switch (zoom) {
case 11:
createCircle(item, zoom, map, point)
break;
case 13:
createCircle(item, zoom, map, point)
break;
case 15:
createReact(item, zoom, map, point)
break;
default:
break;
}
}
return (
<div className="map">
<Navbar leftIcon style={{ zIndex: 2 }}>
地图找房
</Navbar>
<div id="container" style={{ height: 799 }}>
<Popup visible={visible} onVisibleChange={handleVisibleChange} placement="bottom">
<div className="vertical"></div>
</Popup>
</div>
</div>
)
}
效果: