您的位置:首页 > 其它

编写 iPhone Friendly 的 Web 应用程序 (Part 7 - 多点触击)

2011-06-28 15:30 351 查看
转载自:/article/4626249.html

这个系列的上一篇文章差不多是两年之前的事情了,在这两年里Mobile Safari并非停滞不前,从iPhone 2.0开始Mobile Safari就加入了对多点触击的支持,现在我们就来看一下我们可以利用它来干什么。

相信很多人都看过WPF为Surface设备做的一个简单demo,也就是在桌面上显示若干张照片,你可以通过单点触击拖放,也可以通过多点触击缩放和旋转。这在iPhone上能够做到,甚至在Mobile Safari里面也能做到,因为Mobile Safari提供了一套专门用于多点触击的JavaScript接口。现在我们就来看看如何利用这套接口吧。

我们都知道,Mobile Safari自身会处理多点触击,默认行为包括滚动和缩放。我们可以接管相应的事件,同时使用
e.preventDefault()
禁用浏览器默认行为,使得我们的Web应用程序能够如同WPF桌面应用一样处理多点触击。下面我们来深入看看Mobile Safari提供的多点触击事件。

单点触击

首先我们要处理的是单点触击事件,禁用浏览器的滚动行为,同时为我们的照片(一个
img
元素)增加拖动行为。在这里,我们需要用到
touchstart
touchmove
touchend
事件。在这三个事件里,我们可以通过
e.targetTouches
获取到用户点击的坐标,从而计算相对的位置变化。

首先,我们要在
touchstart
事件里面记录下初始坐标:

var transform = {
x: 0,
y: 0,
rotation: 0,
scale: 1
};

var startX;
var startY;
var touching = false;

element.addEventListener("touchstart", function(e){
e.preventDefault();
startX = e.targetTouches[0].clientX;
startY = e.targetTouches[0].clientY;
touching = true;
});


接着,我们要在
touchmove
事件里面计算相对位置变化,并且更新
element
坐标:

element.addEventListener("touchmove", function(e){
e.preventDefault();
if (!touching) return;
transform.x += e.targetTouches[0].clientX - startX;
transform.y += e.targetTouches[0].clientY - startY;
updateTransform();
startX = e.targetTouches[0].clientX;
startY = e.targetTouches[0].clientY;
});


updateTransform
做了什么?现在先不讨论,我们只要把事件相关数据正确地更新到
transform
的四个属性即可,如何把这些属性反映到界面上稍后再说。

最后,我们还要在
touchend
事件里面处理一下标志位:

element.addEventListener("touchend", function(e){
e.preventDefault();
touching = false;
)};


就这么简单?是的。关键点也就在于
touchmove
时跟踪e.targetTouches的变化,并更新
transform
里面的信息。

CSS3变换

接下来我们看看如何将
transform
里面的信息作用到界面上。在没有CSS3的时代,这是极之痛苦的事情,我们需要修改元素的多个样式属性才能实现这部分的功能,并且还没办法实现旋转。现在有了CSS3,只需要修改一下transform属性就可以了:

var updateTransform = function(){
element.style.webkitTransform =
"translate(" + transform.x + "px, " + transform.y + "px) " +
"rotate(" + transform.rotation + "deg) " +
"scale(" + transform.scale + ")";
}


一句代码就把位置、旋转、缩放都设置好了!尽管我们现在还没用到旋转和缩放属性,那就让它们保持默认值吧,我们在多点触击的事件里面会设置它们的。

多点触击

多点触击涉及到三个事件:
gesturestart
gesturechange
gestureend
。这三个事件跟单点触击的三个事件非常类似,使用起来甚至可以说是更简单一些:

var startRotation;
var startScale
var gesturing = false;

element.addEventListener("gesturestart", function(e){
e.preventDefault();
startRotation = transform.rotation;
startScale = transform.scale;
gesturing = true;
});

element.addEventListener("gesturechange", function(e){
e.preventDefault();
if (!gesturing) return;
transform.rotation = startRotation + e.rotation;
transform.scale = startScale * e.scale;
updateTransform();
});

element.addEventListener("gestureend", function(e){
e.preventDefault();
gesturing = false;
});


代码确实比之前的还要少一些,重点就是正确设置
transform
的两个属性,随后调用一下
updateTransform
就能把最近的状态更新的界面上。

小结

在这篇文章里,我们了解到了Mobile Safari的6个特有事件,以及如何利用这6个特有事件处理多点触击。

如果你直接使用我的代码去实现开头所说的照片拖放应用,你会发现一个小问题——在进行多点触击操作时,旋转与缩放都是很自然的,就是拖动不自然,好像拖动只跟随第一个触点似的。原因很简单,在多点触击时,管理触点移动的还是
touchmove
事件,但上述代码只处理
e.targetTouches[0]
,所以拖动只跟随第一个触点。

如果需要同时跟随两个触点,你需要对代码稍作改动,使得移动距离为
e.targetTouches[0]
e.targetTouches[1]
的平均值。为什么呢?如果一个触点往上移动30px,另一个触点往下移动10px,除去旋转与缩放效果外,照片的中点应该是往上移动10px的,也就是两个移动的平均值。那么我如何知道当前有多少个触点呢?看看
e.targetTouches.length
就知道了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: