init
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
This commit is contained in:
226
src/components/ProFromMap/index.tsx
Normal file
226
src/components/ProFromMap/index.tsx
Normal file
@@ -0,0 +1,226 @@
|
||||
import React, { Fragment, useEffect, useRef, useState } from 'react';
|
||||
import style from './index.less';
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import { ProFormSelect } from '@ant-design/pro-components';
|
||||
import img from './point.png';
|
||||
import { Modal } from 'antd';
|
||||
import { debounce } from '@/utils/tools';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
_AMapSecurityConfig?: {
|
||||
securityJsCode: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
export type MapProps = {
|
||||
onSelect: (flag?: boolean, formVals?: unknown) => void;
|
||||
onCancel: (flag?: boolean, formVals?: unknown) => void;
|
||||
open: boolean;
|
||||
};
|
||||
export const aMapConfig = {
|
||||
key: '9cfc9370bd8a941951da1cea0308e9e3',
|
||||
securityJsCode: '7b16386c7f744c3ca05595965f2b037f',
|
||||
};
|
||||
|
||||
const ProFromMap: React.FC<MapProps> = ({ open, onSelect, onCancel }) => {
|
||||
const mapRef = useRef<any>(null);
|
||||
const geocoderRef = useRef<any>(null);
|
||||
const autoCompleteRef = useRef<any>(null);
|
||||
const addMarkerRef = useRef<any>(null);
|
||||
const markerRef = useRef<any>(null);
|
||||
const locationList = useRef<any>([]);
|
||||
const localData = useRef(null);
|
||||
const [selectValue, setSelectValue] = useState<any>(null);
|
||||
const [locationOptions, setLocationOptions] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('open', open);
|
||||
if (!open) return;
|
||||
window._AMapSecurityConfig = {
|
||||
securityJsCode: aMapConfig.securityJsCode,
|
||||
};
|
||||
AMapLoader.load({
|
||||
key: aMapConfig.key, // 申请好的Web端开发者Key,首次调用 load 时必填
|
||||
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||||
plugins: ['AMap.Scale'], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
|
||||
})
|
||||
.then((AMap) => {
|
||||
mapRef.current = new AMap.Map('container', {
|
||||
// 设置地图容器id
|
||||
viewMode: '3D', // 是否为3D地图模式
|
||||
zoom: 11, // 初始化地图级别
|
||||
center: [120.384599, 36.062687], // 初始化地图中心点位置
|
||||
});
|
||||
// 浏览器定位
|
||||
AMap.plugin('AMap.Geolocation', function () {
|
||||
var geolocation = new AMap.Geolocation({
|
||||
enableHighAccuracy: false, //是否使用高精度定位,默认:true
|
||||
timeout: 10000, //超过10秒后停止定位,默认:5s
|
||||
position: 'RB', //定位按钮的停靠位置
|
||||
offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
|
||||
zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
|
||||
});
|
||||
mapRef.current.addControl(geolocation);
|
||||
geolocation.getCurrentPosition();
|
||||
});
|
||||
// 添加插件
|
||||
AMap.plugin('AMap.AutoComplete', function () {
|
||||
// 注意:输入提示插件2.0版本需引入AMap.AutoComplete,而1.4版本应使用AMap.Autocomplete
|
||||
// 实例化AutoComplete
|
||||
autoCompleteRef.current = new AMap.AutoComplete({
|
||||
city: '370200', // 青岛市
|
||||
citylimit: false,
|
||||
});
|
||||
});
|
||||
|
||||
// 将经纬度坐标转化为详细地址
|
||||
AMap.plugin('AMap.Geocoder', () => {
|
||||
geocoderRef.current = new AMap.Geocoder({
|
||||
extensions: 'base',
|
||||
batch: false,
|
||||
city: '370200', // 青岛市
|
||||
});
|
||||
});
|
||||
|
||||
// 添加事件
|
||||
mapRef.current.on('click', (eve) => {
|
||||
console.log(eve);
|
||||
const { lat, lng } = eve.lnglat;
|
||||
if (geocoderRef.current && addMarkerRef.current) {
|
||||
const lnglat1 = [lng, lat];
|
||||
geocoderRef.current.getAddress(lnglat1, (status, result) => {
|
||||
if (status === 'complete' && result.info === 'OK') {
|
||||
const { formattedAddress } = result.regeocode;
|
||||
const id = Date.now();
|
||||
result.id = id;
|
||||
result.address = formattedAddress;
|
||||
result.location = {
|
||||
lat: lat,
|
||||
lng: lng,
|
||||
};
|
||||
setSelectValue(id);
|
||||
setLocationOptions([result]);
|
||||
localData.current = result;
|
||||
console.log(result, '详细地址');
|
||||
}
|
||||
});
|
||||
addMarkerRef.current && addMarkerRef.current(lnglat1);
|
||||
}
|
||||
});
|
||||
|
||||
addMarkerRef.current = (LngLat: any) => {
|
||||
if (markerRef.current) {
|
||||
mapRef.current.remove(markerRef.current);
|
||||
markerRef.current = null;
|
||||
addMarkerRef.current && addMarkerRef.current(LngLat);
|
||||
} else {
|
||||
markerRef.current = new AMap.Marker({
|
||||
icon: new AMap.Icon({
|
||||
size: new AMap.Size(32, 32), // 图标显示大小
|
||||
image: img, // 自定义图标 URL
|
||||
imageSize: new AMap.Size(32, 32), // 强制缩放原始图片大小
|
||||
}),
|
||||
anchor: 'bottom-center', // 设置锚点方位
|
||||
position: LngLat, //标注点位置
|
||||
title: `鼠标移入显示的提示`, //标注点标题
|
||||
map: mapRef.current, //将标注点添加到地图上
|
||||
});
|
||||
}
|
||||
};
|
||||
// 获取输入提示信息
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
}, [open]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
mapRef.current?.destroy();
|
||||
};
|
||||
}, []);
|
||||
|
||||
function autoInput(keywords: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
autoCompleteRef.current.search(keywords, function (status: string, result) {
|
||||
if (status === 'complete' && result.info === 'OK') {
|
||||
// 搜索成功时,result即是对应的匹配数据
|
||||
resolve(result.tips);
|
||||
} else {
|
||||
reject(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const searchLocation = async (keyWords: string) => {
|
||||
const keywordsToSearch = keyWords || '青岛';
|
||||
const resData = await autoInput(keywordsToSearch);
|
||||
locationList.current = resData;
|
||||
setLocationOptions(resData);
|
||||
return resData || [];
|
||||
};
|
||||
|
||||
// 防抖版本(确保组件卸载时清除)
|
||||
const debounceSearch = useRef(debounce(searchLocation, 500)).current;
|
||||
|
||||
function selectItem(id: any) {
|
||||
const items = locationList.current.filter((item) => item.id === id);
|
||||
if (items.length) {
|
||||
const value = items[0];
|
||||
setSelectValue(value.id);
|
||||
addMarkerRef.current([value.location.lng, value.location.lat]);
|
||||
mapRef.current.setZoomAndCenter(16, [value.location.lng, value.location.lat]);
|
||||
localData.current = value;
|
||||
}
|
||||
}
|
||||
|
||||
function locationSuccess() {
|
||||
if (localData.current) {
|
||||
onSelect && onSelect(localData.current);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Modal
|
||||
open={open}
|
||||
title="选择位置"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
width={800}
|
||||
onCancel={onCancel}
|
||||
onOk={locationSuccess}
|
||||
>
|
||||
<div className={style.AmapContainer}>
|
||||
<div className={style.Amap_search}>
|
||||
<ProFormSelect
|
||||
style={{
|
||||
width: '100%',
|
||||
}}
|
||||
debounceTime={500}
|
||||
name="select"
|
||||
// request={searchLocation}
|
||||
showSearch
|
||||
placeholder="请输入地点"
|
||||
fieldProps={{
|
||||
onSelect: selectItem,
|
||||
onSearch: debounceSearch,
|
||||
value: selectValue,
|
||||
options: locationOptions,
|
||||
fieldNames: {
|
||||
label: 'address',
|
||||
value: 'id',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div id="container" className={style.mapContent}></div>
|
||||
</div>
|
||||
</Modal>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProFromMap;
|
||||
Reference in New Issue
Block a user