谷歌地图多边形与右键菜单

734 阅读2分钟

谷歌地图与右键菜单

写在前面

首先非常感谢这位组件的作者,苦恼了一段时间的问题终于解决了。 这里给出这个组件的地址vue3-context-menu (imengyu.top)

需求

大致描述一下需求是怎么样的吧,就是要在谷歌地图上编辑多边形,然后呢,要给每一个多边形添加一个右键点击事件,右键点击会弹出一个菜单,苦于谷歌地图没有提供这方面的示例和文档,最贴合的一个示例还是使用类继承来实现的,当我看到this的时候马上就切掉了,因为项目使用的是vue3。而且网上很多相关的文章教程都挺老了的。看到文章发表日期大多都是15年左右的了,压根都不带看的。

效果

googleMapContextMenu.gif

懒人移步

内容不多,要是嫌麻烦我这里也给出这个视图的.vue文件源码 template

<template>
    <div class="map-container" v-show="true">
        <div id="map"></div>
    </div>
    <svg viewBox="0 0 80 20" xmlns="http://www.w3.org/2000/svg">
        <!-- Your icon -->
        <symbol id="icon-edit" viewBox="0 0 1024 1024">
            <path
                d="M904 318.72l-207.552-207.552 45.248-45.248 207.552 207.552-45.248 45.248z m-522.24 522.24l-231.232 46.272A19.2 19.2 0 0 1 128 864.64l46.272-231.232L641.216 166.4l207.616 207.552-467.072 467.072z m376.576-467.008l-117.12-117.12-408.064 408.128-29.248 146.368 146.304-29.312 408.128-408.064z"
                fill="#000000" fill-opacity=".9" p-id="4276">
            </path>
        </symbol>
    </svg>
    <svg viewBox="0 0 80 20" xmlns="http://www.w3.org/2000/svg">
        <!-- Your icon -->
        <symbol id="icon-delete" viewBox="0 0 1024 1024">
            <path
                d="M640 64a64 64 0 0 1 64 64v85.333h226.133c4.694 0 8.534 3.84 8.534 8.534V268.8a8.533 8.533 0 0 1-8.534 8.533h-55.466V832a128 128 0 0 1-128 128H277.333a128 128 0 0 1-128-128V277.333H93.867a8.533 8.533 0 0 1-8.534-8.533v-46.933c0-4.694 3.84-8.534 8.534-8.534H320V128a64 64 0 0 1 64-64h256z m170.667 213.333H213.333V832a64 64 0 0 0 60.246 63.893l3.754 0.107h469.334a64 64 0 0 0 63.893-60.245l0.107-3.755V277.333z m-392.534 128c4.694 0 8.534 3.84 8.534 8.534v324.266a8.533 8.533 0 0 1-8.534 8.534H371.2a8.533 8.533 0 0 1-8.533-8.534V413.867c0-4.694 3.84-8.534 8.533-8.534h46.933z m234.667 0c4.693 0 8.533 3.84 8.533 8.534v324.266a8.533 8.533 0 0 1-8.533 8.534h-46.933a8.533 8.533 0 0 1-8.534-8.534V413.867c0-4.694 3.84-8.534 8.534-8.534H652.8zM640 128H384v85.333h256V128z"
                fill="#000000" p-id="5443"></path>
        </symbol>
    </svg>
</template>

typescript

<script setup lang="ts">
    import { ref, onBeforeMount } from 'vue'
    import { zoneData, zoneType } from "@/test/map/testData";
    import ContextMenu from '@imengyu/vue3-context-menu'
    const map = ref<google.maps.Map | null>(null) // 地图实例
    const polygonList = ref<google.maps.Polygon[]>([]) // 多边形列表
    const drawingManager = ref<google.maps.drawing.DrawingManager | null>(null) // 绘制工具实例
    const currentPolygon = ref<google.maps.Polygon | null>(null) // 当前多边形
    async function initMap(): Promise<void> {
        const { Map } = (await google.maps.importLibrary('maps')) as google.maps.MapsLibrary;
        map.value = new Map(document.getElementById('map') as HTMLElement, {
            center: { lat: 40.682227, lng: -74.144292 },
            zoom: 14,
            mapId: 'your map id', // 你的地图id
        })
    }
    onBeforeMount(async () => {
        await initMap()
        zoneData.forEach(async (zone) => {
            const polygon = new google.maps.Polygon({
                paths: zone.paths,
                ...zoneType.default
            })
            /**这部分是右键菜单的核心代码 */
            polygon.addListener('contextmenu', (e: google.maps.PolyMouseEvent) => {
                const domEvent: PointerEvent = e.domEvent as PointerEvent
                const x = domEvent.x
                const y = domEvent.y
                ContextMenu.showContextMenu({
                    x: x,
                    y: y,
                    customClass: 'my-menu-box',
                    items: [
                        {
                            label: "Edit",
                            svgIcon: "#icon-edit",
                            onClick: () => {
                                alert("You click a menu Edit");
                            }
                        },
                        {
                            label: "Delete",
                            svgIcon: "#icon-delete",
                            onClick: () => {
                                alert("You click a menu Delete");
                            }
                        },
                    ]
                });
            })
            polygon.setMap(map.value)
            polygonList.value.push(polygon)
        })
        drawingManager.value = new google.maps.drawing.DrawingManager({
            drawingMode: null,
            drawingControl: false,
            polygonOptions: {
                strokeColor: '#42b903',
                strokeOpacity: 0.8,
                strokeWeight: 5,
                fillColor: '#E7F8F1',
                fillOpacity: 0.65,
                editable: false
            }
        })
        drawingManager.value.setMap(map.value)
        // 添加绘制完成事件
        google.maps.event.addListener(drawingManager.value, 'polygoncomplete', drawPolygonComplete)
    })
    const drawPolygonComplete = async (polygon: google.maps.Polygon) => {
        drawingManager.value?.setDrawingMode(null)
        polygonList.value.push(polygon)

        currentPolygon.value = polygon
    }
</script>

css

<style>
    #map {
        height: 100vh;
        width: 100%;
    }

    .map-container {
        display: flex;
        width: 90%;
        height: 90vh;
        flex-direction: column;
        margin: 0 auto;
    }

    .btn {
        margin: 20px 0;
        align-self: flex-start;
    }

    .my-menu-box {
        border-radius: 16px !important;
        background-color: #fff !important;
    }
</style>