react中基于腾讯地图的地图选点,地址搜索逆向定位获取经纬度
效果示例图
地图组件tencentMap/index.jsx
import { useEffect, useRef, useState } from "react";
import "./map.scss";
function loadTMap(key) {
return new Promise((resolve, reject) => {
if (typeof window.TMap !== "undefined") {
resolve(window.TMap);
return true;
}
window.onTMapCallback = function () {
resolve(window.TMap);
return true;
};
const script = document.createElement("script");
script.type = "text/javascript";
script.src = `https://map.qq.com/api/gljs?v=1.exp&key=${key}&callback=onTMapCallback&s=1&libraries=service`;
script.onerror = reject;
document.head.appendChild(script);
return true;
});
}
function TencentMap(props) {
let mapInit = useRef(null);
let Map = useRef(null);
let markerLayer = useRef(null);
let [keyword, setKeyword] = useState("");
let [suggestionList, setSuggestionList] = useState([]);
//初始化腾讯地图
function initMap() {
document.querySelector("#tencentContainer").innerHTML = "";
mapInit.current = loadTMap("PZHBZ-G6A34-QV7UJ-X4QXK-YIMRK-RAFZS");
mapInit.current.then((TMap) => {
//定义map变量,调用TMap.Map构造函数创建地图容器
Map.current = new TMap.Map(document.querySelector("#tencentContainer"), {
zoom: 17, //设置地图缩放级别
});
//修改地图中心点
Map.current.setCenter(new TMap.LatLng(31.230355, 121.47371));
//创建并初始化MultiMarker(用于实现在地图中的点标注功能)
markerLayer.current = new TMap.MultiMarker({
id: "marker-layer",
map: Map.current, //指定地图容器
geometries: [],
});
//给地图设置点击事件
Map.current.on("click", (evt) => {
if (markerLayer.current) {
markerLayer.current.setGeometries([]);
}
const lat = evt.latLng.getLat().toFixed(6);
const lng = evt.latLng.getLng().toFixed(6);
let location = new TMap.LatLng(lat, lng);
// 创建一个正逆地址解析类
const geocoder = new TMap.service.Geocoder();
// 将给定的坐标位置转换为地址
geocoder.getAddress({ location: location }).then((response) => {
setKeyword(response.result.address);
props.click({
keyword: response.result.address,
position: {
lat: lat,
lng: lng,
},
});
markerLayer.current.add([
{
id: "1", //点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
position: evt.latLng, //点标记坐标位置
},
]);
});
});
});
}
//根据输入值进行逆向定位
function searchHandle(e) {
let value = trim(e);
if (value.length > 0) {
setKeyword(value);
searchSuggestionAPI(value);
} else {
setKeyword("");
}
}
function searchSuggestionAPI(value) {
mapInit.current.then((TMap) => {
// 新建一个关键字输入提示类
let suggest = new TMap.service.Suggestion({
pageSize: 10, // 返回结果每页条目数
});
suggest
.getSuggestions({
keyword: value,
})
.then((result) => {
// 以当前所输入关键字获取输入提示
if (result.data.length > 0) {
setSuggestionList(result.data);
}
})
.catch((error) => {
console.log("[error]", error);
});
});
}
// 点击选中下拉数据
function selectSuggestionHandle(row) {
mapInit.current.then((TMap) => {
//修改地图中心点
Map.current.setCenter(
new TMap.LatLng(row.location.lat, row.location.lng)
);
if (markerLayer.current) {
markerLayer.current.setGeometries([]);
}
setKeyword(row.address);
props.click({
keyword: row.address,
position: {
lat: row.location.lat,
lng: row.location.lng,
},
});
markerLayer.current.add([
{
id: "1", //点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
position: new TMap.LatLng(row.location.lat, row.location.lng), //点标记坐标位置
},
]);
setSuggestionList([]);
});
}
//防抖
function debounce(fn, delay = 1000) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
/**
* 去除空格,type: 1-所有空格 2-前后空格 3-前空格 4-后空格
*/
function trim(str, type) {
str = str || "";
type = type || 1;
switch (type) {
case 1:
return str.replace(/\s+/g, "");
case 2:
return str.replace(/(^\s*)|(\s*$)/g, "");
case 3:
return str.replace(/(^\s*)/g, "");
case 4:
return str.replace(/(\s*$)/g, "");
default:
return str;
}
}
useEffect(() => {
initMap();
}, []);
return (
<>
<div className="tencentMap-wrap">
<div className="tencent" id="tencentContainer"></div>
<div className="tencent-search">
<div className="search-header">
<input
type="text"
placeholder="请输入地址"
value={keyword}
onChange={(e) => searchHandle(e.target.value)}
/>
</div>
{suggestionList.length > 0 ? (
<ul className="suggestion-wrap">
{suggestionList.map((item, index) => (
<li
key={index}
className="suggestion-item"
onClick={() => {
selectSuggestionHandle(item);
}}
>
{item.title}
</li>
))}
</ul>
) : (
""
)}
</div>
</div>
</>
);
}
export default TencentMap;
样式map.scss
.tencentMap-wrap {
width: 90%;
margin: 12px auto;
.tencent {
width: 100%;
height: 400px;
}
.tencent-search {
width: 100%;
margin-top: 12px;
display: flex;
flex-direction: column;
position: relative;
.search-header {
width: 100%;
position: relative;
input,
input:focus {
border-radius: 4px;
outline: none;
padding: 0px 12px;
border: 1px solid #dcdcdc;
border-radius: 4px;
width: 100%;
height: 40px;
}
input::placeholder,
input::-moz-placeholder,
input::-webkit-input-placeholder {
color: #999;
}
}
.suggestion-wrap {
border: 1px solid #dcdcdc;
border-radius: 4px;
width: 100%;
position: absolute;
left: 0px;
top: 44px;
background-color: #fff;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
z-index: 9;
padding: 12px 0px;
display: flex;
flex-direction: column;
.suggestion-item {
border-bottom: 1px solid #dcdcdc;
width: 100%;
cursor: pointer;
padding: 12px 12px;
font-size: 16px;
color: #333;
}
.suggestion-item:last-child {
border-bottom: 0px;
}
.suggestion-item:hover {
background-color: rgba(220, 220, 220, 0.5);
}
}
}
}
使用案例
import { useEffect } from "react";
import TencentMap from "../../components/tencentMap";
function Tencent() {
function mapHandle(row) {
console.log("[row]", row);
}
useEffect(() => {}, []);
return (
<>
<TencentMap click={mapHandle} />
</>
);
}
export default Tencent;