OpenLayers 分屏对比(地图联动)

news2025/6/12 11:25:37

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

地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。通过创建多个地图,在其中任意一个地图上缩放或者拖动时,其它地图也进行同样的操作。常见的分屏模式有二分屏、四分屏、六分屏和八分屏。本节主要介绍加载地图分屏对比

1. 创建分屏视图

在创建地图函数中需要传入绑定地图ID值,默认创建二分屏,实现偶数地图加载天地图矢量底图,奇数地图加载天地图影像底图。


/**
 *  创建地图 
 *  mapId:地图ID
 */ 
function createMap(mapId) {
    const num = mapId.replace(/[^d.]/g, "")
    const layer = num % 2 === 0 ? TDTVecLayer : TDTImgLayer
    const vectorMap = new ol.Map({
        target: mapId,
        layers: [
            layer,
            TDTCvaLayer
        ],
        view: new ol.View({
            center: [11421771, 4288300],
            zoom: 5,
            worldsWrap: true,
            minZoom: 1,
            maxZoom: 20,
            projection: projection
        })
    })
    return vectorMap
}

2. 地图分屏操作

地图分屏操作最主要在于根据分屏数量创建地图,通过循环创建地图,并根据位置调整宽高比例,设置地图样式为左浮动。并在点击分屏按钮时切换按钮激活样式,清除销毁的地图元素和清空地图数据。

/**
 * 地图分屏操作
 */
function mapSplit() {
    // 二分屏
    document.getElementById('two').addEventListener('click', evt => {
        toogleAciveClass(evt.target)
        maps = []
        removeChildMap(mapsContainer)
        for (let i = 0; i < 2; i++) {
            // 创建地图元素
            const mapId = 'two-' + i
            const mapTarget = document.createElement('div')
            mapTarget.className = 'split-map'
            mapTarget.style.height = "100%"
            mapTarget.style.width = "50%"
            mapTarget.setAttribute('id', mapId)
            mapsContainer.appendChild(mapTarget)
            const map = createMap(mapId)
            maps.push(map)
        }
        mapZoomAndMove()
    })

    // 四分屏
    document.getElementById('four').addEventListener('click', evt => {
        toogleAciveClass(evt.target)
        maps = []
        removeChildMap(mapsContainer)
        for (let i = 0; i < 4; i++) {
            // 创建地图元素
            const mapId = 'four-' + i
            const mapTarget = document.createElement('div')
            mapTarget.className = 'split-map'
            mapTarget.style.height = "50%"
            mapTarget.style.width = "50%"
            mapTarget.setAttribute('id', mapId)
            mapsContainer.appendChild(mapTarget)
            const map = createMap(mapId)
            maps.push(map)
        }
        mapZoomAndMove()
    })
    // 六分屏
    document.getElementById('six').addEventListener('click', evt => {
        toogleAciveClass(evt.target)
        maps = []
        removeChildMap(mapsContainer)
        for (let i = 0; i < 6; i++) {
            // 创建地图元素
            const mapId = 'six-' + i
            const mapTarget = document.createElement('div')
            mapTarget.className = 'split-map'
            mapTarget.style.height = 100 / 3 + "%"
            mapTarget.style.width = '50%'
            mapTarget.setAttribute('id', mapId)
            mapsContainer.appendChild(mapTarget)
            const map = createMap(mapId)
            maps.push(map)
        }
        mapZoomAndMove()
    })
    // 八分屏
    document.getElementById('eight').addEventListener('click', evt => {
        toogleAciveClass(evt.target)
        maps = []
        removeChildMap(mapsContainer)
        for (let i = 0; i < 8; i++) {
            // 创建地图元素
            const mapId = 'eight-' + i
            const mapTarget = document.createElement('div')
            mapTarget.className = 'split-map'
            mapTarget.style.height = "25%"
            mapTarget.style.width = '50%'
            mapTarget.setAttribute('id', mapId)
            mapsContainer.appendChild(mapTarget)
            const map = createMap(mapId)
            maps.push(map)
        }
        mapZoomAndMove()
    })
}

3. 地图联动

地图联动原理很简单,只需要将其它地图对象的View设置为目标对象的视图即可

// 地图联动
function mapZoomAndMove() {
    maps.forEach(map => {
        maps.forEach(targetMap => {
            map.setView(targetMap.getView())
        })
    })
}

4. 按钮渐变色

  .disable-btn{
    background-color: #c8e7ff;
    border-color: #9e9e9e3d;
  }
  .no-disable-btn{
    color: #d1d1d1;
    background-color: #0167cc;
    border-color: #fff;
    &:hover{
      color:#fff;
      filter: brightness(110%) opacity(100%);
      transition: all .5s ease-in;
      background: linear-gradient(to bottom right, #9a99f1, #0167cc);
    }
    &:focus{
      filter: brightness(120%);
      transition: all .5s ease-in;
      background: radial-gradient(circle at center, #9a99f1, #0167cc);
    }
  }

// 背景色延迟
.tool-bar-item{
  width: 30px;
  height: 30px;
  color: #ffff;
  cursor: pointer;
  border-right: 1px solid #f0f4f76b;
  &:hover{
    background-color:  #248cfba8;
    transition-delay: .25s;
  }
}

5. 完整代码

其中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>
    <script src="../libs/proj4.js"></script>
    <link rel="stylesheet" href="../libs/css/ol.css">
    <style>
        * {
            padding: 0;
            margin: 0;
            font-size: 14px;
            font-family: '微软雅黑';
        }

        html,
        body {
            width: 100%;
            height: 100%;
        }

        #imageMap {
            position: absolute;
            top: 50px;
            bottom: 0;
            left: 0;
            width: 50%;
        }

        #vectorMap {
            position: absolute;
            top: 50px;
            bottom: 0;
            left: 50%;
            width: 50%;

        }

        .split-div {
            position: absolute;
            width: 100%;
            height: 50px;
            line-height: 50px;
            background: linear-gradient(135deg, #ff00cc, #ffcc00, #00ffcc, #ff0066);
            color: #fff;
            text-align: center;
        }

        .split-span {
            border-radius: 5px;
            border: 1px solid #50505040;
            padding: 5px 20px;
            color: #fff;
            margin: 0 10px;
            background: #377d466e;
            transition: background-color 10s ease-in-out 10s;
        }

        .split-span:hover {
            cursor: pointer;
            font-size: 1.25em;
            filter: brightness(120%);
            background: linear-gradient(135deg, #c850c0, #4158d0);
        }

        .active {
            background: linear-gradient(135deg, #c850c0, #4158d0);
        }

        #map-main {
            position: absolute;
            top: 50px;
            bottom: 0;
            left: 0;
            right: 0;
        }

        .clearfix::after {
            display: block;
            content: "";
            clear: both;
        }

        .split-map {
            float: left;
        }
    </style>
</head>

<body>
    <div class="split-div ">
        <span id="two" class="split-span">二分屏</span>
        <span id="four" class="split-span">四分屏</span>
        <span id="six" class="split-span">六分屏</span>
        <span id="eight" class="split-span">八分屏</span>
    </div>
    <div id="map-main" class="clearfix"></div>
</body>

</html>

<script>
    //地图投影坐标系
    const projection = ol.proj.get('EPSG:3857');
    //==============================================================================//
    //============================天地图服务参数简单介绍==============================//
    //================================vec:矢量图层==================================//
    //================================img:影像图层==================================//
    //================================cva:注记图层==================================//
    //======================其中:_c表示经纬度投影,_w表示球面墨卡托投影================//
    //==============================================================================//
    const TDTImgLayer = new ol.layer.Tile({
        title: "天地图影像图层",
        source: new ol.source.XYZ({
            url: "http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=2a890fe711a79cafebca446a5447cfb2",
            attibutions: "天地图注记描述",
            crossOrigin: "anoymous",
            wrapX: false
        })
    })
    const TDTCvaLayer = new ol.layer.Tile({
        title: "天地图影像注记图层",
        source: new ol.source.XYZ({
            url: "http://t0.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=2a890fe711a79cafebca446a5447cfb2",
            attibutions: "天地图注记描述",
            crossOrigin: "anoymous",
            wrapX: false
        })
    })

    const TDTVecLayer = new ol.layer.Tile({
        title: "天地图影像图层",
        source: new ol.source.XYZ({
            url: "http://t0.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=2a890fe711a79cafebca446a5447cfb2",
            attibutions: "天地图注记描述",
            crossOrigin: "anoymous",
            wrapX: false
        })
    })

    /**
     *  创建地图 
     *  mapId:地图ID
     */  
    function createMap(mapId) {
        const num = mapId.replace(/[^d.]/g, "")
        const layer = num % 2 === 0 ? TDTVecLayer : TDTImgLayer
        const vectorMap = new ol.Map({
            target: mapId,
            layers: [
                layer,
                TDTCvaLayer
            ],
            view: new ol.View({
                center: [11421771, 4288300],
                zoom: 5,
                worldsWrap: true,
                minZoom: 1,
                maxZoom: 20,
                projection: projection
            })
        })
        return vectorMap
    }

    // 分屏地图数组
    let maps = []
    /**
     * 默认二分屏
     */
    const mapsContainer = document.getElementById("map-main")
    for (let i = 0; i < 2; i++) {
        // 创建地图元素
        const mapId = 'two-' + i
        const mapTarget = document.createElement('div')
        mapTarget.className = 'split-map'
        mapTarget.style.height = "100%"
        mapTarget.style.width = "50%"
        mapTarget.setAttribute('id', mapId)
        mapsContainer.appendChild(mapTarget)
        const map = createMap(mapId)
        maps.push(map)
    }
    mapZoomAndMove()
    /**
     * 地图分屏操作
     */
    function mapSplit() {
        // 二分屏
        document.getElementById('two').addEventListener('click', evt => {
            toogleAciveClass(evt.target)
            maps = []
            removeChildMap(mapsContainer)
            for (let i = 0; i < 2; i++) {
                // 创建地图元素
                const mapId = 'two-' + i
                const mapTarget = document.createElement('div')
                mapTarget.className = 'split-map'
                mapTarget.style.height = "100%"
                mapTarget.style.width = "50%"
                mapTarget.setAttribute('id', mapId)
                mapsContainer.appendChild(mapTarget)
                const map = createMap(mapId)
                maps.push(map)
            }
            mapZoomAndMove()
        })

        // 四分屏
        document.getElementById('four').addEventListener('click', evt => {
            toogleAciveClass(evt.target)
            maps = []
            removeChildMap(mapsContainer)
            for (let i = 0; i < 4; i++) {
                // 创建地图元素
                const mapId = 'four-' + i
                const mapTarget = document.createElement('div')
                mapTarget.className = 'split-map'
                mapTarget.style.height = "50%"
                mapTarget.style.width = "50%"
                mapTarget.setAttribute('id', mapId)
                mapsContainer.appendChild(mapTarget)
                const map = createMap(mapId)
                maps.push(map)
            }
            mapZoomAndMove()
        })
        // 六分屏
        document.getElementById('six').addEventListener('click', evt => {
            toogleAciveClass(evt.target)
            maps = []
            removeChildMap(mapsContainer)
            for (let i = 0; i < 6; i++) {
                // 创建地图元素
                const mapId = 'six-' + i
                const mapTarget = document.createElement('div')
                mapTarget.className = 'split-map'
                mapTarget.style.height = 100 / 3 + "%"
                mapTarget.style.width = '50%'
                mapTarget.setAttribute('id', mapId)
                mapsContainer.appendChild(mapTarget)
                const map = createMap(mapId)
                maps.push(map)
            }
            mapZoomAndMove()
        })
        // 八分屏
        document.getElementById('eight').addEventListener('click', evt => {
            toogleAciveClass(evt.target)
            maps = []
            removeChildMap(mapsContainer)
            for (let i = 0; i < 8; i++) {
                // 创建地图元素
                const mapId = 'eight-' + i
                const mapTarget = document.createElement('div')
                mapTarget.className = 'split-map'
                mapTarget.style.height = "25%"
                mapTarget.style.width = '50%'
                mapTarget.setAttribute('id', mapId)
                mapsContainer.appendChild(mapTarget)
                const map = createMap(mapId)
                maps.push(map)
            }
            mapZoomAndMove()
        })
    }
    mapSplit()
    // 移除子元素
    function removeChildMap(mapsContainer) {
        const childNodes = Array.from(mapsContainer.children)
        if (childNodes.length) {
            childNodes.forEach(element => {
                mapsContainer.removeChild(element)
            });
        }
    }
    // 地图联动
    function mapZoomAndMove() {
        maps.forEach(map => {
            maps.forEach(targetMap => {
                map.setView(targetMap.getView())
            })
        })
    }
    /**
     * 切换激活样式
     */
    function toogleAciveClass(target) {
        // 判断split-div子元素是否激活,并切换激活样式
        const splitsEle = document.querySelector('.split-div')
        for (let element of splitsEle.children) {
            if (target === element) {
                target.classList.add('active')
            } else {
                element.classList.remove('active')
            }
        }

    }
</script>

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

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2407490.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…