Openlayers3 - 使用捏合手势在触摸设备上进行分数缩放?

时间:2016-11-30 07:03:32

标签: javascript touch zoom openlayers-3 fractions

Openlayers3可以通过在setZoom()中指定小数来以编程方式显示小数缩放级别的地图。

但是,我希望我的用户能够在移动触摸驱动设备(即智能手机)上获得分数缩放级别。当手指从屏幕上移开时,通过跳到最接近的整个缩放级别来缩小或缩小缩放。

触摸/移动用户如何让Openlayers3保持用户所捏的精确范围(分数缩放级别)?

我可以添加到我的Openlayers3地图或视图的javascript中,以使其按需运行吗?

特别是,我注意到Openlayers3有一个ol.interaction.PinchZoom()类(https://openlayers.org/en/latest/apidoc/ol.interaction.PinchZoom.html)。这是ol.interaction.Pointer的子类,其handleUpEventhandleEvent(应该是函数)。所以从理论上讲,我应该能够替换handleUpEvent中的PinchZoom或者将默认的PinchZoom交互替换为具有自定义事件处理函数的交互。但是使用这两种方法,我无法调用我的新handleUpEvent函数。

(在PinchZoom搜索OL代码的同时,我发现如果一根手指在另一根手指之前从触摸屏抬起,默认PinchZoom就能做到我想要的,但我仍然想要当两个手指同时抬起时,让它工作。)

这是我到目前为止所尝试的......

第一次尝试 - 这只是尝试用自定义PinchZoom替换标准handleUpEvent function handleUpEvent(evt) { console.log("Up event handler"); return true; // Stop drag } map = new ol.Map({ layers: [], target: 'map', controls: controls, interactions: [new ol.interaction.PinchZoom({handleEvent: handleUpEvent})], view: new ol.View({projection: projCode}) }); ,并将其设置为地图的唯一互动。但是,永远不会调用事件函数(从不记录任何内容)。

PinchZoom

SECOND ATTEMPT - 此尝试基于用于创建标准targetPointers互动的实际OL代码。在这种情况下,我的所有事件处理函数都被调用,触摸次数(targetPointers)始终为零(记录时)。我不是javascript大师,但我怀疑这是因为ol.js中的符号与ol-debug.js中的符号不​​同,我正在以此为基础。事实上,我必须自己声明function handleDownEvent(mapBrowserEvent) { console.log("DOWN event handler"); this.anchor_ = null; this.lastDistance_ = undefined; this.lastScaleDelta_ = 1; mapBrowserEvent.map.render(); return true; // Start drag } function handleDragEvent(mapBrowserEvent) { if ( this.targetPointers.length < 2 ) { console.log("DRAG event ignored - touches ", this.targetPointers.length); } else { console.log("DRAG event handled"); var scaleDelta = 1.0; var touch0 = this.targetPointers[0]; var touch1 = this.targetPointers[1]; var dx = touch0.clientX - touch1.clientX; var dy = touch0.clientY - touch1.clientY; // distance between touches var distance = Math.sqrt(dx * dx + dy * dy); if (this.lastDistance_ !== undefined) { scaleDelta = this.lastDistance_ / distance; } this.lastDistance_ = distance; if (scaleDelta != 1.0) { this.lastScaleDelta_ = scaleDelta; } var map = mapBrowserEvent.map; var view = map.getView(); var resolution = view.getResolution(); // scale anchor point. var viewportPosition = map.getViewport().getBoundingClientRect(); var centroid = ol.interaction.Pointer.centroid(this.targetPointers); centroid[0] -= viewportPosition.left; centroid[1] -= viewportPosition.top; this.anchor_ = map.getCoordinateFromPixel(centroid); // scale, bypass the resolution constraint map.render(); ol.interaction.Interaction.zoomWithoutConstraints( map, view, resolution * scaleDelta, this.anchor_); } } function handleUpEvent(mapBrowserEvent) { console.log("UP event handler"); return true; // Stop drag } var pinchZoom = new ol.interaction.Pointer({ handleDownEvent: handleDownEvent, handleDragEvent: handleDragEvent, handleUpEvent: handleUpEvent }); pinchZoom.targetPointers = []; map = new ol.Map({ interactions: ol.interaction.defaults().extend([pinchZoom]), layers: [ new ol.layer.Tile({ source: new ol.source.TileJSON({url: 'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure'}) }) ], target: 'map', view: new ol.View({center: [0, 0], zoom: 3}) }); 甚至让它运行,即使它已经由OL本身声明(但可能在非调试版本中使用不同的符号名称)。

plt.xticks

1 个答案:

答案 0 :(得分:0)

您尝试的问题:

首次尝试

handleEvent的选项ol.interaction.PinchZoom不存在。这就是你的回调没有被执行的原因。

第二次尝试

正如您已经注意到的那样,您尝试使用openlayers内部。这可能适用于调试版本,但在版本构建中不起作用,因为名称不同于。

解决方案

添加选项以在openlayers来源的夹点缩放结束处保持小数分辨率。

问题:https://github.com/openlayers/ol3/issues/6223

拉取请求:https://github.com/openlayers/ol3/issues/6224

默认情况下,捏缩放将保持用户选择的分数缩放级别..从OpenLayers 3.20开始

早先的想法:

作为示例,我将选项keepFractionalZoomLevel添加到ol.interaction.PinchZoomhttps://github.com/aAXEe/ol3/commit/7639cb20d17858492652896bcd4a6ff7992a9bb0

请参阅此小提琴,了解一个工作示例:https://jsfiddle.net/wm78prro/5/

注意:小提琴使用自定义openlayers构建:https://github.com/aAXEe/ol3/pull/1
部署网址为:https://deploy-preview-1--pump-attendant-rhinoceros-42285.netlify.com/ol-debug.js

此示例是否符合您的要求?
由于这可能对其他人有用,我们可以尝试将其集成到openlayers中。