meface/docs/article/gis/openlayers/44customcontrol.md

10 KiB

title date author tags categories
自定义导航 2020-10-29 ac
OpenLayers
GIS

自定义导航

来实现一个很久以前比较流行的自定义导航控件。

这需要了解CSS的定位positionbackground属性的知识,来学习构建这个组件,后续的事件交互就是通过View对象控制地图视图的操作。

image-20201110173336191

材料:

map_view.png

toolbar_rbg.png

完整代码:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="css/ol.css" type="text/css">
    <style>
        .map {
            position: relative;
            height: 400px;
            width: 100%;
        }

        /*自定义导航start*/
        .map-toolbar {
            position: absolute;
            left: 20px;
            top: 20px;
            visibility: visible;
            width: 52px;
            overflow: visible;
            z-index: 150;
        }

        .map-pancontrol {
            position: relative;
            display: block;
            width: 52px;
            height: 52px;
            background: url("./img/map_view.png") 0 175px;
        }

        .map-pan-left, .map-pan-top, .map-pan-right, .map-pan-bottom {
            position: absolute;
            cursor: pointer
        }

        .map-pan-left, .map-pan-right {
            width: 12px;
            height: 18px;
            top: 17px
        }

        .map-pan-top, .map-pan-bottom {
            width: 18px;
            height: 12px;
            left: 17px
        }

        .map-pan-left {
            left: 8px
        }

        .map-pan-right {
            left: 32px
        }

        .map-pan-top {
            top: 8px
        }

        .map-pan-bottom {
            top: 31px
        }

        .map-pan-left:hover,
        .map-pan-top:hover,
        .map-pan-right:hover,
        .map-pan-bottom:hover {
            background: url(./img/map_view.png);
        }

        .map-pan-left:hover {
            background-position: -52px -110px
        }

        .map-pan-top:hover {
            background-position: -70px -112px
        }

        .map-pan-right:hover {
            background-position: -61px -110px
        }

        .map-pan-bottom:hover {
            background-position: -84px -110px
        }

        .map-zoomcontrol {
            position: relative;
            left: 14px;
            width: 24px;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            -o-user-select: none;
            user-select: none
        }

        .map-zoom-plus,
        .map-zoom-minus,
        .map-zoom-cursor {
            background: url(./img/map_view.png);
            cursor: pointer
        }

        .map-zoom-ruler,
        .map-zoom-mask {
            background: url(./img/toolbar_rbg.png);
            cursor: pointer
        }

        .map-zoom-ruler {
            overflow: visible
        }

        .map-zoom-plus,
        .map-zoom-minus {
            width: 24px;
            height: 21px
        }

        .map-zoom-plus {
            background-position: 0 -217px
        }

        .map-zoom-plus:hover {
            background-position: 0 -194px
        }

        .map-zoom-minus {
            background-position: -26px -224px
        }

        .map-zoom-minus:hover {
            background-position: -26px -195px
        }

        .map-zoom-ruler {
            display: block;
            width: 12px;
            height: 147px;
            position: relative;
            left: 6px;
            background-position: 0 0
        }

        .map-zoom-mask,
        .map-zoom-cursor {
            position: absolute
        }

        .map-zoom-mask {
            height: 45px;
            width: 12px;
            background-position: -14px 0
        }

        .map-zoom-cursor {
            top: 45px;
            width: 24px;
            height: 20px;
            left: -6px;
            background-position: -127px -164px
        }

        .map-zoom-cursor:hover {
            background-position: -127px -141px
        }

        .map-locate {
            position: relative;
            left: 17px;
            display: block;
            width: 18px;
            height: 18px;
            background: url(./img/map_view.png) -130px -185px;
            cursor: pointer
        }

        .map-touch-toolbar .map-zoomcontrol {
            position: absolute;
            right: 4px;
            bottom: -80px;
            z-index: 500;
            width: 35px;
            background-color: white;
            background-color: rgba(255, 255, 255, 0.9);
            border-radius: 3px;
            border: 1px solid #ccc;
            box-shadow: 1px 1px 10px 0 #ccc
        }

        .map-touch-toolbar .map-zoomcontrol:after {
            position: absolute;
            content: "";
            height: 1px;
            background: #ddd;
            top: 48px;
            width: 60%;
            margin: auto;
            left: 0;
            right: 0
        }

        /*自定义导航end*/
    </style>
    <script src="lib/ol.js"></script>
    <title>简单控件</title>
</head>
<body>
<h2>自定义导航</h2>
<div id="mouse_position"></div>
<div id="map" class="map">
    <!--自定义导航start -->
    <div class="map-toolbar">
        <div class="map-pancontrol">
            <div class="map-pan-left" onclick="handleClickPan('left')"></div>
            <div class="map-pan-top" onclick="handleClickPan('top')"></div>
            <div class="map-pan-right" onclick="handleClickPan('right')"></div>
            <div class="map-pan-bottom" onclick="handleClickPan('bottom')"></div>
        </div>
        <div class="map-locate" onclick="reposition()"></div>
        <div class="map-zoomcontrol">
            <div class="map-zoom-plus" onclick="handleClickZoom('plus')"></div>
            <div class="map-zoom-ruler">
                <div class="map-zoom-mask"></div>
                <div class="map-zoom-cursor"></div>
            </div>
            <div class="map-zoom-minus" onclick="handleClickZoom('minus')"></div>
        </div>
    </div>
    <!--自定义导航end -->
</div>
<script type="text/javascript">

    var shenzhen = ol.proj.fromLonLat([113.958334, 22.535640]);
    var initZoom = 12;
    var map = new ol.Map({
        view: new ol.View({
            center: shenzhen,
            zoom: initZoom,
            maxZoom: 20,
            minZoom: 1
            // rotation: Math.PI/6
        }),
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM()
            })
        ],
        target: "map",
        controls: []//去除默认控件
    });
    var view = map.getView();

    function handleClickPan(type) {
        var oldExtent = view.calculateExtent();
        var height = oldExtent[3] - oldExtent[1];
        var width = oldExtent[2] - oldExtent[0];
        var center = view.getCenter(), newCenter = null;
        switch (type) {
            case "left":
                newCenter = [center[0] - width / 2, center[1]];
                break;
            case "top":
                newCenter = [center[0], center[1] + height / 2];
                break;
            case "right":
                newCenter = [center[0] + width / 2, center[1]];
                break;
            case "bottom":
                newCenter = [center[0], center[1] - height / 2];
        }
        if (center) {
            view.animate({center: newCenter});
        }
    }

    function reposition() {
        view.setCenter(shenzhen);
        view.setZoom(initZoom);
    }

    function handleClickZoom(type) {
        var initZoom = view.getZoom();
        if (type == "plus") {
            view.setZoom(initZoom + 1);
        } else if (type == "minus") {
            view.setZoom(initZoom - 1);
        }
    }

    // ------------缩放条部分-------------
    // 初始化缩放条
    function getCalcMaskHeight() {
        var zoomBarHeight = document.getElementsByClassName("map-zoom-ruler")[0].clientHeight;
        var maskHeight = document.getElementsByClassName("map-zoom-cursor")[0].clientHeight;
        var zoomSilderHeight = zoomBarHeight - maskHeight / 2;

        var maxZoom = view.getMaxZoom();
        var minZoom = view.getMinZoom();
        var currZoom = view.getZoom();
        return (currZoom - minZoom) / (maxZoom - minZoom) * zoomSilderHeight;
    }

    var initMaskHeight = getCalcMaskHeight()
    document.getElementsByClassName("map-zoom-mask")[0].style.height = initMaskHeight + "px";
    document.getElementsByClassName("map-zoom-cursor")[0].style.top = initMaskHeight + "px";

    //缩放条的拖动
    document.getElementsByClassName("map-zoom-cursor")[0].onmousedown = function (evt) {
        var that = this;
        var oEvent = evt || event;
        var disY = oEvent.clientY - parseInt(that.style.top);

        that.onmousemove = function (evt) { //实时改变目标元素obox的位置
            var oEvent = evt || event;
            var curY = oEvent.clientY - disY;
            //修改移动cursor的位置
            if (curY < 0) {
                that.style.top = 1 + 'px';
            } else if (curY > 135) {
                that.style.top = 135 + 'px';
            } else {
                that.style.top = oEvent.clientY - disY + 'px';
            }
            //修改mask的位置
            document.getElementsByClassName("map-zoom-mask")[0].style.height = that.style.top;
            //设置地图
            var zoomBarHeight = document.getElementsByClassName("map-zoom-ruler")[0].clientHeight;
            var maxZoom = view.getMaxZoom();
            var minZoom = view.getMinZoom();
            var newZoom = minZoom + (maxZoom - minZoom) * (parseInt(that.style.top) / zoomBarHeight);
            view.setZoom(newZoom);
        };
        //停止拖动
        that.onmouseup = function () {
            that.onmousemove = null;
            that.onmouseup = null;
        };
        that.onmouseout = function () {
            that.onmousemove = null;
            that.onmouseout = null;
        };
    }
    //绑定视图的缩放事件
    view.on("change:resolution", function changeResolution(e) {
        var maskHeight = getCalcMaskHeight();
        document.getElementsByClassName("map-zoom-mask")[0].style.height = maskHeight + "px";
        document.getElementsByClassName("map-zoom-cursor")[0].style.top = maskHeight + "px";
    })

</script>
</body>
</html>