OpenLayers 地图定位

165 阅读2分钟

注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key

地图定位功能很常见,在移动端和PC端都需要经常用到,像百度、高德、谷歌都提供了方便快捷的定位功能。OpenLayers中也提供了定位的接口,通过ol.Geolocation即可实现地图定位功能。虽然OpenaLayers提供了定位类,但是在PC上的定位效果并不是很完善。本节主要介绍加载地图地图定位

1. 创建定位导航对象

在导航定位类中设置最终参数。

// 创建定位导航对象
const geolocation new ol.Geolocation({
    projection: map.getView().getProjection(),
    trackingtrue,  // 开启定位追踪
    trackingOptions: {
        maximumAge10000,
        enableHighAccuracytrue, // 是否开启高精度
        timeout600000 // 最大等待时间,微秒
    }
})

2. 监听位置事件

当位置信息改变时,更新导航数据。在定位过程中,监听定位错误事件,输出错误信息。

// 添加定位change事件
geolocation.on('change'evt => {
    $('#accuracy').text(geolocation.getAccuracy() + ' [m]');
    $('#altitude').text(geolocation.getAltitude() + ' [m]');
    $('#altitudeAccuracy').text(geolocation.getAltitudeAccuracy() + ' [m]');
    $('#heading').text(geolocation.getHeading() + ' [rad]');
    $('#speed').text(geolocation.getSpeed() + ' [m/s]');
})

// 定位错误处理事件
geolocation.on('error'error => {
    console.error("定位错误:", error.message)
})

// 定位导航事件位置变更处理
geolocation.on('change:position'() => {
    const coordinates = geolocation.getPosition()
    positionPoint.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null)
})

3. 地图定位

通过获取地图中心点进行定位,并更新中心点坐标。

const lonInput = document.querySelector(".lon-input")
const latInput = document.querySelector(".lat-input")
document.querySelector(".map-center").addEventListener('click', evt => {
    const center = map.getView().getCenter()
    lonInput.value = center[0]
    latInput.value = center[1]
})

根据地图中心点坐标跳转到定位位置。

document.querySelector(".navigator-location").addEventListener('click', evt => {
    if (lonInput.value && latInput.value) {
        removeLayerByName("centerPoint")
        const center = [+lonInput.value, +latInput.value]
        map.getView().animate({ center: center, zoom15 })
        const point = new ol.layer.Vector({
            sourcenew ol.source.Vector({
                features: [
                    new ol.Feature({
                        geometrynew ol.geom.Point(center)
                    })
                ]
            }),
            stylenew ol.style.Style({
                imagenew ol.style.Circle({
                    radius5,
                    fillnew ol.style.Fill({
                        color'red'
                    }),
                    strokenew ol.style.Stroke({
                        color'red'
                    })
                })
            })
        })
        point.setProperties({ layerName'centerPoint' })
        map.addLayer(point)
    }
})

4. 完整代码

其中libs文件夹下的包需要更换为自己下载的本地包或者引用在线资源。

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>地图定位</title>
    <meta charset="utf-8" />
    <script src="../libs/js/ol-5.3.3.js"></script>
    <script src="../libs/js/jquery-2.1.1.min.js"></script>
    <link rel="stylesheet" href="../libs/css//ol.css">
    <style>
        * {
            padding0;
            margin0;
            font-size14px;
            font-family'微软雅黑';
        }

        html,
        body {
            width100%;
            height100%;
        }

        #map {
            position: absolute;
            top50px;
            bottom0;
            width100%;
        }

        #lcoation {
            position: absolute;
            width100%;
            height50px;
            backgroundlinear-gradient(135deg#ff00cc#ffcc00#00ffcc#ff0066);
            color#fff;
        }

        .map-location {
            position: absolute;
            top50%;
            left63%;
            transformtranslateY(-50%);
            border-radius5px;
            border1px solid #50505040;
            padding5px 20px;
            color#fff;
            margin0 10px;
            background#377d466e;
        }

        .map-location:hover {
            cursor: pointer;
            filterbrightness(120%);
            backgroundlinear-gradient(135deg#c850c0#4158d0);
            transition-delay: .25s;
        }

        .active {
            backgroundlinear-gradient(135deg#c850c0#4158d0);
        }

        .navigator {
            position: absolute;
            line-height50px;
            left55%;
        }

        .navigator-location {
            border-radius5px;
            border1px solid #50505040;
            padding5px 20px;
            color#fff;
            margin0 10px;
            background#377d466e;
        }

        .navigator-location:hover {
            cursor: pointer;
            filterbrightness(120%);
            backgroundlinear-gradient(135deg#c850c0#4158d0);
            transition-delay: .25s;
        }

        .view-center {
            position: absolute;
            line-height50px;
            left20%;
        }

        .view-center span {
            border-radius5px;
            border1px solid #50505040;
            padding5px 20px;
            color#fff;
            margin0 10px;
            background#377d466e;
        }

        .view-center span:hover {
            cursor: pointer;
            filterbrightness(120%);
            backgroundlinear-gradient(135deg#c850c0#4158d0);
            transition-delay: .25s;
        }

        input[type='text'] {
            padding0 10px;
            height25px;
            border: none;
            border-radius2.5px;
        }

        input[type='text']:focus-visible {
            outline2px solid #8BC34A;
        }

        #location-info {
            position: absolute;
            padding10px;
            right20px;
            top70px;
            background-color#0028657a;
            border-radius2.5px;
            color#fff;
        }
    </style>
</head>

<body>
    <div id="map" title="地图显示"></div>
    <div id="lcoation">
        <button type="button" class="map-location">地图定位</button>
    </div>
    <div class="view-center">
        <span class="map-center">获取地图中心点</span>
        <input type="text" value="" class="lon-input">
        <input type="text" value="" class="lat-input">
    </div>
    <div class="navigator">
        <button type="button" class="navigator-location">导航定位</button>
    </div>
    <div id="location-info">
        <div id="container">
            <p>位置精度: <code id="accuracy"></code></p>
            <p>海拔高度: <code id="altitude"></code></p>
            <p>海拔精度: <code id="altitudeAccuracy"></code></p>
            <p>航向: <code id="heading"></code></p>
            <p>速度: <code id="speed"></code></p>
        </div>
    </div>
</body>

</html>

<script>
    //地图投影坐标系
    const projection = ol.proj.get('EPSG:3857');
    //==============================================================================//
    //============================天地图服务参数简单介绍==============================//
    //================================vec:矢量图层==================================//
    //================================img:影像图层==================================//
    //================================cva:注记图层==================================//
    //======================其中:_c表示经纬度投影,_w表示球面墨卡托投影================//
    //==============================================================================//
    const TDTImgLayer = new ol.layer.Tile({
        title"天地图影像图层",
        sourcenew ol.source.XYZ({
            url"http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=2a890fe711a79cafebca446a5447cfb2",
            attibutions"天地图注记描述",
            crossOrigin"anoymous",
            wrapXfalse
        })
    })
    const TDTImgCvaLayer = new ol.layer.Tile({
        title"天地图影像注记图层",
        sourcenew ol.source.XYZ({
            url"http://t0.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=2a890fe711a79cafebca446a5447cfb2",
            attibutions"天地图注记描述",
            crossOrigin"anoymous",
            wrapXfalse
        })
    })
    const map = new ol.Map({
        target"map",
        loadTilesWhileInteractingtrue,
        viewnew ol.View({
            // center: [11421771, 4288300],
            // center: [102.6914059817791, 25.10595662891865],
            center: [104.063598616048730.660919181071225],
            zoom10,
            worldsWraptrue,
            minZoom1,
            maxZoom20,
            projection"EPSG:4326"
        }),
        layers: [TDTImgLayerTDTImgCvaLayer],
        // 鼠标控件:鼠标在地图上移动时显示坐标信息。
        controls: ol.control.defaults().extend([
            // 加载鼠标控件
            // new ol.control.MousePosition()
        ])
    })
    map.on('click'evt => {
        console.log(evt.coordinate)
    })

    // 创建定位导航对象
    const geolocation = new ol.Geolocation({
        projection: map.getView().getProjection(),
        trackingtrue,  // 开启定位追踪
        trackingOptions: {
            maximumAge10000,
            enableHighAccuracytrue// 是否开启高精度
            timeout600000 // 最大等待时间,微秒
        }
    })

    // 添加定位change事件
    geolocation.on('change'evt => {
        $('#accuracy').text(geolocation.getAccuracy() + ' [m]');
        $('#altitude').text(geolocation.getAltitude() + ' [m]');
        $('#altitudeAccuracy').text(geolocation.getAltitudeAccuracy() + ' [m]');
        $('#heading').text(geolocation.getHeading() + ' [rad]');
        $('#speed').text(geolocation.getSpeed() + ' [m/s]');
    })

    // 定位错误处理事件
    geolocation.on('error'error => {
        console.error("定位错误:", error.message)
    })

    // 精确模式定位
    const accuracyFeature = new ol.Feature()
    geolocation.on("change:accuracyGeometry"() => {
        accuracyFeature.setGeometry(geolocation.getAccuracyGeometry())
    })

    // 定位点要素
    const positionPoint = new ol.Feature({
        stylenew ol.style.Style({
            imagenew ol.style.Circle({
                radius5,
                fillnew ol.style.Fill({
                    color"yellow"
                }),
                strokenew ol.style.Stroke({
                    color"#blue",
                    width2
                })
            })
        })
    })
    // 定位导航事件位置变更处理
    geolocation.on('change:position'() => {
        const coordinates = geolocation.getPosition()
        positionPoint.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null)
    })

    //创建定位点矢量图层(featuresOverlay)
    const features = new ol.layer.Vector({
        sourcenew ol.source.Vector({
            features: [accuracyFeature, positionPoint]
        })
    });
    features.setProperties({ layerName"locationLayer" })
    map.addLayer(features)

    // 定位按钮事件
    document.querySelector('.map-location').addEventListener('click'evt => {
        // 若添加了图层,则移除
        // removeLayerByName("locationLayer")
        // 启动位置跟踪
        geolocation.setTracking(true)
        navigator.geolocation.getCurrentPosition(function (position) {
            console.log(position)
            const coordinate = [position.coords.longitude, position.coords.latitude]

            map.getView().animate({ center: coordinate, zoom15 })
        })

    })

    const lonInput = document.querySelector(".lon-input")
    const latInput = document.querySelector(".lat-input")
    document.querySelector(".map-center").addEventListener('click'evt => {
        const center = map.getView().getCenter()
        lonInput.value = center[0]
        latInput.value = center[1]
    })

    document.querySelector(".navigator-location").addEventListener('click'evt => {
        if (lonInput.value && latInput.value) {
            removeLayerByName("centerPoint")
            const center = [+lonInput.value, +latInput.value]
            map.getView().animate({ center: center, zoom15 })
            const point = new ol.layer.Vector({
                sourcenew ol.source.Vector({
                    features: [
                        new ol.Feature({
                            geometrynew ol.geom.Point(center)
                        })
                    ]
                }),
                stylenew ol.style.Style({
                    imagenew ol.style.Circle({
                        radius5,
                        fillnew ol.style.Fill({
                            color'red'
                        }),
                        strokenew ol.style.Stroke({
                            color'red'
                        })
                    })
                })
            })
            point.setProperties({ layerName'centerPoint' })
            map.addLayer(point)
        }
    })

    function removeLayerByName(layerName) {
        const layers = map.getLayers().getArray()
        layers.forEach(layer => {
            if (layer.get('layerName') === layerName) map.removeLayer(layer)
        });
    }

</script>

OpenLayers示例数据下载,请回复关键字:ol数据

全国信息化工程师-GIS 应用水平考试资料,请回复关键字:GIS考试

【GIS之路】 已经接入了智能助手,欢迎关注,欢迎提问。

欢迎访问我的博客网站-长谈GIShttp://shanhaitalk.com

都看到这了,不要忘记点赞、收藏 + 关注

本号不定时更新有关 GIS开发 相关内容,欢迎关注 !