• 超级小的web手势库AlloyFinger


    针对多点触控设备编程的Web手势组件,快速帮助你的web程序增加手势支持,也不用再担心click 300ms的延迟了。拥有两个版本,无依赖的独立版和react版本。除了Dom对象,也可监听Canvas内元素的手势(需要Canvas引擎内置对象支持addEventListener绑定touch相关事件)。

    据不完全统计,目前AlloyFinger服务于:兴趣部落、QQ群、QQ动漫、腾讯学院、TEDxTencent、 AlloyTeam、腾讯CDC等多个部门、团队和项目。

    功能清单

    极小的文件大小

    简洁的API设计

    优秀的性能

    丰富的手势支持

    双版本(react和独立版)

    支持pinch缩放

    支持rotate旋转

    支持pressMove拖拽

    支持doubleTap双击

    支持swipe滑动

    支持longTap长按

    支持tap按

    支持singleTap单击

    快速上手

    独立版使用方式:

    //element为需要监听手势的dom对象
    new AlloyFinger(element, {
        pointStart: function () {
            //手指触摸屏幕触发
        },
        multipointStart: function () {
            //一个手指以上触摸屏幕触发
        },
        rotate: function (evt) {
            //evt.angle代表两个手指旋转的角度
            console.log(evt.angle);
        },
        pinch: function (evt) {
            //evt.scale代表两个手指缩放的比例
            console.log(evt.scale);
        },
        multipointEnd: function () {
            //当手指离开,屏幕只剩一个手指或零个手指触发
        },
        pressMove: function (evt) {
            //evt.deltaX和evt.deltaY代表在屏幕上移动的距离
            console.log(evt.deltaX);
            console.log(evt.deltaY);
        },
        tap: function (evt) {
            //点按触发
        },
        doubleTap: function (evt) {
            //双击屏幕触发
        },
        longTap: function (evt) {
            //长按屏幕750ms触发
        },
        swipe: function (evt) {
            //evt.direction代表滑动的方向
            console.log("swipe" + evt.direction);
        },
        singleTap: function (evt) {
            //单击
        }
    });

    官网DEMO

    http://alloyteam.github.io/AlloyFinger/

    1.必须跟transformjs一起用吗?

    不必须。也可以在事件回调里根据evt携带的信息使用js去操作CSS3。但是一起用,会让代码更简洁。

    2.pinch、rotate事件怎么在chrome浏览器调试的?

    一般用真机调试,但是也可以使用chrome浏览器,传送门 http://www.html5rocks.com/en/mobile/touch/#toc-touchdev

    3.缩放的origin点设置,这里是想手在图片哪个区域操作就设置哪里为origin进行缩放?

    自己去计算就是两个手指的连线的中点的坐标,

    比如中点X:

      pinch: function (evt) { 
            console.log((evt.touch[0].pageX+evt.touch[1].pageX)/2);
        },

    然后根据这个坐标和图片的坐标计算图片缩放的origin

    4.拖拽位置、缩放大小是否可以限制(始终在屏幕内显示,避免出现缩到很小看不到的情况)

    这个不应该有 AlloyFinger 控制。而应该由你的逻辑去控制

    https://github.com/AlloyTeam/AlloyFinger

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>AlloyFinger</title>
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <link rel="stylesheet" href="style/reset.css">
        <link rel="stylesheet" href="style/main.css">
        <script type="text/javascript" src="script/jquery-1.9.1.min.js"></script>
        <style>
        html, body{100%;height:100%;}
        .view_page{100%;height:100%;max-640px;position:relative;margin:0 auto;}
        .small_map_box{100%;}
        .small_map_box img{100%;display:block;}
        .big_map_box{position:absolute;left:0;top:0;100%;height:100%;background:rgba(0, 0, 0, 1);max-640px;z-index:100;display:none;
            -webkit-transform-origin:50% 20%;transform-origin:50% 20%;}
        .big_map_box.active{
            -webkit-animation:globalSca 0.4s ease both;
            -moz-animation:globalSca 0.4s ease both;
            -ms-animation:globalSca 0.4s ease both;
            animation:globalSca 0.4s ease both;
        }
        @-webkit-keyframes globalSca{
            0%{-webkit-transform:scale(0);background:rgba(0, 0, 0, 0);}
            100%{-webkit-transform:scale(1);background:rgba(0, 0, 0, 1);}
        }
        @-moz-keyframes globalSca{
            0%{-moz-transform:scale(0);background:rgba(0, 0, 0, 0);}
            100%{-moz-transform:scale(1);background:rgba(0, 0, 0, 1);}
        }
        @-ms-keyframes globalSca{
            0%{-ms-transform:scale(0);background:rgba(0, 0, 0, 0);}
            100%{-ms-transform:scale(1);background:rgba(0, 0, 0, 1);}
        }
        @keyframes globalSca{
            0%{transform:scale(0);background:rgba(0, 0, 0, 0);}
            100%{transform:scale(1);background:rgba(0, 0, 0, 1);}
        }
        .big_map_box.active2{
            -webkit-animation:globalScatoZero 0.4s ease both;
            -moz-animation:globalScatoZero 0.4s ease both;
            -ms-animation:globalScatoZero 0.4s ease both;
            animation:globalScatoZero 0.4s ease both;
        }
        @-webkit-keyframes globalScatoZero{
            0%{-webkit-transform:scale(1)}
            100%{-webkit-transform:scale(1);opacity:0;}
        }
        @-moz-keyframes globalScatoZero{
            0%{-moz-transform:scale(1)}
            100%{-moz-transform:scale(1);opacity:0;}
        }
        @-ms-keyframes globalScatoZero{
            0%{-ms-transform:scale(1)}
            100%{-ms-transform:scale(1);opacity:0;}
        }
        @keyframes globalScatoZero{
            0%{transform:scale(1)}
            100%{transform:scale(1);opacity:0;}
        }
        /*@-webkit-keyframes mymove{
            0%   {-webkit-transform:scale(0);}
            100%   {-webkit-transform:scale(1);}
        }
    
        @keyframes mymove{
            0%   {transform:scale(0);}
            100%   {transform:scale(1);}
        }*/
    
        .big_map_box img{position:absolute;100%;left:0;top:50%;}
        #result{position:absolute;left:0;top:0;color:#fff;}
        </style>
    </head>
    <body>
        <div class="view_page">
            <div class="small_map_box" id="small_map_box">
                <img src="images/map_small.jpg" class="small_map" id="small_map" alt="">
            </div>
            <div class="big_map_box">
                <div id="result">fewfew</div>
                <img src="images/map_big.jpg" class="big_map" id="big_map" alt="">
            </div> 
        </div>
    </body>
    </html>
    <script type="text/javascript" src="AlloyFinger-master/alloy_finger.js"></script>
    <script type="text/javascript" src="AlloyFinger-master/asset/transform.js"></script>
    <!-- <script type="text/javascript" src="AlloyFinger-master/asset/image_loaded.js"></script> -->
    <script type="text/javascript" src="AlloyFinger-master/asset/to.js"></script>
    <script type="text/javascript">
    !(function(){
        var winW = window.innerWidth;
        var smallmap = document.getElementById("small_map_box");
        var bigmap = document.getElementById("big_map");
        smallmap.addEventListener("touchstart", function(){
            smallmap.addEventListener("touchend", touchEnd, false);
        }, false);
    
        smallmap.addEventListener("touchmove", function(){
            smallmap.removeEventListener("touchend", touchEnd, false);
        }, false);
    
        smallmap.addEventListener("touchend", touchEnd, false);
    
        function touchEnd(){
            $(".big_map_box").css({"display": "block"}).removeClass("active2").addClass("active");
            bigmap.style.marginTop = -Math.round((winW * 1.0533333333))/ 2 + "px";
            bigmap.style.transform = "perspective(500px) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)";
            bigmap.style.webkitTransform = "perspective(500px) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)";
        }
        Transform(bigmap);
        var initScale = 1;
        var handlerMap = new AlloyFinger(bigmap, {
            //一个手指以上触摸屏幕触发
            multipointStart: function () {
                initScale = this.scaleX;
            },
    
            //当手指离开,屏幕只剩一个手指或零个手指触发
            multipointEnd: function (evt) {
                // bigmap.onclick = function(){
                //     $(".big_map_box").removeClass("active");
                // }
    
                // 缩放小于1的动画
                if(this.scaleX < 1){
                    new To(this, "scaleX", 1, 300);         // 绽放归位
                    new To(this, "scaleY", 1, 300);         // 绽放归位
                    new To(this, "translateX", 0, 300);     // 位移归位
                    new To(this, "translateY", 0, 300);     // 位移归位
                    new To(this, "rotateZ", 0, 300);        // 旋转归位
                    // 自己写的动画
                    // var that = this;
                    // this.scaleX = this.scaleY = 1;
                    // this.translateX = 0;
                    // this.translateY = 0;
                    // this.style.transition = "all 0.3s";
                    // setTimeout(function(){
                    //     this.style.transition = "0ms";
                    // }.bind(this), 300);
                }
                // 限制最大的尺寸
                if(this.scaleX > 3){
                    // this.scaleX = this.scaleY = 3;
                    new To(this, "scaleX", 3, 200);         // 绽放归位
                    new To(this, "scaleY", 3, 200);         // 绽放归位
                }
            },
    
            // 旋转
            // rotate: function (evt) {
            //     evt.preventDefault();
            //     //evt.angle代表两个手指旋转的角度
            //     this.rotateZ += evt.angle;
            // },
    
            // 双指缩放
            pinch: function (evt) {
                handlerMap.isDoubleTap = true;
                this.scaleX = this.scaleY = initScale * evt.zoom;
                evt.preventDefault();
    
            },
            // 双击放大
            // doubleTap: function () {
            //     handlerMap.isDoubleTap = true;
            //     if(this.scaleX === 1){
            //         new To(this, "scaleX", 3, 300);
            //         new To(this, "scaleY", 3, 300);
            //     }else if(this.scaleX === 3){
            //         new To(this, "scaleX", 1, 300);
            //         new To(this, "scaleY", 1, 300);
            //         new To(this, "translateX", 0, 300);     // 位移归位
            //         new To(this, "translateY", 0, 300);     // 位移归位
            //     }
            //     /*else if(this.scaleX > 2){
            //         new To(this, "scaleX", 2, 300);
            //         new To(this, "scaleY", 2, 300);
            //     }*/
            // },
            singleTap: function (evt) {
                if(!handlerMap.isDoubleTap){
                    $(".big_map_box").removeClass("active").addClass("active2");
                    setTimeout(function(){
                        $(".big_map_box").css({"display":"none"});
                    },400)
                }
            },
    
            // 移动
            pressMove: function (evt) {
                // 取消单击事件
    
                handlerMap.isDoubleTap = true;
                this.translateX += evt.deltaX;
                this.translateY += evt.deltaY;
    
                // 边界判断. 不让划出屏幕内
                if(this.scaleX === 1){
                    if(this.translateX !== 0){
                        // this.scaleX = this.scaleY = 3;
                        new To(this, "translateX", 0, 200);         // 绽放归位
                    }
                    this.translateY = 0;
                }
                evt.preventDefault();
            }
        })    
      
    
    }());
    
    function classList(e){
        //CSSClassList是一个模拟DOMTokenList的javascript类
        function CSSClassList(e){        
            //系统偷偷替我们做了:
            //var this = new Object();
            this.e = e;
        }   
    
        //contains方法
        CSSClassList.prototype.contains = function(c){
    
            //权威指南的方法
            //检查c是否是合法的类名
            if(c.length === 0 || c.indexOf(" ") != -1){
                throw new Error("invalid class name:'" + c + "'");
            }
            //首先是常规检查
            var classes = this.e.className;
            if(!classes) return false;          //e不含有类名
            if(classes === c) return true;      //e有一个完全匹配的类名
    
            //否则,把c自身看做一个单词,利用正则表达式搜索c
            //是单词的边界
            return classes.search("\b" + c + "\b") != -1;
    
    
            //网上正则方法
            /*var classname = this.e.className, reg = new RegExp("\b" + c + "\b");
            return reg.test(classname);*/
            
        }
    
        //add()方法
        CSSClassList.prototype.add = function(c){
            if(this.contains(c)) return;            //如果存在,则不添加
            var classes = this.e.className;
    
            //判断存在class与class类里最后一个类名没有空白格
            if(classes && classes[classes.length-1] != " "){
                c = " " + c;        
                this.e.className += c;          //将c添加到className中
            }
        }
    
        //remove()方法
        CSSClassList.prototype.remove = function(c){
            //检查c是否是合法的类名
            if(c.length === 0 || c.indexOf(" ") != -1){
                throw new Error("invalid class name:'" + c + "'");
            }
            //将所有作为单词的c和多余的尾随空格全部删除
            var pattern = new RegExp("\b" + c + "\b\s*","g");
            this.e.className = this.e.className.replace(pattern,"")
        }
    
        //toggle()方法,添加返回true,删除返回false
        CSSClassList.prototype.toggle = function(c){
            if(this.contains(c)){       //如果e.className包含c
                this.remove(c);         //删除它
                return false;
            }else{
                this.add(c);            //否则,添加它
                return true;
            }
        }
    
        //返回e.className本身
        CSSClassList.prototype.toString = function(){
            return this.e.className;
        };
    
        /*//返回在e.className中的类名 (CSSClassList原生中没有toArray方法)
        CSSClassList.prototype.toArray = function(){
            return this.e.className.match(/w+/g) || {};
        }*/
    
        if(e.classList){
            return e.classList;             //如果classList存在,则返回它
        }else{
            return new CSSClassList(e);     //否则就创建一个
        }
    }
    </script>
    

      

    有几个问题没有解决

    1.IOS图片scale放大模糊问题

    2.doubleTap与pinch触摸问题, 事件冲突

    3.禁止双指放大doubleTap事件, 和在pinch上"handlerMap.isDoubleTap = true;" 来阻止singleTap事件区分开来

  • 相关阅读:
    Apache Log4j 学习笔记
    关于BindingResult
    Java源码分析:深入探讨Iterator模式
    hibernate的ID生成策略(annotation方式@GeneratedValue)
    HTML5本地存储不完全指南
    pageX,clientX,offsetX,layerX的那些事
    getHibernateTemplate().execute(new HibernateCallback())方法
    jQuery.extend 与 jQuery.fn.extend 的区别
    16个优秀的JavaScript教程和工具推荐
    Spring 2.5:Spring MVC中的新特性
  • 原文地址:https://www.cnblogs.com/alantao/p/7867169.html
Copyright © 2020-2023  润新知