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

标签 javascript touch zooming openlayers-3 fractions

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

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

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

是否可以向我的 Openlayers3 map 或 View 的 JavaScript 添加一些内容,以使其按预期工作?

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

(在搜索 PinchZoom 的 OL 代码时,我发现如果一根手指先于另一根手指从触摸屏上抬起,默认的 PinchZoom 就会执行我想要的操作,但我仍然希望在同时抬起两个手指时使其正常工作。)

这是我迄今为止尝试过的...

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

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 中的符号不​​同。事实上,我必须自己声明 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 不存在。这就是为什么你的回调没有被执行。

第二次尝试

正如您已经指出的,您尝试使用 openlayers 内部结构。这可能适用于调试版本,但不适用于发布版本,因为名称不同。

解决方案

添加选项以在 openlayers 源中的捏合缩放端保持分数分辨率。

问题: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

请参阅此 fiddle 的工作示例:https://jsfiddle.net/wm78prro/5/

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

这个例子的行为符合你的要求吗?
由于这对其他人可能有用,我们可以尝试将其集成到 openlayers 中。

关于javascript - Openlayers3 - 使用捏合手势在触摸设备上进行分数缩放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40882212/

相关文章:

javascript - 如何从对象数组中获取最大值以在 d3.scale.linear().domain() 中使用

javascript - 使用 Javascript 专注于移动设备的触摸映射和输入

c++ - 为什么我从我的 QTouchPoint 获得无效数据?

javascript - D3 光标下没有SVG元素时的几何缩放

java - Android:放大但保持元素的比例

ios - 可缩放的 UIImageView

javascript - 如何查看Vue组件中的多个属性?

javascript - Node Js - 使用正则表达式向路由添加多个参数

javascript - 打印出所有重复项 - Javascript - 需要替代解决方案

qt - 如何通过拖动来旋转qml矩形?