11 OpenLayers学习笔记-各种控件

412 阅读5分钟

需求

地图上增加旋转、缩放、比例尺、鼠标经纬度等控件。

实现过程

通过ol.Map({controls})实现各种控件的添加和样式自定义。

知识点

  • ol.control.defaults.defaults()包含3个控件的配置:版权所属信息attribution、缩放zoom、旋转rotate
  • 可通过ol.control.defaults.defaults().extend([])扩展各种控件,也可以通过map.addControl()方法添加控件。
  • ol.control.FullScreen()全屏控件。
  • ol.control.ScaleLine()比例尺控件。
  • ol.control.ZoomSlider()缩放滑块控件。
  • ol.control.OverviewMap()小地图鹰眼控件。
  • ol.control.ZoomToExtent()一键恢复到默认视图控件。
  • ol.control.MousePosition()鼠标经纬度实时显示控件。
  • 每个控件默认都有一定的样式和摆放位置,比如缩放按钮和缩放滑块在左上角、鼠标位置在右上角、比例尺和小地图在左下角、版权信息在右下角等。可以通过设置自定义类名className、父元素容器target、文本信息labeltitle信息tipLabel等配置自定义控件的样式和位置。
  • target配置的值可以是元素的id,也可以直接是DOM元素。
  • map.getView().setRotation()将视图旋转到指定角度。
  • 鼠标经纬度实时显示控件的coordinateFormat参数可以格式化显示的经纬度值。placeholder参数可以配置鼠标不在地图范围内时显示的文本。

代码HTML+CSS+JS

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/9.2.4/ol.min.css" integrity="sha512-bc9nJM5uKHN+wK7rtqMnzlGicwJBWR11SIDFJlYBe5fVOwjHGtXX8KMyYZ4sMgSL0CoUjo4GYgIBucOtqX/RUQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <title>各种工具</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
    html,
    body,
    #app,
    .app-map {
        height: 100%;
        height: 100%;
    }
    .app-btns {
        position: fixed;
        right: 10px;
        top: 50%;
        background-color: #fff;
        box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .5);
        width: 210px;
        padding: 25px;
        text-align: center;
        border-radius: 5px;
        z-index: 2;
        transform: translateY(-50%);
    }
    #app .app-btns .ctrl {
        position: relative;
        width: 100%;
        height: 100%;
        background-color: transparent;
    }
    .app-btns .contorl button {
        font-size: 16px;
        border: none;
        padding: 0px 15px;
        border-radius: 0px;
        color: #fff;
        background-color: #409eff;
        border-color: #409eff;
        cursor: pointer;
        border: none;
        margin-bottom: 5px;
        line-height: 40px;
        height: 40px;
        width: 100%;
    }
    #app .app-btns button:focus,
    #app .app-btns button:hover {
        background: #66b1ff;
        border-color: #66b1ff;
        color: #fff;
        outline: none;
    }
    .app-btns .contorl {
        height: 40px;
        width: 100%;
        margin-bottom: 10px;
    }
    #zoom-to-extent button {
        width: 100%;
    }
    #zoom .ctrl {
        display: flex;
    }
    #mouse-position {
        position: relative;
        text-align: center;
    }
    #mouse-position .ol-mouse-position {
        top: 0;
        right: 0;
        position: relative;
        height: 40px;
        line-height: 40px;
        background-color: #409eff;
        border-color: #409eff;
        color: #fff;
        font-size: 16px;
    }
    #rotate {
        position: relative;
        display: flex;
    }
    #rotate .ol-rotate {
        position: relative;
        top: 0;
        right: 0;
        bottom: 0;
        width: 50%;
    }
    #rotate .ol-rotate button {
        margin: 0;
    }
    #rotate .manual-rorate {
        width: 50%;
    }
    #scale-line {
        position: relative;
        height: 60px;
    }
    #scale-line .ol-scale-bar {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
    }
    #zoom-slider {
        position: relative;
        height: auto;
    }
    #zoom-slider .ol-zoomslider  {
        top: 0;
        left: 0;
        height: 200px;
        position: relative;
        width: 36px;
        margin: 0 auto;
    }
    #zoom-slider .ol-zoomslider button {
        margin-bottom: 0;
        margin: 0;
    }
    #overview-map {
        position: relative;
        height: 150px;
    }
    #overview-map .ol-overviewmap {
        left: 5px;
        bottom: 0;
    }
    .ol-attribution,
    #attribution {
        height: 40px;
        line-height: 40px;
    }
    #rotate .ol-control,
    #attribution .ol-control {
        background-color: transparent;
    }
    </style>
</head>
<body>
    <div id="app">
        <div class="app-map" id="app-map">
            <div class="app-btns">
                <div class="contorl" id="zoom-to-extent"></div>
                <div class="contorl" id="zoom"></div>
                <div class="contorl" id="full-screen"></div>
                <div class="contorl" id="mouse-position"></div>
                <div class="contorl" id="rotate">
                    <button @click='handleClickRotateMap' type="button" class="manual-rorate">旋转</button>
                </div>
                <div class="contorl" id="scale-line"></div>
                <div class="contorl" id="zoom-slider"></div>
                <div id="overview-map"></div>
                <div id="attribution"></div>
            </div>
        </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/9.2.4/dist/ol.min.js" integrity="sha512-xXS2hdEzrUC2BFO0fIJ+d/bwScOLgN+W7psE4XXq6xULXjKFCskUNe8QOVVUsB7vtYRI5ZS0Ie4EgS4VzJQBkQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.14/vue.global.prod.min.js" integrity="sha512-huEQFMCpBzGkSDSPVAeQFMfvWuQJWs09DslYxQ1xHeaCGQlBiky9KKZuXX7zfb0ytmgvfpTIKKAmlCZT94TAlQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script>
    const { createApp } = Vue;
    const vm = createApp({
        data() {
            return {
                map: {}
            }
        },
        methods: {
            // 初始化地图
            initMap() {
                const attributions = '<a href="https://ditu.amap.com/" target="_blank">&copy; 地图版权归高德地图所有</a>';
                // 图层资源
                const source = new ol.source.XYZ({
                    attributions: attributions,
                    url: 'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
                });
                // 高德地图瓦片地址
                const mainLayer = new ol.layer.Tile({
                    source 
                });
                //  初始化地图
                this.map = new ol.Map({
                    target: 'app-map',
                    layers: [mainLayer],
                    controls: ol.control.defaults.defaults({
                        zoom: true, // 放大缩小工具
                        zoomOptions: {
                            zoomInLabel: '放大 +', // 放大按钮文本
                            zoomInTipLabel: '点击放大', // 放大按钮title
                            zoomOutLabel: '缩小 -', // 缩小按钮文本
                            zoomOutTipLabel: '点击缩小', // 缩小按钮title
                            target: 'zoom', // 父元素ID
                            className: 'ctrl', // 自定义类名
                            duration: 500, // 动画效果的持续时间
                            delta: 0.1 // 每次点击放大缩小的层级,默认为1
                        },
                        rotate: true, // 旋转工具
                        rotateOptions: {
                            tipLabel: '摆正', // title文本
                            autoHide: false, // 角度为0的时候是否自动隐藏
                            target: 'rotate', // 父元素ID
                            compassClassName: 'icon', // 旋转图标的自定义类名
                            duration: 250, // 旋转动画的持续时间
                            resetNorth: (a) => { // 默认是点击后旋转到0度,可自定义点击后的操作,可以覆盖原有的
                                this.map.getView().setRotation(0);
                            }
                        },
                        attribution: true, // 地图版权信息工具
                        attributionOptions: {
                            target: 'attribution', // 父元素ID
                            collapsed: false, // 默认折叠
                            collapsible: true // 是否可折叠,显示折叠按钮 106.577545 29.565593
                        }
                    }).extend([
                        // 全屏退出全屏工具
                        new ol.control.FullScreen({
                            label: '全屏', // 全屏按钮文本
                            labelActive: '退出全屏', // 退出全屏按钮文本
                            tipLabel: '全屏/退出全屏', // 按钮title
                            className: 'ctrl', // 自定义类名
                            target: 'full-screen', // 父元素ID
                            activeClassName: 'is-full', // 全屏状态下按钮自定义类名
                            inactiveClassName: 'not-full' // 不是全屏状态下按钮自定义类名
                        }),
                        // 比例尺工具
                        new ol.control.ScaleLine({
                            bar: true, // 展示为柱状,默认是直线
                            text: true, // 显示比例尺数字 1:421,111,348,当bar为true是生效
                            units: 'metric', // 单位,默认米制 {'degrees'} {'imperial'} {'nautical'} {'metric'} {'us'}
                            // className: 'sccale-line', // 自定义类名
                            steps: 4, // 柱状的比例尺时,将柱状分为几段,默认4
                            target: 'scale-line'// 父元素ID
                        }),
                        // 缩放滑块工具
                        // https://openlayers.org/en/v8.1.0/examples/zoomslider.html
                        new ol.control.ZoomSlider({
                            // className: 'ol-zoomslider ol-zoomslider-custom', // 自定义类名
                            duration: 500, // 缩放动画执行时间
                            target: 'zoom-slider' // 父元素ID
                        }),
                        // 小地图工具
                        new ol.control.OverviewMap({
                            target: 'overview-map', // 父元素ID
                            className: 'ol-overviewmap ol-overviewmap-custom', // 自定义类名
                            collapsed: false, // 默认折叠
                            collapsible: true, // 是否可折叠,显示折叠按钮
                            label: 'op', // 展开的文本
                            collapseLabel: 'cl', // 折叠的文本
                            rotateWithView: false, // 是否跟着地图旋转
                            tipLabel: '小地图', // 文本的title
                            layers: [ // 小地图内部的图层
                                new ol.layer.Tile({
                                    source: new ol.source.XYZ({
                                        url: 'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
                                    })
                                })
                            ]
                        }),
                        // 恢复到置顶视图工具
                        new ol.control.ZoomToExtent({
                            extent: [7108532.525146691, 2150882.129043405, 16501114.56082915, 6646602.384664332], // 恢复视图的经纬度范围
                            label: '恢复默认视图', // 展示的文本
                            tipLabel: '点击恢复默认视图', // title文本
                            target: 'zoom-to-extent', // id 或者DOM document.getElementById('zoomToExtent')
                            className: 'zoomToExtent ctrl' // 自定义类名
                        }),
                        // 展示鼠标经纬度工具
                        new ol.control.MousePosition({
                            projection: 'EPSG:4326', // 经纬度的坐标系
                            coordinateFormat: function (coordinate) { // 格式化经纬度
                                return '(' + coordinate.map(e => {
                                    return e.toFixed(3)
                                }).join(',') + ')';
                            },
                            target: 'mouse-position', // 父元素ID
                            placeholder: '鼠标不在地图范围内'
                        })
                    ]),
                    view: new ol.View({
                        projection: 'EPSG:3857',
                        center: ol.proj.transform([106.04453415000009, 36.70986324334069], 'EPSG:4326', 'EPSG:3857'),
                        zoom: 10
                    })
                });
                window.aa = this.map;
            },
            // 点击旋转地图
            handleClickRotateMap () {
                this.map.getView().setRotation(Math.floor(Math.random() * (2 * Math.PI)));
            }
        },
        mounted() {
            this.initMap();
        }
    }).mount('#app')
    </script>
</body>
</html>

参考文章

小地图官方栗子

Zoom控件官网文档

addControl官网文档

Rotate控件官网文档

setRotation官方文档

ScaleLine控件官网文档

FullScreen控件官网文档

Attribution控件官网文档

ZoomSlider控件官网文档

OverviewMap控件官网文档

ZoomToExtent控件官网文档

MousePosition控件官网文档

全屏、旋转、缩放、版权信息官方栗子