Javascript Openlayers3-使用按压手势在触摸设备上进行分数缩放?
Openlayers3可以通过在Javascript Openlayers3-使用按压手势在触摸设备上进行分数缩放?,javascript,touch,zooming,openlayers-3,fractions,Javascript,Touch,Zooming,Openlayers 3,Fractions,Openlayers3可以通过在setZoom()中指定分数,以编程方式以分数缩放级别显示地图 然而,我希望我的用户能够在移动触摸驱动设备(即智能手机)上获得分数缩放级别。当手指从屏幕上移开时,收缩或反向收缩通过跳到最近的整个缩放级别进行缩小/放大 触摸/移动用户如何才能让Openlayers3保持在用户所控制的精确范围(分数缩放级别) 我是否可以为Openlayers3地图或视图添加javascript,以使其按预期工作 特别是,我注意到Openlayers3有一个ol.interaction
setZoom()
中指定分数,以编程方式以分数缩放级别显示地图
然而,我希望我的用户能够在移动触摸驱动设备(即智能手机)上获得分数缩放级别。当手指从屏幕上移开时,收缩或反向收缩通过跳到最近的整个缩放级别进行缩小/放大
触摸/移动用户如何才能让Openlayers3保持在用户所控制的精确范围(分数缩放级别)
我是否可以为Openlayers3地图或视图添加javascript,以使其按预期工作
特别是,我注意到Openlayers3有一个ol.interaction.PinchZoom()
class()。这是ol.interaction.Pointer
的一个子类,它有一个handleUpEvent
和一个handleEvent
(应该是一个函数)。因此从理论上讲,我应该能够在PinchZoom
中替换handleUpEvent
,或者将默认的PinchZoom
交互替换为具有自定义事件处理函数的交互。但使用这两种方法,我无法调用新的handleUpEvent函数
(在拖网查看PinchZoom
的OL代码时,我发现默认的PinchZoom
可以实现我想要的功能,如果一个手指先从触摸屏上抬起,然后再从另一个手指上抬起,但我仍然希望在同时抬起两个手指时能够工作。)
这是我到目前为止试过的
第一次尝试-这只是尝试将标准的PinchZoom
手动事件替换为自定义事件,并将其设置为地图的唯一交互。但是,从不调用事件函数(从不记录任何内容)
第二次尝试-此尝试基于创建标准PinchZoom
交互的实际OL代码。在这种情况下,所有我的事件处理程序函数都会被调用,触摸次数(targetPointers
)始终为零(记录)。我不是javascript大师,但我怀疑这是因为ol.js中的符号与我所基于的ol-debug.js中的符号不同。事实上,我必须自己声明targetPointers
才能让它运行,即使它已经由OL本身声明了(但可能在非调试版本中使用了不同的符号名)
函数handleDownEvent(mapBrowserEvent){
log(“关闭事件处理程序”);
this.anchor=null;
此.lastDistance=未定义;
this.lastScaleDelta=1;
mapBrowserEvent.map.render();
返回true;//开始拖动
}
函数handleDragEvent(mapBrowserEvent){
if(this.targetPointers.length<2){
log(“拖动事件忽略-触摸”,this.targetPointers.length);
}否则{
log(“已处理的拖动事件”);
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;
//触间距离
变量距离=数学sqrt(dx*dx+dy*dy);
if(this.lastDistance=未定义){
scaleDelta=此.lastDistance uuz/距离;
}
此.lastDistance=距离;
如果(scaleDelta!=1.0){
this.lastScaleDelta=scaleDelta;
}
var map=mapBrowserEvent.map;
var view=map.getView();
var resolution=view.getResolution();
//缩放锚点。
var viewportPosition=map.getViewport().getBoundingClientRect();
var centroid=ol.interaction.Pointer.centroid(this.targetPointers);
质心[0]-=视口位置.left;
质心[1]-=viewportPosition.top;
this.anchor=map.getCoordinateCompixel(质心);
//缩放,绕过分辨率约束
map.render();
ol.interaction.interaction.zoomWithoutConstraints(
地图、视图、分辨率*scaleDelta,this.anchor_u2;);
}
}
函数handleUpEvent(mapBrowserEvent){
log(“向上事件处理程序”);
返回true;//停止拖动
}
var pinchZoom=new ol.interaction.Pointer({
handleDownEvent:handleDownEvent,
handleDragEvent:handleDragEvent,
handleUpEvent:handleUpEvent
});
pinchZoom.targetPointers=[];
map=新ol.map({
交互:ol.interaction.defaults().extend([pinchZoom]),
图层:[
新ol.layer.Tile({
source:newol.source.TileJSON({url:'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure'})
})
],
目标:“地图”,
视图:新ol.view({中心:[0,0],缩放:3})
});
尝试时出现的问题:
第一次尝试
ol.interaction.PinchZoom
的handleEvent
选项不存在。这就是为什么不执行回调
第二次尝试
正如您已经注意到的,您尝试使用openlayers内部构件。这可能适用于调试版本,但不适用于发布版本,因为名称不同于
解决方案
添加选项以在openlayers源中的收缩缩放端保持分数分辨率
问题:
拉取请求:
默认情况下,收缩缩放将保持用户选择的分数缩放级别。。从OpenLayers 3.20开始
早期的想法是: 例如,我将选项
keepFractionalZoomLevel
添加到ol.interaction.PinchZoom
:
请参阅此小提琴以了解工作示例:
注意:fiddle使用自定义openlayers构建:部署url为: 此示例是否按照您的要求运行?
由于这可能对其他人有用,我们可以尝试将其集成到openlayers中。
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})
});
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})
});