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


    转载自:http://www.cnblogs.com/cathsfz/archive/2009/11/24/1609883.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元素)增加拖动行为。在这里,我们需要用到touchstarttouchmovetouchend事件。在这三个事件里,我们可以通过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 + ")";
    }
    

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

    多点触击

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

    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就知道了。

  • 相关阅读:
    使用logstash配置nginx和tomcat日志统一收集到一台日志服务器
    文章
    辣和辛的区别是什么?
    prometheus和zabbix的对比
    从零搭建Prometheus监控报警系统
    Adobe Flash Professional 制作定制FLashPlayer播放器之读取配置文件(二)
    Adobe Flash Professional 制作定制FLashPlayer播放器(一)
    OSG+VS2015 测试Demo
    OSG+VS2015 入门教程---环境搭建
    button的类型?为什么button 会自动提交表单?
  • 原文地址:https://www.cnblogs.com/yili/p/2092338.html
Copyright © 2020-2023  润新知