Openlayers 教程 - feature(图形要素)三种悬浮事件(移入移出)以及适用范围

news2024/12/26 22:36:58

Openlayers 教程 - feature(图形要素)两种悬浮事件以及使用范围

    • 核心代码
    • 完整代码:
    • 在线示例

之前介绍了 Openlayers 的点击事件,这次介绍一下悬浮事件

悬浮事件和点击事件还是有区别的:一般点击事件是一次事件,而悬浮事件往往是两次事件。

比如,点击改变颜色,想要改回来,再执行一遍即可;

而悬浮事件改变颜色,往往需要鼠标移入改变颜色,移出还原颜色

本文介绍了图形要素(Feature)的三种悬浮事件实现方式:

  1. 开启地图事件,通过传递给图形要素(Feature)的方式实现。
  2. 开启地图事件,判断当前图形要素(Feature)的方式实现。
  3. 通过图形要素(Feature)选中交互实现。

三种方式可根据实际需求来选择使用,详情见代码注释。

本文包括核心代码、完整代码以及在线示例。


核心代码

三种注册悬浮事件方式:


// 注册地图悬浮事件
function registerMapEvent() {
    map.on('pointermove', function (event) {
        map.forEachFeatureAtPixel(event.pixel, function (feature) {
            // 为移动到的 feature 发送自定义的 mousemove 消息
            try {
                feature && feature.set('position', map.getCoordinateFromPixel(event.pixel));
            } catch (e) {
                console.error(e);
            }
            feature.dispatchEvent && feature.dispatchEvent({type: 'mousemove', event});
        });
    });
}

// 单击事件对象
const func1 = function (e) {
    console.log('触发悬浮事件: ', e.target)
    feature1.setStyle(hoverStyle1)
}

// 记录对象,用于清除事件
feature1.set('eventFunction', func1);

feature1.on('mousemove', func1)
        
//分割线 =================================================================

// 开启地图悬浮事件
// 可以记录移入和移出事件
function featureMapHover() {

    const feature = features[1]

    // 用来记录选中的图形要素
    let selected = null;
    // 用来关闭悬浮离开状态
    let unselect = false;

    function mapHoverFunc(e) {

        if (selected !== null) {
            selected = null;
        }

        map.forEachFeatureAtPixel(e.pixel, function (f) {
            // 这里可以判断某个或者某些图形要素组
            if (f === feature) {
                selected = f;
                return true;
            } else {
                return false;
            }

        });

        // 鼠标移入
        if (selected) {
            console.log('悬浮中', e);
            unselect = false;
            feature.setStyle(hoverStyle2)
            //鼠标移出
        } else {
            if (!unselect) {
                console.log('已移开');
                unselect = true;
                feature.setStyle(undefined)
            }
        }
    }

    map.set('eventFunction', mapHoverFunc);
    map.on('pointermove', mapHoverFunc);
}

//分割线 =================================================================

// 选中交互来实现悬浮事件
function featureSelectHover() {

    // 创建一个选择交互实例
    const selectInteraction = new ol.interaction.Select({
        // 设置触发选择的事件条件为点击事件
        condition: ol.events.condition.pointerMove,
        // 设置图层
        layers: [layerSelect],
    });

    map.set('selectInteraction',selectInteraction);

    selectInteraction.on('select',function (e){
        console.log('e.selected',e.selected)
        if(e.selected.length>0){
            console.log('选中:',e.selected)
        }else{
            console.log('取消选中!')
        }
    });

    // 将选择交互添加到地图实例中
    map.addInteraction(selectInteraction);
}



完整代码:


<html lang="en">
<head>
    <meta charSet="utf-8">
    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
    <link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css">
    <style>
        /* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */
        .map {
            height: 400px;
            width: 100%;
            float: left;
        }
    </style>
    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
    <script src="http://openlayers.vip/examples/resources/ol.js"></script>
    <script src="./turf.min.js"></script>
    <script src="./tiandituLayers.js"></script>
    <title>OpenLayers example</title>
    <script>
        var _hmt = _hmt || [];
        (function () {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?f80a36f14f8a73bb0f82e0fdbcee3058";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
        })();
    </script>
</head>
<body>
<h2>OpenLayers feature hover</h2>
<!--地图容器,需要指定 id -->
<div id="map" class="map"></div>
<br/>
<br/>
<script type="text/javascript">

    var map = new ol.Map({
        // 地图容器
        target: 'map',
        // 地图图层,比如底图、矢量图等
        layers: [
            getIMG_CLayer(),
            getIBO_CLayer(),
            getCIA_CLayer(),
        ],
        // 地图视野
        view: new ol.View({
            projection: "EPSG:4326",
            // 定位
            center: [115.67724700667199, 37.73879478106912],
            // 缩放
            zoom: 6,
            maxZoom: 18,
            minZoom: 1,
        })
    });

    // 注册地图悬浮事件
    function registerMapEvent() {
        map.on('pointermove', function (event) {
            map.forEachFeatureAtPixel(event.pixel, function (feature) {
                // 为移动到的 feature 发送自定义的 mousemove 消息
                try {
                    feature && feature.set('position', map.getCoordinateFromPixel(event.pixel));
                } catch (e) {
                    console.error(e);
                }
                feature.dispatchEvent && feature.dispatchEvent({type: 'mousemove', event});
            });
        });
    }

    registerMapEvent();

    // 默认样式
    var defaultStyle = new ol.style.Style({
        //边框样式
        stroke: new ol.style.Stroke({
            color: 'red',
            width: 2,
        }),
        //填充样式
        fill: new ol.style.Fill({
            color: 'rgba(0, 0, 255, 0.3)',
        }),
        image: new ol.style.Circle({
            radius: 5,
            fill: new ol.style.Fill({
                color: 'white',
            })
        })
    })

    var hoverStyle1 = new ol.style.Style({
        //边框样式
        stroke: new ol.style.Stroke({
            color: '#00ff00',
            width: 2,
        }),
        //填充样式
        fill: new ol.style.Fill({
            color: 'rgba(0, 0, 255, 0.3)',
        }),
    })

    var hoverStyle2 = new ol.style.Style({
        //边框样式
        stroke: new ol.style.Stroke({
            color: '#00ffff',
            width: 2,
        }),
        //填充样式
        fill: new ol.style.Fill({
            color: 'rgba(0, 0, 255, 0.3)',
        }),
        image: new ol.style.Circle({
            radius: 5,
            fill: new ol.style.Fill({
                color: 'white',
            })
        })
    })

    // 初始化图层
    var layer = initVectorLayer();
    // 选中图形要素图层
    var layerSelect = initVectorLayer();
    // 点线面数组
    var features = [];

    // 传递的方式开启悬浮的图形要素
    let polygon1 = "POLYGON((112.80630306271966 46.27140545436643,116.23403743771966 44.33781170436643,117.81606868771966 40.29484295436643,117.90395931271966 38.36124920436643,117.81606868771966 35.02140545436643,116.14614681271966 32.38468670436643,113.50942806271966 33.26359295436643,111.75161556271966 34.58195232936643,110.60903743771966 35.46085857936643,113.28970150021968 36.03214764186642,111.35610775021968 36.33976482936642,110.91665462521968 36.91105389186642,111.22427181271968 37.52628826686642,112.10317806271968 37.30656170436642,112.41079525021968 37.78996014186642,112.32290462521968 38.36124920436642,111.44399837521968 38.66886639186642,110.52114681271968 39.10831951686642,110.38931087521968 39.81144451686642,111.09243587521968 40.07511639186642,112.19106868771968 40.38273357936642,112.49868587521968 41.04191326686642,111.88345150021968 41.21769451686642,111.26821712521968 40.86613201686642,110.43325618771968 40.91007732936642,110.65298275021968 41.39347576686642,110.47720150021968 42.66788982936642,111.79556087521968 42.75578045436642,110.38931087521968 43.19523357936642,110.56509212521968 44.24992107936642,111.44399837521968 43.76652264186642,111.79556087521968 44.16203045436642,111.09243587521968 44.60148357936642,111.22427181271968 45.30460857936642,112.10317806271968 44.95304607936642,112.67446712521968 45.26066326686642,111.75161556271968 45.78800701686642,111.88345150021968 46.40324139186642,112.14712337521968 47.94132732936642,112.45474056271968 47.15031170436642,113.99282650021968 47.28214764186642,113.28970150021968 46.79874920436642,114.95962337521968 46.71085857936642,112.80630306271966 46.27140545436643))";
    // 移入和移出事件的图形要素
    let polygon2 = "POLYGON((123.94676492355833 44.03121337817592,118.40965554855833 38.23043212817592,121.66160867355833 32.82515869067592,129.30809304855833 33.39644775317592,129.92332742355833 39.46090087817592,123.94676492355833 44.03121337817592))";
    // 选中方式的悬浮的图形要素
    let polygon3 = "POLYGON((107.96587424038064 27.434398296739595,125.98345236538064 30.554515484239595,126.68657736538064 24.446117046739595,110.16313986538064 17.942210796739595,107.96587424038064 27.434398296739595))";

    // 添加点线面
    function addFeatures() {

        // 这里处理一下,可以自由传图形要素 start===================================================
        layer.getSource().clear();
        layerSelect.getSource().clear();

        features = [];

        const feature1 = getFeatureByWKT(polygon1);
        const feature2 = getFeatureByWKT(polygon2);
        const feature3 = getFeatureByWKT(polygon3);

        // 单击事件对象
        const func1 = function (e) {
            console.log('触发悬浮事件: ', e.target)
            feature1.setStyle(hoverStyle1)
        }

        // 记录对象,用于清除事件
        feature1.set('eventFunction', func1);

        feature1.on('mousemove', func1)

        features.push(...[feature1, feature2]);

        layer.getSource().addFeatures([feature1, feature2]);
        layerSelect.getSource().addFeatures([feature3]);

        map.getView().fit([93.64037006658276, 10.72265625,128.53294819158273, 51.181893294147805], {
            duration: 1,//动画的持续时间,
            callback: null,
        });
    }

    addFeatures();

    /**
     * @todo 矢量图层
     * @returns {VectorLayer}
     * @constructor
     */
    function initVectorLayer() {
        //实例化一个矢量图层Vector作为绘制层
        let source = new ol.source.Vector();
        //创建一个图层
        let customVectorLayer = new ol.layer.Vector({
            source: source,
            zIndex: 2,
            //设置样式
            style: defaultStyle,
        });
        //将绘制层添加到地图容器中
        map.addLayer(customVectorLayer);

        return customVectorLayer;
    }

    /**
     * @todo wkt格式数据转化成图形对象
     * @param {string} wkt   "POINT(112.7197265625,39.18164062499999)" 格式数据
     * @param {string|Projection} sourceCode 源投影坐标系
     * @param {string|Projection} targetCode 目标投影坐标系
     * @returns {Feature}
     */
    function getFeatureByWKT(wkt, sourceCode, targetCode) {
        try {
            let view = map.getView();
            if (!wkt) {
                return null;
            }
            let format = new ol.format.WKT();

            let feature;

            feature = format.readFeature(wkt, {
                featureProjection: targetCode || view.getProjection(),
                dataProjection: sourceCode || view.getProjection(),
            });

            return feature;
        } catch (e) {
            console.log(e);
            return null;
        }
    }

    // 开启地图悬浮事件
    // 可以记录移入和移出事件
    function featureMapHover() {

        const feature = features[1]

        // 用来记录选中的图形要素
        let selected = null;
        // 用来关闭悬浮离开状态
        let unselect = false;

        function mapHoverFunc(e) {

            if (selected !== null) {
                selected = null;
            }

            map.forEachFeatureAtPixel(e.pixel, function (f) {
                // 这里可以判断某个或者某些图形要素组
                if (f === feature) {
                    selected = f;
                    return true;
                } else {
                    return false;
                }

            });

            // 鼠标移入
            if (selected) {
                console.log('悬浮中', e);
                unselect = false;
                feature.setStyle(hoverStyle2)
                //鼠标移出
            } else {
                if (!unselect) {
                    console.log('已移开');
                    unselect = true;
                    feature.setStyle(undefined)
                }
            }
        }

        map.set('eventFunction', mapHoverFunc);
        map.on('pointermove', mapHoverFunc);
    }

    // 选中交互来实现悬浮事件
    function featureSelectHover() {

        // 创建一个选择交互实例
        const selectInteraction = new ol.interaction.Select({
            // 设置触发选择的事件条件为点击事件
            condition: ol.events.condition.pointerMove,
            // 设置图层
            layers: [layerSelect],
        });

        map.set('selectInteraction',selectInteraction);

        selectInteraction.on('select',function (e){
            console.log('e.selected',e.selected)
            if(e.selected.length>0){
                console.log('选中:',e.selected)
            }else{
                console.log('取消选中!')
            }
        });

        // 将选择交互添加到地图实例中
        map.addInteraction(selectInteraction);
    }

    featureMapHover();
    featureSelectHover();

    // 清空事件
    function clearFunc() {

        const feature = features[0];
        const func = feature.get('eventFunction');
        feature.un('mousemove', func);
        feature.setStyle(undefined)

        const funcMap = map.get('eventFunction');
        map.un('pointermove', funcMap);

        const selectInteraction = map.get('selectInteraction');
        map.removeInteraction(selectInteraction);
    }

</script>
<h4>左一为传递方式实现悬浮事件,契合面相对象思想,但是不能记录移出事件!</h4>
<h4>左二为地图方式实现悬浮事件,整个地图开启悬浮事件,可以记录移入移出事件!</h4>
<h4>下侧为选中交互实现悬浮事件,契合面向对象思想,可以绑定图层,不能记录移出事件!</h4>
<button id="clearFunc" onClick="clearFunc()">关闭所有事件</button>
</body>
</html>


在线示例

在线示例:Openlayers 教程 - feature(图形要素)三种悬浮事件(移入移出)以及适用范围

在这里插入图片描述


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

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

相关文章

element plus表格合并行

/*** 合并相同数据&#xff0c;导出合并列所需的方法(只适合el-table)*/ export function getRowSpanMethod(data, rowSpanArray) {/*** 要合并列的数据*/const rowSpanNumObject {};//初始化 rowSpanNumObjectrowSpanArray.map((item) > {rowSpanNumObject[item] new Arr…

Informatica使用操作流程--聚合、表达式转换、查找、排序组件的使用 案例3

一、需求&#xff1a; 将oracle数据库的scott用户源表items 直抽至 EDW层 EDW_items。数据存储到oracle的edw01用户下 数据抽取至EDW层做聚合转换 求各供应商 min(price),avg(price),max(price),sum(price), 2*avg(price) 根据供应商id去供应商表查找供应商名称 查验…

【Java核心知识】idea项目编译错误排查思路

文章目录 idea项目编译错误排查思路一个项目是如何运行的项目编译报错时排查常见思路 idea项目编译错误排查思路 一个项目是如何运行的 在开始之前&#xff0c;我们需要知道idea对一个项目是如何维护和运行的&#xff1f;idea会把用户自定义配置放在.idea文件夹中&#xff0c…

LeetCode:2. 两数之和

这个解题思路来自代码随想录&#xff1a;代码随想录 (programmercarl.com) class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {std::unordered_map <int,int> map;for(int i 0; i < nums.size(); i) {// 遍历当前元素&am…

ME21N 采购订单屏幕增强

1、业务需求 采购订单行项目新增“图号”和“价格类型”字段。其中图号只查询底表展示&#xff0c;不做修改&#xff1b;价格类型做下拉框&#xff1b; 2、增强实现 增强标准表EKPO结构CI_EKPODB。抬头增加字段则修改EKKO结构CI_EKKODB 增强点CMOD&#xff1a;MM06E005 出口…

Redis7--基础篇1(概述,安装、卸载及配置)

1. Redis概述 1.1 什么是Redis Redis&#xff1a;REmote Dictionary Server&#xff08;远程字典服务器&#xff09; Remote Dictionary Server(远程字典服务)是完全开源的&#xff0c;使用ANSIC语言编写遵守BSD协议&#xff0c;是一个高性能的Key-Value数据库提供了丰富的数…

运营岗位需要一个内部知识库吗?

在运营岗位中&#xff0c;一个内部知识库是非常有价值的。运营岗位涉及到许多不同的任务和责任&#xff0c;需要掌握大量的专业知识和最佳实践。一个内部知识库可以帮助运营团队更好地管理和共享这些知识&#xff0c;提高工作效率和质量。 内部知识库对运营岗位的价值和应用场…

Eclipse安装FTP连接工具

查看Eclipse版本 Eclipse 安装串口终端工具_哭哭啼的博客-CSDN博客 安装 选择您的版本的插件发布站点&#xff1a; 在过滤器字段中,键入"remote".选择Mobile and Device Development&#xff0c;并选择 点击"下一步",然后接受条款.它现在应该下载并安装.…

SAP物料主数据归档详解(物理删除)

平时在操作系统过程中经常会不小心创建出很多无用的物料主数据&#xff0c;但是系统只能通过MM06打上删除标记&#xff0c;但是物料最终在系统中还是可以查询到的。 相信各位大顾问们肯定被用户问过&#xff0c;有没有办法把物料或者是业务数据从物理上删除。顾问们的回答肯定…

【算法】Java-使用数组模拟单向链表,双向链表

目录 试题1&#xff1a;实现一个单链表&#xff0c;并实现以下功能&#xff1a; 试题2&#xff1a;实现一个双链表&#xff0c;并实现以下功能 思路总结&#xff1a; 什么情况下可能涉及到用数组实现链表呢&#xff1f; 在学习时了解到了可以用数组模拟链表&#xff0c;使其…

【LInux编译器gcc/g++】gcc使用方法和动静态库相关概念

目录 一.前言 二.源代码的翻译环境 三.gcc相关指令 四.动静态库 1.什么是库&#xff1f; 2.库的命名 3.库的链接方式 4.动静态链接的优缺点 5.小结 一.前言 在Windows系统上我们常用VisualStudio来进行C/C开发&#xff0c;VS并不是一款单一的软件&#xff0c;而是集成…

UI设计模式是什么?有哪些常用的?

UI设计模式是针对常见的用户界面问题提出的解决方案。当解决方案得到验证时&#xff0c;它经常被使用&#xff0c;最终演变成可重复使用的设计模式。 设计师可以根据不同的网站功能类型选择使用相应的网站UI设计模式&#xff0c;从而创建一致高效的网站UI界面。 本文推荐8种常…

选择排序——直接选择排序

直接选择排序&#xff1a;&#xff08;以重复选择的思想为基础进行排序&#xff09; 1、简述 顾名思义就是选出一个数&#xff0c;再去抉择放哪里去。 设记录R1&#xff0c;R2…&#xff0c;Rn&#xff0c;对i1&#xff0c;2&#xff0c;…&#xff0c;n-1&#xff0c;重复下…

【MMDetection】bug记录

bug1&#xff1a; if env_cfg.get(cudnn_benchmark): AttributeError: NoneType object has no attribute get 解决办法&#xff1a; 配置文件缺少了env_cfg信息&#xff0c;需要在config文件中添加&#xff0c;如以下内容&#xff1a; env_cfg dict(cudnn_benchmarkFalse…

Java 使用 EMQX 实现物联网 MQTT 通信

一、介绍 1、MQTT MQTT(Message Queuing Telemetry Transport, 消息队列遥测传输协议)&#xff0c;是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议&#xff0c;该协议构建于TCP/IP协议上&#xff0c;由IBM在1999年发布。MQTT最大优点在于&#xff…

Netty核心原理:一、基础入门-01:初入JavaIO之门BIO、NIO、AIO实战练习

文章目录 一、前言介绍1.1 BIO&#xff1a;同步阻塞I/O模式1.2 NIO&#xff1a;同步非阻塞I/O模式1.3 AIO&#xff1a;异步非阻塞I/O模式 二、代码实现2.1 工程结构2.2 BIO&#xff1a;同步阻塞I/O实现2.2.1 BIO处理器2.2.2 BIO适配器2.2.3 BIO客户端处理器2.2.4 BIO客户端2.2.…

计算机网络第五章——传输层(上)

早知如此绊人心&#xff0c;何如当初莫相识 文章目录 前言 前言 虽然说是手机和手机之间的通信但是其实是手机之间的进程和进程之间的通信&#xff0c;所以这一章主要是研究进程之间通信的问题&#xff0c;在计算机网络中有一个重要的问题&#xff0c;在进行数据通信和资源共享…

【分享】golang windows 运行报错 undefined: syscall.SIGUSR1

在跟着煎鱼大佬学习 Golang-gin的时候&#xff0c;"在优雅的重启服务篇" ,为了gin服务的热更新&#xff0c;采用了 endlessfresh的方案&#xff0c;安装endless后无法在windows本地调试,然后报错。 (优雅的重启服务-地鼠文档优雅的重启服务-我不怎么喜欢左写写&#…

linux内核模块编译方法之模块编程详解

文章目录 一、模块传参二、模块依赖三、内核空间和用户空间四、执行流五、模块编程与应用编程的比较六、内核接口头文件查询总结 本期和大家主要分享的是驱动开发内核编译过程中对于模块是如何设计的&#xff0c;进行了详细的分享&#xff0c;从模块传参、模块依赖一直到内核空…

楼顶空地适合建造气膜体育馆吗?

众所周知&#xff0c;传统建筑的荷载太大&#xff0c;出于安全考虑&#xff0c;是不适合继续在楼顶加盖传统结构体育馆的&#xff0c;但是&#xff0c;气膜体育馆作为一种装配式建筑&#xff0c;它是可以在城市高空上建造一个轻盈又新颖独特的全天候气膜馆。 气膜体育馆作为一种…