Vue中使用高德地图js api 2.0封装的一些常用工具 1.绘制城市级边阔,2.地图撒点,3.自定义点位,增加弹框,4.绘制轨迹,5.mouseTool 工具绘制多边形,6.Polyline飞线图

目录

 

一.  vue项目 中使用--初始化地图

二:地图撒点(如果是1000条以上的撒点,请自行使用海量点的方式撒点,否则会影响性能)

三:批量撒点+自定义弹框

四:绘制轨迹-----并设置车辆 起点,终点

五:AMap.MouseTool 插件 绘制多边形

六.利用Polyline + Marker的轨迹回放动画实现简易的飞线图 )

七:amap.js文件


一.  vue项目 中使用--初始化地图

1.引入loader 并填写秘钥  (目录结构如下:Home页面为地图展示的页面)

2. 页面中引入地图,并默认添加城市级轮廓线

新建utils 文件夹 下创建amap.js-----(amap.js放在了文章的末尾)

页面的使用:

<script setup>
    import myMap, {
        initMap
    } from "../utils/amap"
    import {
        onMounted
    } from "vue";
    let amap = null
    onMounted(() => {
        initMap().then(res => {
            init()
        })
    })
    const init = () => {
        amap = new myMap("mapElement", {
            viewMode: '2D', //开启3D视图,默认为关闭
        })
    }
</script>
<style lang="less">
    .main {
        position: relative;
        .home {
            width: 100%;
            height: 100vh;
        }
        .butList {
            position: absolute;
            right: 20px;
            z-index: 100;
            display: flex;
            flex-direction: column;
            top: 26px;
        }
    }
</style>

2.1:效果如图,已经成功初始化了 当前的地图,并绘制了 城市轮廓

二:地图撒点(如果是1000条以上的撒点,请自行使用海量点的方式撒点,否则会影响性能)

<template>
    <div class="main">
        <div class="home" id="mapElement">
        </div>
        <div class="butList">
            <button @click="addMask()">添加1个点位</button>
           </div>
    </div>
</template>
 // 撒点
    const addMask = () => {
        var data = { //数据源
            name:"我是傻13傻13",
            pos:[121.251581, 31.127219]
        }
        amap.addMark({
            position: data.pos,
            icon: new AMap.Icon({
                image: require('@/assets/旗子.png'),
                imageOffset: new AMap.Pixel(0, 0)
            }),
            title:data.name,
            extData:{
                ...data
            }
        })
    }
效果如图:

 三:批量撒点+自定义弹框

   <button @click="addMaskDialog()">添加多个点位并增加弹框</button>
//使用
   const addMaskDialog = () => {
        var data = [{
                position: [121.251581, 31.127219],
                title: "标题标题标题11111",
                content: "内容1111111",
            },
            {
                position: [121.514752, 31.084229],
                title: "标题标题标题22222",
                content: "内容2222222222",
            }
        ]
        data.forEach((item) => {
            amap.addMark({
                position: item.position,
                icon: new AMap.Icon({
                    image: require('@/assets/旗子.png'),
                    imageOffset: new AMap.Pixel(0, 0)
                }),
                title:item.title,
                extData: {
                    ...item
                }
            }, (obj => {        //自定义弹框内容
                let html = `<div>  
                     <p> ${obj.title}</p>
                     <p> ${obj.content}</p>
                    </div>`
                return html
            }))
        })
    }
效果如图: (点击后显示弹框)

四:绘制轨迹-----并设置车辆 起点,终点

<button @click="drawTrajectory()">绘制轨迹</button>
//使用  --(TrajectoryData)为你自己的轨迹数据
//格式为 [  [121.3465860503654,31.36514270534356],[xxxx,xxx],[xxx,xxxx]... ]
  const drawTrajectory = () => {
        amap.drawTrajectory(TrajectoryData)
    }
效果如图

五:AMap.MouseTool 插件 绘制多边形

<button @click="drawElectronic()">绘制多边形(电子围栏)</button>
   const drawElectronic = () => {
        amap.drawpolygon(null, (e) => {
            console.log("绘制完毕" + e);
        })
    }
效果如图:

 

六.利用Polyline + Marker的轨迹回放动画实现简易的飞线图 )

    <button @click="drawFlyLines()">绘制飞线图</button>
  const drawFlyLines = () => {
        const data = [
            [
                [121.5477, 31.31193],
                [121.5045, 31.35096],
            ],
            [
                [121.5477, 31.31193],
                [121.37117808036108, 31.396691737575335],
            ],
            [
                [121.5477, 31.31193],
                [121.38543721542061, 31.323684255209596],
            ],
            [
                [121.5477, 31.31193],
                [121.44815275644933, 31.356271308434827],
            ],
            [
                [121.5477, 31.31193],
                [121.4304612729651, 31.406328350479193],
            ]
        ]
        amap.drawFlyLines(data)
    }
效果如图

 

最后附上当前home页面的全部代码:

最后附上所有代码:
<template>
    <div class="main">
        <div class="home" id="mapElement">
        </div>
        <div class="butList">
            <button @click="addMask()">添加1个点位</button>
            <button @click="addMaskDialog()">添加多个点位并增加弹框</button>
            <button @click="clearMap()">清空点位</button>
            <button @click="drawTrajectory()">绘制轨迹</button>
            <button @click="drawElectronic()">绘制多边形(电子围栏)</button>
            <button @click="drawFlyLines()">绘制飞线图</button>
            <button @click="clearMap()">隐藏飞线图</button>
        </div>
    </div>
</template>
<script setup>
    import myMap, {
        initMap
    } from "../utils/amap"
    import TrajectoryData from "../utils/Trajectory.json"
    import {
        onMounted
    } from "vue";
    let amap = null
    onMounted(() => {
        initMap().then(res => {
            init()
        })
    })
    const init = () => {
        amap = new myMap("mapElement", {
            viewMode: '2D', //开启3D视图,默认为关闭
        })
    }
    // 撒点
    const addMask = () => {
        var data = { //数据源
            name: "我是傻13傻13",
            pos: [121.251581, 31.127219]
        }
        amap.addMark({
            position: data.pos,
            icon: new AMap.Icon({
                image: require('@/assets/旗子.png'),
                imageOffset: new AMap.Pixel(0, 0)
            }),
            title: data.name,
            extData: {
                ...data
            }
        })
    }
    const addMaskDialog = () => {
        var data = [{
                position: [121.251581, 31.127219],
                title: "标题标题标题11111",
                content: "内容1111111",
            },
            {
                position: [121.514752, 31.084229],
                title: "标题标题标题22222",
                content: "内容2222222222",
            }
        ]
        data.forEach((item) => {
            amap.addMark({
                position: item.position,
                icon: new AMap.Icon({
                    image: require('@/assets/旗子.png'),
                    imageOffset: new AMap.Pixel(0, 0)
                }),
                title: item.title,
                extData: {
                    ...item
                }
            }, (obj => { //自定义弹框内容
                let html = `<div>  
                     <p> ${obj.title}</p>
                     <p> ${obj.content}</p>
                    </div>`
                return html
            }))
        })
    }
    const clearMap = () => {
        amap.clearMap()
    }
    const drawTrajectory = () => {
        amap.drawTrajectory(TrajectoryData)
    }
    const drawElectronic = () => {
        amap.drawpolygon(null, (e) => {
            console.log("绘制完毕" + e);
        })
    }
    const drawFlyLines = () => {
        const data = [
            [
                [121.5477, 31.31193],
                [121.5045, 31.35096],
            ],
            [
                [121.5477, 31.31193],
                [121.37117808036108, 31.396691737575335],
            ],
            [
                [121.5477, 31.31193],
                [121.38543721542061, 31.323684255209596],
            ],
            [
                [121.5477, 31.31193],
                [121.44815275644933, 31.356271308434827],
            ],
            [
                [121.5477, 31.31193],
                [121.4304612729651, 31.406328350479193],
            ]
        ]
        amap.drawFlyLines(data)
    }
</script>
<style lang="less">
    .main {
        position: relative;
        .home {
            width: 100%;
            height: 100vh;
        }
        .butList {
            position: absolute;
            right: 20px;
            z-index: 100;
            display: flex;
            flex-direction: column;
            top: 26px;
        }
    }
</style>

七:amap.js文件

import {
    filterGjData
} from "./index"
class myMap {
    constructor(el, config) {
        this.aMap = null
        this.polygonList = [] //多边形
        this.overlays = [] //地图上的覆盖物
        if (el) {
            this.init(el, config)
        }
    }
    /**
     * 地图初始化
     * @param {dom元素} el
     * @param {配置参数} config 对传入的配置合并
     */
    init(el, config) {
        let setConf = {
            mapStyle: 'amap://styles/fresh', //设置地图的显示样式
            rotateEnable: false,
            pitchEnable: false,
            resizeEnable: true,
            zoom: 12.5,
            pitch: 45, //45度俯视
            // rotation: 45,
            viewMode: '3D', //开启3D视图,默认为关闭
            zooms: [2, 20],
            skyColor: "#002d56", //天空颜色 倾斜后才会产生 仅限于3D 模式下
            center: [121.489612, 31.405457], //中心点
        }
        this.aMap = new AMap.Map(el, {
            ...setConf,
            ...config
        });
        this.sketchContours()
    }
    /**
     * 默认添加地图城市级边阔
     * https://lbs.amap.com/api/javascript-api-v2/guide/services/district-search
     * @param {initconfig}:  Polygon的样式
     */
    sketchContours(initconfig) {
        let that = this
        let mapConfig = {
            strokeWeight: 4,
            strokeColor: '#005aad', //轮廓边框颜色
            fillColor: '', //填充的背景色
            fillOpacity: 0.3,
            bubble: true //覆盖物的点击事件冒泡到地图上
        }
        Object.assign(mapConfig, initconfig)
        let district = new AMap.DistrictSearch({ // 创建行政区查询对象
            extensions: 'all', // 返回行政区边界坐标等具体信息
            level: 'city' // 设置查询行政区级别为 省
        });
        district.search("上海市", function (status, result) {
            if (Object.keys(result).length <= 0) {
                return
            }
            let holes = result.districtList[0].boundaries
            for (let i = 0, l = holes.length; i < l; i++) {
                let polygon = new AMap.Polygon({
                    map: that.aMap,
                    ...mapConfig,
                    path: holes[i]
                });
                that.aMap.add(polygon)
                that.aMap.setFitView(); // 地图自适应 调整视野 
            }
        })
    }
    /**
     * 对外暴露的amap,可自行获取map对象
     */
    getMap() {
        return this.aMap
    }
    /**
     * 撒点
     * @param {config}
     * @param {content} HTML要素字符串
     * @param {contentCallBack} 在此回调函数中可以获取到自定义的数据 返回值以供弹框展示内容
     */
    addMark(config, contentCallBack) {
        const oldconfig = {
            clickable: true, //点标记是否可点击
            position: [], //经纬度
            icon: "https://vdata.amap.com/icons/b18/1/2.png", //点标记图片
            extData: { //自定义属性
            }
        }
        Object.assign(oldconfig, config)
        let marker = new AMap.Marker({
            map: this.aMap,
            ...oldconfig
        });
        this.aMap.add(marker);
        this.overlays.push(marker)
        let userData = marker.getExtData()
     
        if (contentCallBack) {
            marker.on('click', (e) => {
                this.openInfoWindow(userData, contentCallBack(userData)) //自定义信息窗体
            })
        }
        this.aMap.setFitView();
    }
    openInfoWindow(data, content) {
        let infoWindow = new AMap.InfoWindow({
            content,
            anchor: 'bottom-center',
            offset: [16, 0]
        });
        infoWindow.open(this.aMap, data.position); //信息窗体打开
        this.aMap.setFitView();
    }
    /**
     * 清除地图覆盖物(不包括轮廓)包括停止轨迹
     */
    clearMap() {
        this.aMap.clearInfoWindow()
        this.overlays.forEach(item => {
            if (item.type == "AMap.Marker" && item.getExtData() == "stopdrawGj") {
                item.stopMove();
            }
            item.remove()
        })
    }
    /**
     * 
     * @param {轨迹数据 cj02坐标} arrPath :[[121.4363,31.222],[121.4363,31.222],[121.4363,31.222]....]
     * @param {*轨迹线条样式} options
     * 内含车辆开始位置,结束位置,以及车辆运行时轨迹动画
     * 如果是成千上万条的轨迹数据 得使用https://lbs.amap.com/api/amap-ui/reference-amap-ui/mass-data/pathsimplifier 组件
     */
    drawTrajectory(arrPath, options) {
        let PolylineStyle = {
            strokeColor: "#AF5", //线颜色
            strokeWeight: 7, //线宽
            lineJoin: 'round',
            isOutline: true,
            showDir: true, //显示箭头  3D 模式下不支持
            borderWeight: 1,
            dirColor: '#fff',
            strokeStyle: "solid" //线样式
        }
        Object.assign(PolylineStyle, options)
        var start = arrPath[0] //开始点
        var end = arrPath[arrPath.length - 1] //结束点
        this.addMark({
            position: start,
            icon: new AMap.Icon({
                image: require('@/assets/start.png'),
                imageOffset: new AMap.Pixel(0, 0)
            })
        })
        const travelCar = new AMap.Marker({
            map: this.aMap,
            position: start,
            icon: new AMap.Icon({
                image: "https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png", //注意车头的方向
                imageOffset: new AMap.Pixel(0, 0)
            }),
            offset: new AMap.Pixel(-13, -26),
            extData: 'stopdrawGj'
        });
        var polylines = new AMap.Polyline({ //此处对比 arrPath 与filterGjData(arrPath) 简化后 之后的轨迹路线是一致的,
            map: this.aMap,
            path: arrPath,
            showDir: true,
            strokeColor: "#28F", //线颜色
            strokeWeight: 6, //线宽
        });
        const polyline = new AMap.Polyline({
            map: this.aMap,
            ...PolylineStyle
        });
        this.aMap.setFitView(polyline);
        travelCar.on('moving', ((e) => {
            polyline.setPath(e.passedPath);
            this.aMap.setCenter(e.target.getPosition(), true)
        }));
        function startTraGj(data) { //开始绘制轨迹
            travelCar.moveAlong(data, {
                // // 每一段的时长
                duration: 200,
                // JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置
                autoRotation: true,
            });
        }
        startTraGj(filterGjData(arrPath)) //对于每秒钟接收的轨迹数据 做简化,否则会卡顿且会被延迟播放
        travelCar.on('movealong', ((e) => { //最终动画执行结束
            this.addMark({
                icon: new AMap.Icon({
                    image: require('@/assets/end.png'),
                    imageOffset: new AMap.Pixel(0, 0)
                }),
                position: end,
            })
            travelCar.hide()
        }));
    
        this.overlays.push(travelCar, polyline, polylines)
    }
    /**
     *  使用mouseTool 插件 绘制电子围栏
     *  鼠标单击地图选点/线,右键结束
     * @param {isbatch : 是否批量绘制 电子围栏(多边形)} isbatch ? '每次只能绘制一个' : '不限制'
     * @param {drawCompletedfn} 每次绘制完毕的回调
     */
    drawpolygon(nobatch,drawCompletedfn) {
        const mouseTool = new AMap.MouseTool(this.aMap);
        mouseTool.polygon({
            map: this.aMap,
            fillColor: '#00b0ff',
            strokeColor: '#80d8ff'
        });
        mouseTool.on('draw', (e) => { //每次绘制完图形的回调
            if(drawCompletedfn){
                drawCompletedfn(e)
            }
            if (nobatch) {
                if (this.polygonList.length) {
                    this.aMap.remove(this.polygonList)
                    this.polygonList = []
                }
            }
            this.polygonList.push(e.obj);
        })
    }
    /**
     * 获取绘制的图形 的路径
     * @return [[path1],[path2]]
     */
    getDrawedpolygon() {
        return this.polygonList.map(item => {
            return [item.getPath()]
        })
    }
    /**
     * 利用Polyline + Marker的轨迹回放动画 实现简易的飞线图
     *  @param {data}[[[121.5477, 31.31193],[121.5477, 31.31193]],]
     */
    drawFlyLines(data) {
        data.forEach(item => {
            const linePath = new AMap.Polyline({
                map: this.aMap,
                path: item,
                strokeColor: "#b3e9af", //线颜色
            });
            const line = new AMap.Polyline({
                map: this.aMap,
                path: item,
                showDir: true,
                strokeColor: "#b3e9af", //线颜色
                strokeWeight: 6, //线宽
                lineCap: "round",
                zIndex: 100,
                cursor: "pointer",
                strokeStyle: "solid" //线样式
            });
            line.on('mouseover', (e) => { //如果需要添加鼠标移至线段上 显示文本 则可以通过e.pixel.x/y, 动态设置某个div的postition用来显示即可
                let postition = { //针对于当前地图的px
                    left: e.pixel.x,
                    top: e.pixel.y,
                }
            })
            line.on('mouseout', (e) => {
            })
            const flyIcon = new AMap.Marker({
                map: this.aMap,
                position: item[0],
                icon: new AMap.Icon({
                    image: require('@/assets/rightHeader.png'),
                    imageOffset: new AMap.Pixel(0, 0)
                }),
                offset: new AMap.Pixel(-16, -16),
                extData: 'stopdrawGj'
            });
            flyIcon.moveAlong(item, {
                duration: 4000,
                autoRotation: true,
                circlable: true //循环
            });
            this.overlays.push(flyIcon, line, linePath)
        })
    }
}
export function initMap() {
    return new Promise((resolve, reject) => {
        AMapLoader.load({
            "key": "填写你自己的key", // 申请好的Web端开发者Key,首次调用 load 时必填
            "version": "2.0", // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15
            "plugins": [
                "AMap.MoveAnimation,AMap.MouseTool,AMap.PlaceSearch,AMap.DistrictSearch"
            ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
            // "AMapUI": { // 是否加载 AMapUI,缺省不加载
            //     "version": '1.1', // AMapUI 版本
            //     "plugins": [], // 需要加载的 AMapUI ui插件
            // },
            // "Loca": { // 是否加载 Loca, 缺省不加载
            //     "version": '2.0' // Loca 版本
            // },
        }).then((AMap) => {
            window.AMap = AMap
            resolve(AMap)
        }).catch((e) => {
            console.error(e); //加载错误提示
            reject(e)
        });
    })
}
export default myMap



//filterGjData方法:
/**
 * 对于每秒钟记录的轨迹数据 简化,如上一秒的轨迹与下一秒的轨迹数据一致 则删除下一次的轨迹
 * 如:[
    [
        121.3465860503654,
        31.36514270534356
    ],
    [
        121.3465860503654,
        31.36514270534356
    ],
    [
        121.3465860503654,
        31.36514270534356
    ],
    [
        121.3465860503654,
        31.36514270534356
    ],
    [
        121.3465860503654,
        31.36514270534356
    ],
    [
        121.6444464646,
        31.36514270534356
    ],[
        121.888888888888,
        31.36514270534356
    ],]
 * @param {} data
 * @returns {最终只需要 [[121.3465860503654,31.36514270534356],[121.6444464646,31.36514270534356],[121.888888888888,31.36514270534356
    ]] }  
 */
export function filterGjData(data) {
    for (let i = 0; i < data.length; i++) {
        let item1 = data[i]
        if (i + 1 == data.length) {
            break;
        } else {
            let item2 = data[i + 1]
            if (item1[0] == item2[0] && item1[1] == item2[1]) {
                data.splice(i, 1)
                i--
            }
        }
    }
    return data
}

最后: 欢迎大家点评,有不足的地方 望请大佬指出。以上为自己工作中用的比较多的工具

若还有其他用的比较多的地图功能,欢迎大家留言 我有空会补上去

猜你喜欢

转载自blog.csdn.net/qq_48554377/article/details/130207337