使用技术:vue3.2+openlayers8.2.0

<template>
    <div style="width: 100%;height: 100%">
        <div class="map" id="mymap"></div>
        <div class="tools shadow-md rounded flex">
            <el-button class="btn-search" @click="layerChange" :type="isHeatLayer ? 'primary' : 'success'">{{
                isHeatLayer ? '点位图' : '热力图' }}</el-button>
        </div>
        <el-card id="popup" class="popup">
            <div class="popupContainer"></div>
        </el-card>
    </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import 'ol/css';
import Map from 'ol/Map';
import ZoomToExtent from 'ol/control/ZoomToExtent';
import { defaults } from 'ol/control';
import Feature from 'ol/Feature';
import Overlay from 'ol/Overlay';
import VectorSource from 'ol/source/Vector';
import { Tile as TileLayer, Vector as VectorLayer, Heatmap as HeatmapLayer } from 'ol/layer';
import View from 'ol/View';
import XYZ from 'ol/source/XYZ'
import Point from 'ol/geom/Point';
import { Icon, Style, Fill, Text, Stroke } from 'ol/style';
import markerImg from '@/assets/img/marker.png'; // 静态图片资源

const mapDom = ref(null)
const mapObj = ref(null)
const mapPointList = ref([]) // 
const pointLayer = ref(null) // 点图层
const heatLayer = ref(null) // 热力图图层
const pointLayerSource = ref(null) // 点图层数据源


// 清除地图 某些情况 地图容器会存在两个 导致地图无法正常显示
const mapClear = () => {
    if (mapDom.value) {
        mapDom.value.innerHTML = ''
        mapDom.value = null
    }
}
mapClear()
// 初始化地图
const initMap = () => {
    // 获取地图容器
    mapDom.value = document.getElementById('mymap')
    // 初始化地图配置
    mapObj.value = new Map({
        target: mapDom.value, // 地图容器
        view: new View({
            center: [120.990969, 31.635013], // 地图中心点
            zoom: 10, // 缩放
            minZoom: 3, // 最小缩放
            maxZoom: 17, // 最大缩放
            projection: 'EPSG:4326', // 坐标系
            // extent: [116.67, 31.05, 116.67, 34.51], // 地图显示范围
        }),
        layers: [
            // new TileLayer({
            //     source: new OSM(),
            // }),
            new TileLayer({
                source: new XYZ({
                    // url: 'http://192.168.10.179:9527/roadmap/roadmap' + '/{z}/{x}/{y}.png'  // 设置本地离线瓦片所在路径
                    url: 'https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}' //在线高德地图
                })
            })
        ],

        controls: defaults().extend([
            new ZoomToExtent({
                extent: [119.67, 31.05, 119.67, 34.81], // 地图显示范围
            })
        ])
    })

    // 地图点击事件
    mapOnClick()
    // 加载点位
    addPoint()
}
// 地图点击事件
const mapOnClick = () => {
    // popupDom
    const popupDom = document.getElementById('popup')
    // 创建 popup
    const popup = new Overlay({
        element: popupDom,
        positioning: 'bottom-center',
        stopEvent: false
    })
    // 加载到地图
    mapObj.value.addOverlay(popup)

    // 地图点击事件
    mapObj.value.on('click', function (evt) {
        if (isHeatLayer.value) return
        // 获取点击位置的数据
        const feature = mapObj.value.forEachFeatureAtPixel(evt.pixel, function (feature) {
            return feature;
        })

        const popupContainer = document.getElementsByClassName('popupContainer')[0]

        // 判断数据
        if (feature) {
            // feature.values_.data ,data字段是在 addPoint 函数创建point时添加 可以自定义
            if (feature.values_.data) {
                const pointData = feature.values_.data
                popup.setPosition(evt.coordinate)
                popupContainer.innerHTML = `<div>${pointData}</div>`
                popupDom.style.display = 'block'
                // 设置地图中心点
                // mapObj.value.getView().setCenter(evt.coordinate)
                // 设置地图层级
                // mapObj.value.getView().setZoom(15)
            }
        } else {
            popupDom.style.display = 'none'
        }
    })
}
// 添加地理坐标
const addPoint = () => {
    // 清除所有点
    delPointAll()
    // 地理坐标数组
    // const pointData = [
    //     { longitude: 120.29, latitude: 31.93 }
    // ]

    makers.map(item => {
        // 创建点
        const point = new Feature({
            geometry: new Point([item.longitude, item.latitude]),
            data: item.title
        })
        // 点的样式
        const iconStyle = new Style({
            image: new Icon({
                // color: 'red',
                crossOrigin: 'anonymous',
                // 设置图标
                src: markerImg,
                // 设置图标缩放
                // scale: 0.02,
                scale: 0.2,
                // 设置图标偏移
                anchor: [0.6, 1],
            }),
            text: new Text({
                text: item.title,
                cursor: 'pointer',
                fill: new Fill({
                    color: '#000'
                }),
                backgroundFill: new Fill({
                    color: '#00E400'
                }),
                offsetX: 0,
                offsetY: -35,
                font: 'normal 14px 微软雅黑',
                stroke: new Stroke({
                    color: '#00E400',
                    width: 2
                })
            })
        })

        // 设置样式
        point.setStyle(iconStyle)
        // 保存到数据  方便删除
        mapPointList.value.push(point)
    })
    // 创建geojson数据源
    pointLayerSource.value = new VectorSource({ features: mapPointList.value })
    // 创建图层 并加载数据
    pointLayer.value = new VectorLayer({ source: pointLayerSource.value })
    heatLayer.value = new HeatmapLayer({
        source: pointLayerSource.value,
        blur: 15,
        radius: 15,
    })
    // 将图层添加地图上
    mapObj.value.addLayer(pointLayer.value)
    mapObj.value.addLayer(heatLayer.value)
    heatLayer.value.setVisible(false)
}
// 点位图和热力图切换
let isHeatLayer = ref(false)
const layerChange = () => {
    isHeatLayer.value = !isHeatLayer.value
    if (isHeatLayer.value) {
        pointLayer.value.setVisible(false)
        heatLayer.value.setVisible(true)
    } else {
        heatLayer.value.setVisible(false)
        pointLayer.value.setVisible(true)
    }
}
// 地理点位删除
const delPointAll = () => {
    // 判断 删除的数据源是否存在
    if (pointLayerSource.value) {
        // 删除图层 重置数据
        mapObj.value.removeLayer(pointLayer.value)
        pointLayerSource.value = null
        pointLayer.value = null
        mapPointList.value = []
    }
}

onMounted(() => {
    initMap()
    // 获取水印元素然后隐藏
    const waterMarker = document.getElementsByClassName('ol-attribution')
    waterMarker[0].style.display = 'none'
})


</script>

<style scoped>
.map {
    width: 100vw;
    height: 98vh;
    background: transparent;
}


.ol-attribution {
    display: none !important;
}

.tools {
    position: fixed;
    z-index: 999;
    top: 60px;
    right: 30px;
    width: 32%;
    background: rgba(255, 255, 255, 0.5);
    border: 1px solid #3782b4 !important;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
</style>
最后修改:2024 年 08 月 21 日
如果觉得我的文章对你有用,请随意赞赏