侧边栏壁纸
  • 累计撰写 21 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

openlayers6卷帘对比

南风过境
2023-12-10 / 0 评论 / 0 点赞 / 5 阅读 / 6781 字 / 正在检测是否收录...

借鉴自:Openlayers 卷帘功能_openlayers 卷帘分析-CSDN博客

原理

其实就是两个图层,通过裁剪上面图层的大小,来控制下方图层的展示大小

所以除了map以外,还需要一个用来控制裁剪的工具(这个工具可以自己写样式,div也好,官网示例用的input也好)

步骤

  1. 创建好一个至少包含两个底图图层的Map实例(map的样式定位要设置relative,让控制工具能按照map的位置来偏移)

  2. 对控制工具添加onmousedown ,并在拖拽过程中在onmousemove 事件中对这个控制工具的位置进行变换

  3. 控制工具的位置一旦变化,就同时更新map上方图层的裁剪

map图层裁剪的刷新需要用到prerender,postrender 这两个事件(ol6中是这两个,ol5中是precompose,postcompose

代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Layer Swipe</title>
    <script src="./v6.12.0-dist/ol.js"></script>
    <link rel="stylesheet" href="./v6.12.0-dist/ol.css">
    <style>
        .map {
            margin: auto;
            width: 90%;
            height: 400px;
            position: relative;
        }

        #swipeContainer {
            position: absolute;
            opacity: 0.8;
            width: 0.625rem;
            height: 100%;
            /* margin: 0 auto; */
            top: 0;
            left: 50%;
            background-color: rgba(50, 50, 50, 0.75);
            cursor: col-resize;
            z-index: 2;
        }

        #swipeContainer:hover {
            opacity: 0.5;
        }

        #swipeDiv {
            border: solid 0.5px #ffffff;
            height: 100%;
            width: 0px;
            margin: 0 auto;
        }

        #swipeDiv .handle {
            width: 51px;
            height: 24px;
            margin-top: -12px;
            margin-left: -20px;
            top: 50%;
            left: 0;
            position: absolute;
            z-index: 30;
            font-family: "CalciteWebCoreIcons";
            speak: none;
            font-size: 12px;
            font-style: normal;
            font-weight: normal;
            font-variant: normal;
            text-transform: none;
            text-indent: 0;
            line-height: 1;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
            background-color: black;
            color: white;
            opacity: 0.6;
        }

        *,
        *:before,
        *:after {
            -moz-box-sizing: border-box;
            -webkit-box-sizing: border-box;
            box-sizing: border-box;
        }

        .handle:before {
            margin: 0 18px 0 5px;
            content: "\0399\0399\0399";
            width: 20px;
            height: 24px;
            line-height: 2;
        }

        .handle:after {
            content: "\0399\0399\0399";
            width: 20px;
            height: 24px;
            line-height: 2;
        }
    </style>
</head>

<body>
    <div id="map" class="map">
        <div id="swipeContainer">
            <div id="swipeDiv">
                <div class="handle"></div>
            </div>
        </div>
    </div>
    <script>
        const vec = new ol.layer.Tile({
            source: new ol.source.XYZ({
                url: 'http://t4.tianditu.com/DataServer?T=img_w&tk={密钥}&x={x}&y={y}&l={z}',
                maxZoom: 20,
            }),
        });

        const aerial = new ol.layer.Tile({
            source: new ol.source.XYZ({
                url: 'http://t4.tianditu.com/DataServer?T=vec_w&tk={密钥}&x={x}&y={y}&l={z}',
                maxZoom: 20,
            }),
        });

        const zhuji = new ol.layer.Tile({
            source: new ol.source.XYZ({
                url: 'http://t4.tianditu.com/DataServer?T=cva_w&tk={密钥}&x={x}&y={y}&l={z}',
                maxZoom: 20,
            }),
        });

        const map = new ol.Map({
            layers: [vec, aerial, zhuji],  // zhuji这个图层可以忽略
            target: 'map',
            view: new ol.View({
                center: ol.proj.fromLonLat([116, 33]),
                zoom: 12,
            }),
        });
        window.map = map;
        var swipe = document.getElementById("swipeContainer");
        var obj = {};
        swipe.onmousedown = function (event) {
            var e = event || window.event;
            // map容器左侧和浏览器左侧的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离
            obj.diffX = e.clientX - this.offsetLeft;
            document.onmousemove = function (event) {
                var e = event || window.event;
                // 控制工具距离map容器左侧的距离 = 鼠标移动时位置相对于浏览器最左边的距离-map容器左侧和浏览器左侧的距离
                var moveX = e.clientX - obj.diffX;
                // 控制工具距离map容器左侧的距离不能小于0 也不能大于map容器宽度
                if (moveX < 0) {    
                    moveX = 0
                } else if (moveX > document.getElementById("map").offsetWidth) {
                    moveX = document.getElementById("map").offsetWidth
                }
                swipe.style.left = moveX + 'px';

                //重新渲染图层->prerender->postrender
                map.render();
            };
            document.onmouseup = function () {
                this.onmousemove = null;
                this.onmouseup = null;
            }
        };

        aerial.on('prerender', function (event) {
            var swipe = document.getElementById("swipeContainer");
            var ctx = event.context;
            //计算图层在canvas画布上需要显示的范围
            var mapSize = map.getSize();    // [map的宽度, map的高度]
            var height = event.context.canvas.height;
            var width = event.context.canvas.width;
            var swipeWidth = swipe.offsetLeft * width / mapSize[0];

            // 裁剪的范围就是一个矩形,定义矩形的四个顶点(左上、右上、左下、右下)
            var tl = [swipeWidth, 0];
            var tr = [width, 0];
            var bl = [swipeWidth, height];
            var br = [width, height];

            ctx.save();
            //绘制裁剪路径(左上->左下->右下->右上)
            ctx.beginPath();
            ctx.moveTo(tl[0], tl[1]);
            ctx.lineTo(bl[0], bl[1]);
            ctx.lineTo(br[0], br[1]);
            ctx.lineTo(tr[0], tr[1]);
            ctx.closePath();
            //裁剪,裁剪路径以外的部分不会绘制在canvas上下文中
            ctx.clip();
        });

        aerial.on('postrender', function (event) {
            const ctx = event.context;
            ctx.restore();
        });
    </script>
</body>

</html>

0

评论区