指引网

当前位置: 主页 > 网页制作 > JavaScript >

手势识别与事件库 Touch.js

来源:未知 作者:admin 点击: 时间:2017-11-04 11:21
[摘要] Touch.js是移动设备上的手势识别与事件库, 由百度云Clouda团队维护,也是在百度内部广泛使用的开发工具.Touch.js的代码已托管于github并开源,希望能帮助国内更多的开发者学习和开发出优秀的A

Touch.js是移动设备上的手势识别与事件库, 由百度云Clouda团队维护,也是在百度内部广泛使用的开发工具.

Touch.js的代码已托管于github并开源,希望能帮助国内更多的开发者学习和开发出优秀的App产品.

Touch.js手势库专为移动设备设计, 请在Webkit内核浏览器中使用.

Examples

//swipe example 
touch.on('.target', 'swipeleft swiperight', function(ev){
    console.log("you have done", ev.type);
});

 

http://www.cnblogs.com/lukunlin/p/4514253.html?utm_source=tuicool&utm_medium=referral

今天,随便搜搜看到了一个新的手势库,也许能让我为现在使用者的hammer.js的手势库带来的烦恼而消除。

它是百度团队开发的,现在由百度云Clouda进行维护。

在我上一篇文章里有提到怎么去使用hammer.js的框架,他有个比较让人烦躁的缺点,就是事件绑定,每次只能绑定一个DOM元素,而且每次都需要去NEW 一个函数,大家都知道,每new一次都会在内存开辟一个新的空间,也就是他比较占用内存。

如:

var obj = new Hammer( document.getElementById('element') );

obj.on('tap',function);

如果是这样,会给我们造成比较多的麻烦。

所以今天就简单说说touch.js这个框架给我们开发带来的便利。

我们看看它是如何给一个DOM快速选择并且绑定事件的。

代码:

touch.on(".div","tap",function);

 就这样简单就能选择到所有class为div的DOM元素加了一个点击事件。

并且事件里面的this指向了发生事件的原生DOM的元素。

event对象是我们做手势里用处比较多的一个对象,如发生的距离的X/Y,发生的type等。

 

 

http://cloudajs.org/formerIndex

 

 

百度touch.js API教程  http://blog.csdn.net/libin_1/article/details/50534611

下载:http://download.csdn.net/detail/cometwo/9407914

<!DOCTYPE html>
<html>

    <head>
        <link href="img/favicon.ico" rel="shortcut icon" type="images/x-icon">
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta content="initial-scale=1.0,maximum-scale=1.0,width=device-width" name="viewport">
        <meta name="apple-touch-fullscreen" content="YES">
        <meta name="format-detection" content="telephone=no">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">
        <meta http-equiv="expires" content="0">
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <title>百度touch.js API教程[UC浏览器测试通过]</title>
        <script type="text/javascript" src="js/touch.min.js"></script>
        <script type="text/javascript" src="js/jquery-2.1.4.min.js"></script>
        <script type="text/javascript" src="js/hijs.js"></script>
        <style type="text/css">
            *,
            html,
            body {
                padding: 0px;
                margin: 0px;
                left: 0px;
                top: 0px;
            }

            #main {
                padding: 5px;
            }

            #play {
                background: black;
                width: 100%;
                height: 800px;
                border: 1px solid red;
                position: relative;
                overflow: hidden;
            }

            img {
                position: absolute;
                width: 200px;
                height: 200px;
                display: block;
                left: 50%;
                top: 50%;
                margin-left: -100px;
                margin-top: -100px;
                border-radius: 50%;
                border: 1px solid red;
            }

            img:hover {
                cursor: pointer;
            }

            .div1 {
                margin-top: 10px;
                width: 100%;
                height: 50px;
                color: blue;
                font-size: 25px;
                line-height: 50px;
                background: green;
                text-align: center;
            }
        </style>
        <script type="text/javascript">
            /*******************************旋转程序****************************************/
            /*  $(function() { //旋转程序
                //  runhijs(); //官方程序不知为什么要加,貌似不加也可以
                var angle = 0;
                touch.on('#target', 'touchstart', function(ev) {
                    ev.startRotate();
                    ev.preventDefault();
                });
                touch.on('#target', 'rotate', function(ev) {
                    var totalAngle = angle + ev.rotation;
                    if (ev.fingerStatus === 'end') { //这一句很重要
                        angle = angle + ev.rotation;
                        $('.div1').text("本次旋转角度为:" + ev.rotation + "度, 方向:" + ev.direction + ".");
                    }
                    this.style.webkitTransform = 'rotate(' + totalAngle + 'deg)';
                });
            }); */
            /*******************************放大缩小****************************************/
            //                      $(function() {     //放大缩小
            //                          var target = document.getElementById("target");
            //                          target.style.webkitTransition = 'all ease 0.05s';
            //                          touch.on('#target', 'touchstart', function(ev) {
            //                              ev.preventDefault();
            //                          });
            //                          var initialScale = 1;
            //                          var currentScale;
            //                          touch.on('#target', 'pinchend', function(ev) {
            //                              currentScale = ev.scale - 1;
            //                              currentScale = initialScale + currentScale;
            //                              currentScale = currentScale > 5 ? 5 : currentScale; //自己调节可以放大的最大倍数
            //                              currentScale = currentScale < 0.1 ? 0.1 : currentScale; //自己调节可以缩小的最小倍数
            //                              this.style.webkitTransform = 'scale(' + currentScale + ')';
            //                              $('.div1').text("当前缩放比例为:" + currentScale + "倍.");
            //                          });
            //                          touch.on('#target', 'pinchend', function(ev) {
            //                              initialScale = currentScale;
            //                          });
            //                      });
            /*******************************识别tap[单击], doubletap[双击]和hold[长按]事件****************************************/
            //          $(function() { //识别tap[单击], doubletap[双击]和hold[长按]事件
            //              $('.div1').text("识别tap[单击], doubletap[双击]和hold[长按]事件.");
            //              // touch.on('#target', 'touchstart', function(ev){
            //              // ev.preventDefault();
            //              // });
            //              touch.on('#target', 'hold tap doubletap', function(ev) {
            //                  $('.div1').text("当前事件为: " + ev.type);
            //                  var _this = this;
            //                  this.classList.add("bounce");
            //                  touch.on(this, "webkitAnimationEnd", function() {
            //                      _this.classList.remove("bounce");
            //                  });
            //              });
            //          });
            /*******************************向左向右滑动****************************************/
            //          $(function() {
            //              var w = 205;
            //              var tw = play.offsetWidth;
            //              var lf = document.getElementById("target").offsetLeft;
            //              var rt = tw - w - lf;
            //              $('.div1').text("向左, 向右swipe滑动");
            //              touch.on('#target', 'touchstart', function(ev) {
            //                  ev.preventDefault();
            //              });
            //              var target = document.getElementById("target");
            //              target.style.webkitTransition = 'all ease 0.2s';
            //              touch.on(target, 'swiperight', function(ev) {
            //                  this.style.webkitTransform = "translate3d(" + rt + "px,0,0)";
            //                  $('.div1').text("向右滑动.");
            //              });
            //              touch.on(target, 'swipeleft', function(ev) {
            //                  $('.div1').text("向左滑动.");
            //                  this.style.webkitTransform = "translate3d(-" + this.offsetLeft + "px,0,0)";
            //              });
            //          });
            /*******************************抓取并拖拽目标元素****************************************/
                        $(function() {
                            $('.div1').text("抓取并拖拽目标元素");
                            touch.on('#target', 'touchstart', function(ev) {
                                ev.preventDefault();
                    });
                        var target = document.getElementById("target");
                        var dx, dy;
                            touch.on('#target', 'drag', function(ev) {
                                dx = dx || 0;
                                dy = dy || 0;
                                var offx = dx + ev.x + "px";
                            var offy = dy + ev.y + "px";
                                this.style.webkitTransform = "translate3d(" + offx + "," + offy + ",0)";
                            });
                            touch.on('#target', 'dragend', function(ev) {
                                dx += ev.x;
                                dy += ev.y;
                                $('.div1').text("当前x值为:" + dx + ", 当前y值为:" + dy + ".");
                            });
                        });
            /*******************************抓取并拖拽目标元素****************************************/
            //          $(function() {
            //              $('.div1').text("识别原生事件");
            //              touch.on('#target', 'touchstart', function(ev) {
            //                  ev.preventDefault();
            //              });
            //              touch.on('#target', 'touchstart touchmove touchend', function(ev) {
            //                  var _this = this;
            //                  if (!this.classList.contains("bounce")) {
            //                      if (ev.type === "mousedown" || ev.type === "touchstart") {
            //                          this.classList.add("bounce");
            //                          touch.on(this, "webkitAnimationEnd", function() {
            //                              _this.classList.remove("bounce");
            //                          });
            //                      }
            //                  }
            //                  $('.div1').text("当前为原生事件: " + ev.type);
            //              });
            //          });
        </script>
    </head>

    <body>
        <div id="main">
            <h1 style="color: red;text-align: center;">使用哪个只需要打开相应的注释即可</h1>
            <div id="play">
                <img id="target" draggable="false" src="img/cloud.png" />
            </div>
            <div class="div1">"touch.js demo记录每一次操作"</div>
        </div>
    </body>

</html>

 

原文:http://mobile.51cto.com/news-414811_all.htm

¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥ 
Touch 
在开发移动端的应用中会使用到很多的手势操作,例如一指拖动、两指旋转等等,为了方便开放者快速集成这些手势,在Clouda中内置了事件和手势库Library.touch,下面将详细的介绍如何使用Library.touch。

touch.config 
语法: touch.config(config) 
对手势事件库进行全局配置。

参数描述:

config为一个对象


tap: true, //tap类事件开关, 默认为true 
doubleTap: true, //doubleTap事件开关, 默认为true 
hold: true, //hold事件开关, 默认为true 
holdTime: 650, //hold时间长度 
swipe: true, //swipe事件开关 
swipeTime: 300, //触发swipe事件的最大时长 
swipeMinDistance: 18, //swipe移动最小距离 
swipeFactor: 5, //加速因子, 值越大变化速率越快 
drag: true, //drag事件开关 
pinch: true, //pinch类事件开关 

touch.on 
语法:touch.on(element, types, options, callback) 
绑定指定元素的事件。

参数描述:

element: 元素对象或选择器。

types: 事件的类型, 可接受多个事件以空格分开,支持原生事件的透传, 支持的一些事件类型有:

pinchstart 双指缩放动作开始 
pinchend 双指缩放动作结束 
pinch 双指缩放事件 
pinchin 双指向里缩小 
pinchout 双指向外放大 
rotateleft 向左旋转 
rotateright 向右旋转 
rotate 旋转事件 
swipestart 单指滑动动作开始 
swiping 单指滑动事件 
swipeend 单指滑动动作结束 
swipeleft 单指向左滑动 
swiperight 单指向右滑动事件 
swipeup 单指向上滑动 
swipedown 单指向下滑动 
swipe 单指滑动事件 
drag 单指向左右拖动 
hold 单指按住不放事件 
tap 单指点击 
doubletap 单指双击 
例如旋转实例如下:

var angle = 30; 
touch.on(‘#rotation .target’, ‘touchstart’, function(ev){ 
ev.startRotate(); 
ev.originEvent.preventDefault(); 
ev.originEvent.stopPropagation(); 
}); 
touch.on(‘#rotation .target’, ‘rotate’, {interval: 10}, function(ev){ 
var totalAngle = angle + ev.rotation; 
if(ev.fingerStatus === ‘end’){ 
angle = angle + ev.rotation; 
}

this.style.webkitTransform = ‘rotate(’ + totalAngle + ‘deg)’; 
}); 
更多使用实例请查看http://code.baidu.com/

options(可选): 目前可配置的参数为:


//采样频率 
interval: 10,//性能参数,值越小,实时性越好, 但性能可能略差, 值越大, 性能越好。遇到性能问题时,可以将值设大调优,建议值设置为10。 
//swipe加速度因子(swipe事件专用) 
swipeFactor: 5 //(int: 1-10)值越大,速率更快。 

callback: 事件处理函数, 该函数接受的参数为一个gesture event object, 可访问的属性有:

originEvent //触发某事件的原生对象

type //事件的名称

rotation //旋转角度

scale //缩放比例

direction //操作的方向属性

fingersCount //操作的手势数量

position //相关位置信息, 不同的操作产生不同的位置信息。

distance //swipe类两点之间的位移

distanceX //swipe类事件x方向的位移

distanceY //swipe类事件y方向的位移

angle //swipe类事件触发时偏移角度

factor //swipe事件加速度因子

startRotate //启动单指旋转方法,在某个元素的touchstart触发时调用。

touch.live 
语法:touch.live(selector, types, options, callback) 
使用方法基本上与on相同,live的第一个参数只接受css3选择器。通过live()方法附加的事件处理程序适用于匹配选择器的当前及未来的元素(比如由脚本创建的新元素)

touch.off 
语法:touch.off(element,types,callback) 
解除某元素上的事件绑定。

参数描述:

element:元素对象或选择器

types:事件的类型

callback:时间处理函数

Publish/Subscribe 
subscribe 
订阅被发布的数据,与pubilsh配合使用

不带参数 env.subscribe(publishName, function(collection){});

env.subscribe(“pub-allStudents”, function(studentCollection){

}); 
pulishName

所定义的Publish的唯一名称,在一个App内全局唯一,该参数与sumeru.publish(modelName, publishName,function(callback))中的publishName名称需要保持一致。

function(Collection){}

Subscribe成功获得数据时,被调用的响应方法。

带参数 env.subscribe(publishName,arg1,arg2, … , function(collection){});

env.subscribe(“pub-StudentsWithGender”, “male”, function(msgCollection){

}); 
subscribeByPage 
分页订阅数据

不带参数 env.subscribeByPage(publishName, options, function(collection){});

var pageOption{ 
pagesize : 1, 
page : 2, 
uniqueField : ‘time’ 
};

env.subscribeByPage(“pub-allStudents”, pageOption, function(studentCollection){

}); 
options

分页设置

pageSize

每页数据的数量

page

页码

uniqueField

排序的唯一字段名

带参数 env.subscribeByPage(publishName, options, arg1,arg2, … , function(collection){});

env.subscribeByPage(“pub-StudentsWithGender”, pageOption, “male”, function(msgCollection){

}); 
prioritySubscribe 
在断线重新连接的情况下,使用prioritySubscribe方法订阅数据优先被调用,使用方式与subscribe相同。

publish 
发布数据的方法,其运行在Server上。

不带参数 sumeru.publish(modelName,pubName,function(callback){},options)

modelName

被发布数据所属的Model名称

pubName

所定义的Publish的唯一名称,在一个App内全局唯一,该参数与Controller中subscribe()成对使用。

function(callback)

描述数据发布规则的自定义函数,在这里定义被发布数据所需要符合的条件。

options

可在此添加以下六种事件

beforeInsert

在实际插入数据到数据库前的事件

beforeInsert : function(serverCollection, structData, userinfo, callback){ 
callback(structData); 

structData

需要插入到数据库的数据,我们可以对该数据进行操作,然后将数据插入到数据库中,如果对数据没有修改,则将原数据添加到数据库中。

callback

before系列的事件中如果不添加 callback(),将阻止数据对数据库的影响。

callback(structData)

如果需要对原数据进行修改,可以传入参数structData

afterInsert

在实际插入数据到数据库后的事件

afterInsert : function(serverCollection, structData){ 

beforeUpdate

在实际更新数据库数据前的事件

beforeUpdate : function(serverCollection, structData, userinfo, callback){ 
callback(); 

afterUpdate

在实际更新数据库数据后的事件

afterUpdate : function(serverCollection, structData){ 

beforeDelete

在实际删除数据库数据前的事件

beforeDelete : function(serverCollection, structData, userinfo, callback){ 
callback(); 

afterDelete

在实际删除数据库数据后的事件

afterDelete : function(serverCollection, structData){ 

实例:

module.exports = function(sumeru){ 
sumeru.publish(‘student’, ‘pub-allStudents’, function(callback){ 
var collection = this;

    collection.find({}, function(err, items){ 
        callback(items); 
    }); 
}); 


带参数 sumeru.publish(modelName,pubName,function(arg1, …, callback){},options)

实例:

module.exports = function(sumeru){ 
sumeru.publish(‘student’, ‘pub-allStudents’, function(gender,callback){ 
var collection = this;

    collection.find({'gender':gender}, function(err, items){ 
        callback(items); 
    }); 
}); 


publishByPage 
分页发布数据

sumeru.publishByPage(modelName,pubName,function(arg1,arg2,…,pageOptions, callback){},options) 
options

分页设置,有Controller中subscribeByPage()传入。

实例:

sumeru.publishByPage(‘student’, ‘pub-allStudents’, function(gender,options,callback){ 
var collection = this; 
collection.find({ sort :{‘time’:-1}, 
limit : options.pagesize, 
skip : (options.page-1)*options.pagesize, 
“gender”: gender 
}, function(err, items){ 
callback(items); 
}); 
}); 
sort

排序

limit

每页显示的个数

skip

当前页与起始页间隔的个数

详细的使用情况请查看《Example》文档中的实例。

publishPlain 
用于发布简单对象,而非Collection。

sumeru.publishPlain(modelName,pubName,function(callback){},options) 
实例:

如果需要发布Collection中数据的总数量,可使用下面方法:

fw.publishPlain(‘student’, ‘pub-allStudents’, function(callback){ 
var collection = this;

collection.count({},function(err, count){ 
    callback(count); 
}); 

}); 
下面的三种方法是包含权限中心的身份验证的Publish。

securePublish 
在身份验证成功的情况下发布数据

sumeru.publish(modelName,pubName,function(userinfo, callback){},options) 
securePublishByPage 
在身份验证成功的情况下分页发布数据

sumeru.securePublishByPage(modelName,pubName,function(pageOptions,userinfo, callback){},options) 
securePublishPlain 
在身份验证成功的情况下发布简单对象

sumeru.securePublishPlain(modelName,pubName,function(userinfo, callback){},options) 
external 
实现了三方数据同步的方法,用来满足从三方网站/三方接口获取和同步数据的需求。

extfind(pubName,callback)

在publish文件中发布第三方数据

fw.publish(‘news’,’pubnews’,function(callback){ 
var collection = this;

collection.extfind('pubnews',callback); 

}); 
使用该方法需要在publish下添加一个如何获取第三方数据的配置文件

config[pubname]

pubname

与publish中collection.extfind(pubname,callback)方法pubname一致,全局唯一

uniqueColumn

uniqueColumn为三方数据唯一标识,类型为String

uniqueColumn : “name”, 
fetchUrl: function((/* arg1, arg2, arg3 /)){}

指定抓取的URL。arg1,arg2为传递的参数

fetchUrl : function(/* arg1, arg2, arg3 /){ 
return ‘http://some.host.com‘; 

resolve : function(originData){}

resolve方法作用是将抓取回来的原始数据(originData)转化成为符合Model定义的数据(resolved)

resolve : function(originData){ 
var j = JSON.parse(originData); 
var resolved = j; 
return resolved; 

fetchInterval

fetchInterval为可选参数,用来指定抓取时间间隔,单位为ms

buffer

buffer为可选参数,值为true时表示获取原始Buffer,否则获取原始数据字符串

type

声明此模块为归属为’external’

return { 
type : ‘external’, 
config : config 

实例如下:

/** 
* 获取三方数据信息,由开发者自定义 
*/ 
function runnable(){ 
//{Object} config是所有三方publish配置的容器 
var config = {};

config['pubext'] = { 
    //{String} uniqueColumn为三方数据唯一标识 
    uniqueColumn : "name", 

    //{Function} fetchUrl的参数就是订阅时发起的参数,返回值为pubext所抓取的url地址 
    fetchUrl : function(/** arg1, arg2, arg3 */){ 
        return 'http://some.host.com'; 
    }, 

    //{Function} resolve方法作用是将抓取回来的原始数据(originData)转化成为符合Model定义的数据(resolved) 
    resolve : function(originData){ 
        var j = JSON.parse(originData); 
        var resolved = j; 

        return resolved; 
    }, 

    //{Number} fetchInterval为可选参数,用来指定抓取时间间隔,单位为ms 
    fetchInterval : 60 * 1000, 

    //{Boolean} buffer为可选参数,值为true时表示获取原始Buffer,否则获取原始数据字符串 
    buffer : false 
} 

//最后需要声明此模块为归属为'external' 
return { 
    type : 'external', 
    config : config 
} 

}

module.exports = runnable; 
指定三方增/删/改接口以及数据

当数据发生变化时,如何使用Clouda达到三方数据同步的效果,具体实现方法如下:

较为紧凑的声明方式

postUrl

postUrl方法用来指定三方post接口的地址信息, 参数type为增量类型,增量类型为’insert’,’update’,’delete’三者之一;

prepare

prepare方法用来将增量数据转化成为符合三方POST接口要求的post数据,参数type同为增量类型,参数data为增量的实际数据。

实例如下:

/** 
* 三方数据POST请求信息,由开发者自定义 
*/ 
function runnable(){

var config = {} 

config['pubext'] = { 

    /** 
     * 声明三方POST接口地址 
     * {String} type为'delete', 'insert', 'update'其中之一 
     * 如果subscribe时带参数,参数会按照subscribe顺序接在postUrl的参数中 
     */ 
    postUrl : function(type /** arg1, arg2, arg3... */){ 
        var options = { 
            host : 'some.host.com', 
            path : '/' + type , 
            headers: { 
                //在此自定义header内容,clouda默认的 'Content-Type': 'application/x-www-form-urlencoded' 
                'Content-Type': ... 
            } 
        } 
        return options; 
    }, 

    /** 
     * prepare方法将增量数据转化为符合三方要求的post数据。 
     * {String} type为增量操作,值为'delete', 'insert', 'update'其一; 
     * {Object} data为增量数据,如:{ name : 'user1', age : 26 }。 
     */ 
    prepare : function(type, data){ 
        var prepareData = {};  //prepareData为三方post所需的data 
        if(type === "delete"){ 
            prepareData.name = data.name; 
        }else if(type === "insert"){ 
            prepareData.name = data.name; 
            prepareData.age = data.age; 
        }else{ 
            prepareData.name = data.name; 
            prepareData.age = data.age; 
        } 

        return prepareData; 
    } 
} 

return { 
    type : 'external', 
    config : config 
} 

}

module.exports = runnable; 
较为工整的声明方式

deleteUrl,insertUrl,updateUrl

三个方法作用等同于postUrl,返回不同操作下三方接口url信息

onDelete,onInsert,onUpdate

三个方法作用等同于prepare方法, 返回经过处理,传给三方接口的post数据

实例如下:

function runnable(){

var config = {}; 

config['pubext'] = { 
    //arg1, arg2, arg3是subscribe时输入的参数 
    deleteUrl : function(/** arg1, arg2, arg3... */){ 
        return { 
            host : 'some.host.com', 
            path : '/delete' 
        } 
    }, 

    insertUrl : function(/** arg1, arg2, arg3... */){ 
        return { 
            host : 'some.host.com', 
            path : '/insert' 
        } 
    }, 

    updateUrl : function(/** arg1, arg2, arg3... */){ 
        return { 
            host : 'some.host.com', 
            path : '/update' 
        } 
    }, 

    onInsert : function(data){ 
        var prepareData = {}; 
        prepareData.name = data.name; 
        prepareData.age = data.age; 
        return prepareData; 
    }, 

    onUpdate : function(data){ 
        var prepareData = {}; 
        prepareData.name = data.name; 
        prepareData.age = data.age; 
        return prepareData; 
    }, 

    onDelete : function(data){ 
        var prepareData = {} 
        prepareData.name = data.name; 
        return prepareData; 
    } 
} 

return { 
    type : 'external', 
    config : config 
} 

}

module.exports = runnable; 
sumeru.external.get

向第三方发送get请求

var url = “http://some.host.com“; 
var getCallback = function(data){ 
console.log(data); 

sumeru.external.get(url, getCallback); 
sumeru.external.post

向第三方发送post请求

var options = { 
host : “some.host.com”, 
path : “/insert” 
}

var postData = { 
name : sumeru.utils.randomStr(8), 
age : parseInt( 100 * Math.random()) 
}

var postCallback = function(data){ 
console.log(data); 
}

sumeru.external.post(options, postData, postCallback); 
具体使用请查看《Example》文档中的SpiderNews实例。

------分隔线----------------------------