mapboxGL卷帘实现

2021-09-10 11:01:40 浏览数 (1)

概述

卷帘对比是webgis中常见的一种对比方式,本文讲述一下如何在mapboxGL中实现卷帘对比。

效果

实现思路

  1. 通过input[range]实现卷帘的操作;
  2. 通过地图的事件实现两个地图的联动操作。

实现代码

代码语言:javascript复制
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <title>mapboxGL卷帘</title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link href='https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css' rel='stylesheet' />
  <style>
    html, body, .map {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
    }
    .map {
        position: absolute;
        left: 0;
        top: 0;
        font-size: 32px;
        color: white;
        padding: 100px 0;
    }

    .swipe input[type=range] {
        margin: 0;
        padding: 0;
        width: 100%;
        position: absolute;
        top: calc(50% - 18px);
        left: 0;
        z-index: 9;
        outline: none; 
        -webkit-appearance: none;
        height: 0;
        background-color: white;
    }

    .swipe input[type=range]::-webkit-slider-thumb {
        -webkit-appearance: none;
        height:36px;
        width: 36px;
        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABhklEQVRoQ 2XPU7EMBCFvyk4AAU3oOAMFJyKrXYRLAIa9lycgYIbUFAjCq9CAgpZO2PHTFDEuHX8PN97/ouw8CYLrx8H OsEPQFPoNIBX0KVBlYP9wSqLawU8AQqDawe7glUW1gp8H8SCHANHAlsKk0bHR7gDvgQ2ObMk5VAgEvgsRPcCaxyxEu/Ce0czVxNWwnsNA0VYFD8l95G4F4TL kPcAXcDsaoEKMAieJfgXOBl5ICtW8DnAJPwEkJRBJgpPgLgWetoCn9Ac46iONciChAoviimoSfv6sBQpHA4cfR5XQA8BvFN3MbAEQ3dgzghvbIrGpGAFuBpr7vllpC/eNsEogBQPT4HtvEMYi37gSaexMn7x7tGI1BzH2Mjl6cORdZDGIt8DBpbSUGBVjTPiP6Tb31VYBGbXDFq6JTwabMkwXQg3if4TH3 ebKfW9lA0x11XqcA1g7rOl7AppD1v2egLXDmr4noDlk3e8JWDus6XsCmkPW/Z6AtcOaviegOWTdv/gE9iihUjF faiWAAAAAElFTkSuQmCC);
        background-size: 100%;
        cursor: move;
    }

    .swipe .swipe-bar {
        position: fixed;
        width: 4px;
        height: 100%;
        content: ' ';
        top: 0;
        background: rgb(255, 0, 0);
        z-index: 9;
    }
  </style>
</head>

<body>
  <div class="swipe">
    <input type="range" id="swipe"/>
    <div class="swipe-bar" id="swipeBar"></div>
  </div>
  <div class="map" id="map1">map1</div>
  <div class="map" id="map2">map2</div>
  <script src='https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js'></script>
  <script>
   const style1 = {
        "version": 8,
        "name": "lzugis",
        "sources": {
            "nav": {
                "type": "raster",
                "tiles": ['https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'],
                "tileSize": 256
            }
        },
        "layers": [{
            "id": "nav",
            "type": "raster",
            "source": "nav",
            "minzoom": 0,
            "maxzoom": 17
        }]
    }
    const style2 = {
        "version": 8,
        "name": "lzugis",
        "sources": {
            "nav": {
                "type": "raster",
                "tiles": ['http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8'],
                "tileSize": 256
            }
        },
        "layers": [{
            "id": "nav",
            "type": "raster",
            "source": "nav",
            "minzoom": 0,
            "maxzoom": 17
        }]
    }
    const doms = document.getElementsByClassName('map')
    const maps = []
    const styles = [style1, style2]
    for (let i = 0; i < doms.length; i  ) {
        const dom = doms[i];
        maps.push(new mapboxgl.Map({
            container: dom,
            style: styles[i],
            center: [103.081163, 37.1612],
            zoom: 3.5,
            minZoom: 2,
            maxZoom: 18
        }))
    }

    maps.forEach(map => {
        const mapDom = map.getContainer().getAttribute('id')
        // 鼠标进入的时候注册事件
        map.on('mouseover', e => {
            const mouseDom = e.target.getContainer().getAttribute('id')
            if(mouseDom === mapDom) {
                map.on('move', moveEvent)
            } else {
                map.off('move', moveEvent)
            }
        })
        // 鼠标移除的时候关闭事件
        map.on('mouseout', e => {
            maps.forEach(map => {
                map.off('move', moveEvent)
            })
        })
    })

    function moveEvent(e) {
        const c = e.target.getCenter()
        const d = e.target.getContainer().getAttribute('id')
        const z = e.target.getZoom()
        maps.forEach(map => {
            if(d !== map.getContainer().getAttribute('id')) {
                map.setCenter(c)
                map.setZoom(z)
            }
        })
    }

    const map1 = document.getElementById('map1')
    const map2 = document.getElementById('map2')
    const WIDTH = map1.clientWidth
    const HEIGHT = map1.clientHeight

    const swipe = document.getElementById('swipe')
    const MAX = 1000
    swipe.setAttribute('min', 0)
    swipe.setAttribute('max', MAX)
    swipe.setAttribute('value', MAX / 2)
    swipe.oninput = function(e) {
        setStyle()
        
    }
    setStyle()

    function setStyle() {
        const v = swipe.value
        const left = Math.ceil((v / MAX) * WIDTH)
        map1.style.clip = `rect(0, ${left}px, ${HEIGHT}px, 0)`
        map2.style.clip = `rect(0, ${WIDTH}px, ${HEIGHT}px, ${left}px)`
        // 设置bar样式
        const swipeBar = document.getElementById('swipeBar')
        swipeBar.style.left = `${left - 2}px`
        // 设置swipe样式
        const hWIDTH = MAX / 2
        const isLeft = v < hWIDTH
        const offsetL = Math.abs(((hWIDTH - v) / hWIDTH) * 18)
        swipe.style.left = isLeft ? `-${offsetL}px` : `${offsetL}px`
    }
  </script>
</body>
</html>

0 人点赞