如何在OpenLayers 7中实现按住要素400ms后才可通过Translate移动
问题:实现按住点要素400ms后才可移动的交互效果
我需要实现这样的效果:点击地图添加点要素后,只有按住该点400ms后才能移动它。目前我在添加点要素时就为其绑定了Translate交互,但当前onPointTranslateStart监听器中的延迟仅能控制监听器内部的逻辑,无法阻止点被即时移动。我尝试通过预校验的方式在Translate操作前做判断,但OpenLayers 7中似乎不存在mousedown这类事件的旧注册方式,相关尝试代码也无法生效。
当前实现代码
let isTranslating = false; let isTranslateAccept = true; props.map.on("singleclick", onMapTouch); const onMapTouch = async (event: ol.MapBrowserEvent<any>) => { if (isTranslating) return let newFeature = new ol.Feature(new Point(event.coordinate)); let newNameID = Math.random().toString(); newFeature.set('nameID', newNameID); rulerPoint.getSource()?.addFeature(newFeature); let features = rulerPoint.getSource()!.getFeatures(); let translate = new Translate({ features: new ol.Collection([features[features.length - 1]]), condition: (mapBrowserEvent) => { if (Condition.doubleClick(mapBrowserEvent) || Condition.singleClick(mapBrowserEvent) || Condition.doubleClick(mapBrowserEvent)) return false; return true; } }); props.map.addInteraction(translate); translate.on('translatestart', onPointTranslateStart); translate.on('translateend', onPointTranslateEnd); translate.on('translating', onPointTranslating); } const onPointTranslateStart = async (event: TranslateEvent) => { isTranslateAccept = false; await setTimeout(() => { if (isTranslateAccept) { isTranslateAccept = true; return } isTranslateAccept = true isTranslating = true; //do something }, 400); }; const onPointTranslating = (event: TranslateEvent) => { if (!isTranslateAccept) return //do something }; const onPointTranslateEnd = async (event: TranslateEvent) => { if (!isTranslateAccept) { isTranslateAccept = true return } isTranslating = false; //do something isTranslateAccept = false };
尝试过的无效代码
var events = props.map.events; events.register("mousedown",map,function(e){ console.log("mousedown"); return true; },true);
解决方案
核心思路
通过自定义Translate交互的condition判断函数,结合pointerdown/pointerup事件记录按住时长,从源头控制Translate交互的触发时机——只有当按住点要素的时间≥400ms时,才允许启动移动操作。同时优化交互创建逻辑,避免为每个点单独创建Translate实例。
修改后的完整代码
import ol from 'openlayers'; let isTranslating = false; let pressStartTime: number | null = null; // 监听地图指针按下事件,记录开始时间 props.map.on('pointerdown', () => { pressStartTime = Date.now(); }); // 监听地图指针抬起事件,重置时间记录 props.map.on('pointerup', () => { pressStartTime = null; }); // 地图点击添加点要素 props.map.on("singleclick", async (event: ol.MapBrowserEvent<any>) => { if (isTranslating) return; const newFeature = new ol.Feature(new ol.geom.Point(event.coordinate)); const newNameID = Math.random().toString(); newFeature.set('nameID', newNameID); rulerPoint.getSource()?.addFeature(newFeature); }); // 全局创建一个Translate交互,作用于所有点要素 const translate = new ol.interaction.Translate({ features: rulerPoint.getSource()?.getFeaturesCollection(), condition: (mapBrowserEvent: ol.MapBrowserEvent<any>) => { // 排除双击、单击事件,避免冲突 if (ol.events.condition.doubleClick(mapBrowserEvent) || ol.events.condition.singleClick(mapBrowserEvent)) { return false; } // 判断按住时长是否达标 if (pressStartTime && (Date.now() - pressStartTime) >= 400) { return true; } return false; } }); props.map.addInteraction(translate); // 移动开始事件处理 translate.on('translatestart', () => { isTranslating = true; // 此处添加移动开始的业务逻辑 }); // 移动中事件处理 translate.on('translating', (event: ol.interaction.TranslateEvent) => { // 此处添加移动中的业务逻辑,比如实时更新坐标 }); // 移动结束事件处理 translate.on('translateend', () => { isTranslating = false; // 此处添加移动结束的业务逻辑 });
关键优化点
- 统一交互管理:不再为每个新点单独创建Translate交互,改为绑定到图层的要素集合,减少内存占用和逻辑复杂度。
- 源头控制触发:通过
condition函数直接判断是否允许启动Translate,从根本上阻止即时移动,替代原有的事件内延迟逻辑。 - 正确的事件监听:OpenLayers 7中使用
pointerdown/pointerup替代旧版的mousedown事件,兼容鼠标和触摸设备。
内容的提问来源于stack exchange,提问作者FResh Lemon
相关产品推荐
相关产品推荐

