三十、openlayers官网示例解析Double click, Drag and Zoom——第二次点击鼠标拖拽缩放地图效果、取消地图双击放大事件

 这篇展示了如何在地图上添加第二次按下鼠标移动鼠标实现拖拽缩放地图效果。

官网demo地址:

Double click, Drag and Zoom

官网介绍文字的翻译如下:

示例比较简单,直接贴代码:

 const map = new Map({
        //添加第二次点击拖拽缩放地图
        interactions: defaultInteractions().extend([new DblClickDragZoom()]),
        layers: [
          new Tile({
            source: new XYZ({
              url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
            }),
          }),
        ],
        target: "map",
        view: new View({
          center: [0, 0],
          zoom: 2
<think>我们正在使用OpenLayers,需要在执行自定义鼠标事件(如绘制、测量)时,临时禁止地图的默认拖拽双击放大行为,并在事件结束后恢复这些交互功能。 根据引用[2]中的内容,我们知道OpenLayers的交互行为(如拖拽DragPan和双击缩放DoubleClickZoom)可以通过交互模块控制。我们可以通过移除这些交互来禁止默认行为,然后在需要时重新添加。 步骤如下: 1. 获取地图当前的所有交互,并从中移除我们想要禁止的交互(如DragPan和DoubleClickZoom)。 2. 执行自定义鼠标事件(比如绘制、测量等)。 3. 在自定义事件结束后,将之前移除的交互重新添加到地图上。 但是,我们需要注意: - 如何识别和存储这些交互?可以在初始化地图后,保存这些交互的引用。 - 为了避免重复创建,我们可以在初始化地图时保存默认的交互,然后在需要时移除和添加。 另外,引用[2]中提到了在Vue 3中如何控制交互,其中有一个关键点:使用`defaults`函数可以获取默认的交互集合,然后我们可以从中提取出DragPan和DoubleClickZoom交互,并分别控制。 具体实现: 步骤1:在初始化地图时,保存默认的交互对象(特别是拖拽双击缩放交互)的引用。 步骤2:当开始执行自定义鼠标事件时,从地图中移除这些交互。 步骤3:在自定义事件结束后(比如双击结束绘制,或者点击了结束按钮),将之前移除的交互重新添加到地图中。 示例代码: 首先,在创建地图时,我们可以获取默认的交互,并保存我们需要控制的交互: ```javascript import Map from 'ol/Map'; import View from 'ol/View'; import { defaults as defaultInteractions, DragPan, DoubleClickZoom } from 'ol/interaction'; import TileLayer from 'ol/layer/Tile'; import OSM from 'ol/source/OSM'; class CustomMap { constructor() { // 创建地图时,使用默认的交互集合 this.map = new Map({ target: 'map', layers: [new TileLayer({ source: new OSM() })], view: new View({ center: [0, 0], zoom: 2 }), interactions: defaultInteractions() // 使用默认交互 }); // 从地图的交互集合中获取拖拽双击缩放交互 this.dragPanInteraction = this.map.getInteractions().getArray().find(interaction => interaction instanceof DragPan); this.doubleClickZoomInteraction = this.map.getInteractions().getArray().find(interaction => interaction instanceof DoubleClickZoom); } // 开始自定义事件时,移除默认交互 startCustomEvent() { if (this.dragPanInteraction) { this.map.removeInteraction(this.dragPanInteraction); } if (this.doubleClickZoomInteraction) { this.map.removeInteraction(this.doubleClickZoomInteraction); } // 然后添加自定义事件监听,例如绘制图形等 // ... 添加自定义事件处理器 } // 结束自定义事件时,恢复默认交互 endCustomEvent() { // 移除自定义事件监听 // ... // 恢复交互 if (this.dragPanInteraction) { this.map.addInteraction(this.dragPanInteraction); } if (this.doubleClickZoomInteraction) { this.map.addInteraction(this.doubleClickZoomInteraction); } } } ``` 另一种方法:在创建地图时不添加默认交互,而是自己管理所有交互。但这样比较繁琐,通常我们只需要临时移除两个交互。 注意:在自定义事件过程中,可能还需要临时添加一些交互(比如绘制图形的交互),这些交互在移除默认交互后单独添加。 根据引用[3]中的问题127:“如何阻止地图默认的双击放大行为?”,我们可以知道,通过移除DoubleClickZoom交互就可以阻止。同样,问题128提到如何启用拖拽,也是通过DragPan交互控制。 因此,上面的方法有效。 引用[1]中的示例是通过jQuery监听按钮的mousedown事件,然后在其中监听鼠标移动,并在双击时结束。我们可以参考这个事件触发流程,但采用OpenLayers的方式。 在OpenLayers中,我们可以使用`map.on('click', ...)`等方式监听事件,并在事件处理函数中执行自定义逻辑。同时,在开始监听前移除默认交互,在结束时恢复。 示例:实现一个简单的绘制点并结束的功能 ```javascript // 在startCustomEvent方法中 startCustomEvent() { // 移除默认交互 this.removeDefaultInteractions(); // 添加点击事件监听 this.map.on('click', this.handleClick); // 添加双击结束事件 this.map.on('dblclick', this.handleEnd); } handleClick = (event) => { // 处理点击,比如添加点 console.log('添加点', event.coordinate); } handleEnd = () => { // 结束自定义事件 this.map.un('click', this.handleClick); this.map.un('dblclick', this.handleEnd); // 恢复默认交互 this.restoreDefaultInteractions(); } ``` 注意:上面的代码是简化的,实际应用中可能需要更复杂的逻辑,比如使用Draw交互等。 总结步骤: 1. 在初始化地图时保存需要控制的交互(DragPan和DoubleClickZoom)的引用。 2. 在开始自定义事件时,移除这些交互,并添加自定义事件监听。 3. 在自定义事件结束(通过双击点击按钮等方式)时,移除自定义事件监听,并恢复默认交互。 这样就能实现在执行自定义鼠标事件时禁止地图拖拽双击放大,结束后恢复的功能。 </think>在 OpenLayers 中临时禁止地图拖拽双击放大功能,并在事件结束后恢复,可通过以下方法实现: ### 解决方案步骤 1. **禁用默认交互功能** ```javascript // 获取地图所有交互对象 const interactions = map.getInteractions().getArray(); // 查找并移除拖拽双击缩放交互 let dragPan, doubleClickZoom; interactions.forEach(interaction => { if (interaction instanceof DragPan) { dragPan = interaction; } else if (interaction instanceof DoubleClickZoom) { doubleClickZoom = interaction; } }); // 临时移除交互 map.removeInteraction(dragPan); map.removeInteraction(doubleClickZoom); ``` 2. **添加自定义事件监听** ```javascript // 示例:测量工具的事件监听 let startPoint, endPoint; // 鼠标按下事件 map.on('pointerdown', (event) => { startPoint = event.coordinate; console.log('开始坐标:', startPoint); }); // 鼠标移动事件 map.on('pointermove', (event) => { if (!startPoint) return; endPoint = event.coordinate; // 实时绘制测量线(伪代码) drawMeasureLine(startPoint, endPoint); }); // 双击结束事件(引用[1]的方案) map.on('dblclick', () => { finishMeasurement(); // 结束测量 restoreInteractions(); // 恢复交互 }); ``` 3. **手动恢复交互功能** ```javascript // 恢复地图默认交互 function restoreInteractions() { if (dragPan) map.addInteraction(dragPan); if (doubleClickZoom) map.addInteraction(doubleClickZoom); console.log('地图交互功能已恢复'); } ``` 4. **备用恢复方案(按钮/超时)** ```javascript // 通过按钮恢复(引用[2]的CTRL控制思路) document.getElementById('restoreBtn').addEventListener('click', restoreInteractions); // 自动超时恢复(防止用户未完成操作) const timeoutId = setTimeout(() => { restoreInteractions(); }, 30000); // 30秒超时自动恢复 ``` ### 关键说明 1. **交互控制原理** OpenLayers 通过 `interactions` 管理所有交互行为,移除 `DragPan` 和 `DoubleClickZoom` 可禁用对应功能[^2] 2. **事件冲突处理** 使用 `pointerdown` 替代 `click` 避免与拖拽冲突,通过坐标跟踪实现连续操作 3. **性能优化** ```javascript // 添加条件判断避免高频触发 let lastRender = 0; map.on('pointermove', (event) => { if (Date.now() - lastRender < 50) return; lastRender = Date.now(); // 处理逻辑... }); ``` 4. **完整流程示例** ```javascript function startMeasurement() { // 1. 禁用交互 disableMapInteractions(); // 2. 设置事件监听 map.on('pointerdown', handleMeasureStart); map.on('pointermove', handleMeasureMove); map.on('dblclick', handleMeasureEnd); } function handleMeasureEnd() { // 3. 完成测量计算 calculateDistance(); // 4. 移除事件监听 map.un('pointerdown', handleMeasureStart); map.un('pointermove', handleMeasureMove); map.un('dblclick', handleMeasureEnd); // 5. 恢复交互功能 restoreInteractions(); } ``` ### 注意事项 1. **交互状态保存** 建议将原始交互对象存储在闭包或类属性中,确保恢复时能准确引用 2. **移动端适配** 统一使用 `pointer` 事件系列(pointerdown/pointermove)兼容触摸屏设备 3. **异常处理** ```javascript // 添加安全恢复机制 window.addEventListener('beforeunload', () => { if (!dragPan || !doubleClickZoom) restoreInteractions(); }); ``` > 此方案通过精确控制交互对象实现功能开关,避免全局禁用导致的地图卡死问题。实际坐标转换需参照项目坐标系(EPSG:4326/EPSG:3857)进行调整[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值