高德web服务api 查询接口案例

import React, { useEffect, useRef, useState, CSSProperties } from 'react'
import { Select } from 'antd'
const { Option } = Select;

const AMAP_KEY = "cc9fb7d123185499909bf80c4c778535" 

const queryBykeyword = async (params: object) => {
    let url = 'https://restapi.amap.com/v3/place/text'
    const config = {
        output: 'JSON',
        key: AMAP_KEY,
        extensions: 'all'
    }
    let newParams = "?"
    for (const [key, value] of Object.entries({ ...config, ...params })) {
        newParams = newParams[newParams.length - 1] === "&" ? newParams : newParams + "&"
        newParams = newParams + key + "=" + value;
    }
    url = url + newParams
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.open("get", url)
        xhr.send()
        // xhr.responseType
        xhr.addEventListener('load', () => {
            const status = xhr.status;
            if ((status >= 200 && status < 300) || status === 304) {
                const result = JSON.parse(xhr.response)
                resolve(result)
            } else {
                reject(xhr)
            }
        });
    })

}
const styleSearch: CSSProperties = {
    width: "60%",
    background: 'transparent',
    position: 'absolute',
    right: 12,
    top: 20,
    zIndex: 2,
}

const styleHandle: CSSProperties = {
    cursor: ' pointer',
    pointerEvents: 'all',
    zIndex: 3,
    position: 'absolute',
    right: 8,
    top: 0,
    transform: 'translateY(50%)'
}
const styleTip: CSSProperties = {
    pointerEvents: 'none',
    zIndex: 3,
    position: 'absolute',
    right: 0,
    top: 20,
    // transform: 'translateX(50%) translateY(calc(-50% - 10px ))',
    fontSize: 12,
    transition: 'all 0.4s ease 0s'
}


interface PropsT {
    sendLnglat: (lnglat: any[]) => void
    initLnglat?: any[]
}
const Amap = (props: PropsT) => {
    const { sendLnglat,initLnglat } = props
    const refMap = useRef(null)
    // const [geoCenter, setGeoCenter] = useState<any[]>()
    const [keywords, setSeywords] = useState('')
    const [result, setResult] = useState<any[]>([])
    const [myMap, setMyMap] = useState<any>()
    // const [currentItem, setCurrentItem] = useState<any>({})
    const [hoverItemPos, setHoverItemPos] = useState<any>({})
    const [hoverItem, setHoverItem] = useState<any>({})

    useEffect(() => {
        if (!window.AMap) {
            // console.log('start loadMapScript');
            loadMapScript()
        } else {
            initMap()
        }
    }, [])

    const loadMapScript = () => {
        window.initMap = () => {
            // console.log('AMap script is ready!!');
            initMap();
        };
        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.src =
            `https://webapi.amap.com/maps?v=1.4.15&key=${AMAP_KEY}&callback=initMap`;
        document.body.appendChild(script);
    };

    const initMap = () => {
        if (!window.AMap) {
            // console.error('AMap script is not ready!!');
            return;
        }
        // console.log('start initMap');
        const map = new window.AMap.Map(refMap.current, {
            zoom: 12, // 级别
            center: initLnglat,// 中心点坐标
            resizeEnable: true,
            dragEnable: true,
            // showIndoorMap: false,
            // showLabel: false,
            // mapStyle: 'amap://styles/whitesmoke',
            // features: ['bg', 'road', 'building'],
        });
        map.plugin('AMap.ToolBar', () => { // 添加地图控件
            const toolbar = new window.AMap.ToolBar();
            map.addControl(toolbar)
        })
        map.on('click', (ev: any) => {// 绑定全局事点击件获取坐标
            // 触发事件的对象
            // var target = ev.target;
            // 触发事件的地理坐标,AMap.LngLat 类型
            const lnglat = ev.lnglat;
            // 触发事件的像素坐标,AMap.Pixel 类型
            // var pixel = ev.pixel;
            // 触发事件类型
            // var type = ev.type;
            // console.log("ev==", ev);
            const { lng, lat } = lnglat
            sendLnglat([lng, lat])

        });
        map.on('dragstart', () => { // 绑定全局拖拽事件,重置活跃项及其坐标
            setHoverItemPos({})
            setHoverItem({})
        });

        setMyMap(map)  // 保存当前地图实例
    };
    const handleChange = (_val: any, opt: any) => {
        const { item } = opt.props
        // console.log("val opt", val, opt);

        // setCurrentItem(item)
        if (!window.AMap || !myMap) {
            return
        }
        setHoverItemPos({})
        setHoverItem({})
        const lnglat = item.location?.split(',').map((i: any) => +i) || []
        myMap.setCenter(lnglat) // 定位到选中项
        myMap.setZoom(17)

    }
    const handleSearch = (val: any) => {
        const words = val.trim()
        // console.log("words==", words);
        setSeywords(words)
        search({ keywords: words })
    }
    const search = (prms = {}) => {
        const params = {
            // keywords: keywords,
            // city: 'beijing',
            offset: 25,
            page: 1,
            ...prms
        }
        queryBykeyword(params).then((data: any) => {
            if (data?.status == 1 && data.pois.length) {
                setResult(data.pois)
                const item = data.pois?.[0] // 默认取搜索结果第一项为活跃项
                if (!window.AMap || !myMap) {
                    return
                }
                const lnglat = item.location?.split(',').map((i: any) => +i) || []
                myMap.setCenter(lnglat)
                markResult(data.pois) // 将搜索结果 Mark 到地图上
            } else {
                setResult([])
            }
        })

    }
    const markResult = (resultList: any[]) => {
        if (!window.AMap || !myMap) {
            return
        }
        setHoverItemPos({})
        setHoverItem({})
        const markers = resultList?.map(item => {
            const lnglatn = item.location?.split(',').map((i: any) => +i) || []
            const marker = new window.AMap.Marker({
                icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png",
                position: lnglatn,
                offset: new window.AMap.Pixel(-10, -30),
                extData: { // marker 的额外数据
                    ...item
                },
            });
            marker.on('click', (e: any) => { // 单独给 marker 绑定事件 
                // console.log("ev click", e);
                const { target = {}, } = e
                const { w = {} } = target
                const { extData = {} } = w
                // const { lng, lat } = lnglat
                // myMap.setCenter([lng, lat])
                // setCurrentItem(extData)
                const { location = '' } = extData
                sendLnglat(location.split(',')) // 获取点击项坐标
            });
            marker.on('mousemove', (e: any) => {
                // console.log("ev mousemove", e);
                const { target = {}, pixel } = e
                const { w = {} } = target
                const { extData = {} } = w
                setHoverItemPos(pixel) // 获取 hover 项坐标等信息以显示
                setHoverItem(extData)
            })
            // marker.on('mouseout', (e: any) => {
            //     console.log("ev mouseout", e);
            // })
            return marker
        })
        myMap.clearMap(); // mark 前先 clear
        myMap.add(markers)
    }
    const Options = result.map((item: any) => <Option key={item.id} value={item.id} item={item} >{item.name}</Option>)
    return (
        <div style={{ width: '100%', height: 300, position: 'relative' }}>
            <div ref={refMap} style={{ width: '100%', height: "100%" }} > </div>
            <div style={{
                ...styleTip,
                right: hoverItemPos.x ? `calc(100% - ${hoverItemPos.x}px` : undefined,
                top: hoverItemPos.y,
                transform: `${hoverItemPos.x ? 'scale(1)' : 'scale(0.001)'} translateX(50%) translateY(calc(-50% - 10px ))`
            }}
            >{hoverItem.name}</div>
            <div style={{ ...styleSearch }} >
                <Select
                    className="amap-search"
                    showSearch
                    // value={"Homepp"}
                    size="large"
                    placeholder={"请输入"}
                    defaultActiveFirstOption={false}
                    showArrow={false}
                    filterOption
                    onSearch={handleSearch}
                    onChange={handleChange}
                    notFoundContent={null}
                    optionFilterProp="children"
                    // style={{ pointerEvents: 'all' }}
                    dropdownStyle={{ backgroundColor: 'rgba(225,225,225,0.8)' }}
                    listHeight={220}
                >
                    {Options}
                </Select>
                <span style={{ ...styleHandle }} onClick={() => { search({ keywords }) }}>搜索</span>
            </div>
        </div >)



}
export default Amap

  

posted @ 2021-05-27 21:57  大_大汤  阅读(329)  评论(0编辑  收藏  举报