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



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

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

触摸/移动用户如何让 Openlayers3 保持在用户捏合到的确切程度(分数缩放级别)?

我可以在 Openlayers3 地图或视图的 JavaScript 中添加一些东西来使其按预期工作吗?

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

(在拖曳 OL 代码PinchZoom时,我发现如果一根手指先从触摸屏抬起另一根手指,默认PinchZoom会做我想要的,但我仍然想在同时抬起两根手指时让它工作。

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

第一次尝试- 这只是尝试将标准PinchZoomhandleUpEvent替换为自定义,并将其设置为地图的唯一交互。 但是,永远不会调用事件函数(从不记录任何内容)。

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交互的实际 OL 代码。 在这种情况下,我所有的事件处理程序函数都会被调用,触摸次数(targetPointers)始终为零(记录)。 我不是javascript大师,但我怀疑这是因为ol.js中的符号与ol-debug中的符号不同.js而ol-debug是基于这一点。 事实上,我必须自己声明targetPointers才能运行它,即使它已经由 OL 本身声明(但大概在非调试版本中使用了不同的符号名称)。

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.interaction.PinchZoom的选项handleEvent不存在。这就是不执行回调的原因。

第二次尝试

正如您已经指出的,您尝试使用开放层内部。这可能适用于调试版本,但在发布版本中不起作用,因为名称不同。

溶液

添加选项以在打开图层源的收缩缩放端保持分数分辨率。

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

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

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


一个早期的想法:

例如,我将选项keepFractionalZoomLevel添加到ol.interaction.PinchZoom:https://github.com/aAXEe/ol3/commit/7639cb20d17858492652896bcd4a6ff7992a9bb0

有关工作示例,请参阅此小提琴:https://jsfiddle.net/wm78prro/5/

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

此示例是否按您的需要运行?
由于这可能对其他人有用,我们可以尝试将其集成到开放层中。

最新更新