zoukankan      html  css  js  c++  java
  • js 拖动滑块验证

     备注:拖动滑块时尽量平移,chrome浏览器上没有卡顿情况,但是搜狗极速模式和360极速模式都遇到了卡顿,拖不动情况,应是浏览器内部对事件响应速度导致吧。

    JS代码:

    ;(function ($,window,document,undefined) {
        function SliderUnlock(elm, options, success){
            var me = this;
            var $elm = me.checkElm(elm) ? $(elm) : $;
            success = me.checkFn(success) ? success : function(){};
    
            var opts = {
                successLabelTip: "验证成功!",
                defaultLabelTip: "拖动滑块验证!",
                duration:  200,
                swipestart:  false,
                min:  0,
                max:  $elm.width(),
                index:  0,
                IsOk:  false,
                lableIndex: 0
            };
    
            opts = $.extend(opts, options||{});
            
            //$elm
            me.elm = $elm;
            //opts
            me.opts = opts;
            //是否鼠标移入状态
            me.isIn = false;
            //鼠标移出次数,防抖
            me.outNum = 0;
            //是否开始滑动
            me.swipestart = opts.swipestart;
            //最小值
            me.min = opts.min;
            //最大值
            me.max = opts.max;
            //当前滑动条所处的位置
            me.index = opts.index;
            //是否滑动成功
            me.isOk = opts.isOk;
            //滑块宽度
            me.labelWidth = me.elm.find('#label').width();
            //滑块背景
            me.sliderBg = me.elm.find('#slider_bg');
            //鼠标在滑动按钮的位置
            me.lableIndex = opts.lableIndex;
            //success
            me.success = success;
        }
    
        SliderUnlock.prototype.init = function () {
            var me = this;
            me.elm.find("#label").on("mousedown", function (event) {
                var e = event || window.event;
                me.lableIndex = e.clientX - this.offsetLeft;
                me.handerIn();
            }).on("mousemove", function (event) {
                me.handerMove(event);
            }).on("mouseup", function (event) {
                me.handerOut();
            }).on("mouseout", function (event) {
                me.handerOut();
            }).on("touchstart", function (event) {
                var e = event || window.event;
                me.lableIndex = e.originalEvent.touches[0].pageX - this.offsetLeft;
                me.handerIn();
            }).on("touchmove", function (event) {
                me.handerMove(event, "mobile");
            }).on("touchend", function (event) {
                me.handerOut();
            });
            me.updateView();
        };
    
        /**
         * 鼠标/手指接触滑动按钮
         */
        SliderUnlock.prototype.handerIn = function () {
            var me = this;
            if (me.isIn)
                return;
            me.swipestart = true;
            me.outNum = 0;
            me.min = 0;
            me.max = me.elm.width();
            me.isIn = true;
        };
    
        /**
         * 鼠标/手指移出
         */
        SliderUnlock.prototype.handerOut = function () {
           
            var me = this;
            if (!me.isIn)
                return;
            me.outNum = me.outNum + 1;
            if (me.outNum == 2)
            {
                me.outNum = 0;
                me.isIn = false;
                //停止
                me.swipestart = false;
                //me.move();
                if (me.index < me.max) {
                    me.reset();
                }
            }
        };
    
        /**
         * 鼠标/手指移动
         * @param event
         * @param type
         */
        SliderUnlock.prototype.handerMove = function (event, type) {
            var me = this;
            if (me.swipestart) {
                event.preventDefault();
                event = event || window.event;
                if (type == "mobile") {
                    me.index = event.originalEvent.touches[0].pageX - me.lableIndex;
                } else {
                    me.index = event.clientX - me.lableIndex;
                }
                me.move();
            }
        };
    
        /**
         * 鼠标/手指移动过程
         */
        SliderUnlock.prototype.move = function () {
            var me = this;
            if ((me.index + me.labelWidth) >= me.max) {
                me.index = me.max - me.labelWidth - 2;
                //停止
                me.swipestart = false;
                //解锁
                me.isOk = true;
            }
            if (me.index < 0) {
                me.index = me.min;
                //未解锁
                me.isOk = false;
            }
            if (me.index + me.labelWidth + 2 == me.max && me.max > 0 && me.isOk) {
                console.log("me.index + me.labelWidth + 2 == me.max && me.max > 0 && me.isOk");
                //解锁默认操作
                $('#label').unbind().next('#labelTip').
                text(me.opts.successLabelTip).css({ 'color': '#fff' });
                me.success();
            }
            me.updateView();
        };
    
    
        /**
         * 更新视图
         */
        SliderUnlock.prototype.updateView = function () {
            var me = this;
            me.sliderBg.css('width', me.index);
            me.elm.find("#label").css("left", me.index + "px")
        };
    
        /**
        * 是否验证通过
        */
        SliderUnlock.prototype.isValidateOk = function () {
            var me = this;
            return me.isOk;
        };
    
        /**
         * 重置slide的起点
         */
        SliderUnlock.prototype.reset = function () {
            var me = this;
            me.isOk = false;
            me.index = 0;
            me.sliderBg.animate({ 'width': 0 }, me.opts.duration);
            me.elm.find("#label").on("mousedown", function (event) {
                var e = event || window.event;
                me.lableIndex = e.clientX - this.offsetLeft;
                me.handerIn();
            }).on("mousemove", function (event) {
                me.handerMove(event);
            }).on("mouseup", function (event) {
                me.handerOut();
            }).on("mouseout", function (event) {
                me.handerOut();
            }).on("touchstart", function (event) {
                var e = event || window.event;
                me.lableIndex = e.originalEvent.touches[0].pageX - this.offsetLeft;
                me.handerIn();
            }).on("touchmove", function (event) {
                me.handerMove(event, "mobile");
            }).on("touchend", function (event) {
                me.handerOut();
            }).animate({ left: me.index }, me.opts.duration)
                .next("#labelTip").text(me.opts.defaultLabelTip).css({ 'color': '#787878' })
                .animate({ opacity: 1 }, me.opts.duration);
            me.updateView();
        };
    
        /**
         * 检测元素是否存在
         * @param elm
         * @returns {boolean}
         */
        SliderUnlock.prototype.checkElm = function (elm) {
            if($(elm).length > 0){
                return true;
            }else{
                throw "this element does not exist.";
            }
        };
    
        /**
         * 检测传入参数是否是function
         * @param fn
         * @returns {boolean}
         */
        SliderUnlock.prototype.checkFn = function (fn) {
            if(typeof fn === "function"){
                return true;
            } else {
                return false;
                //throw "the param is not a function.";
            }
        };
    
        window['SliderUnlock'] = SliderUnlock;
    })(jQuery, window, document);

    Css样式:

    #slider {
      margin: 10px auto;
      width: 200px;
      height: 30px;
      position: relative;
      border-radius:5px;
      background-color: #dae2d0;
      overflow: hidden;
      text-align: center;
      user-select: none;
      -moz-user-select: none;
      -webkit-user-select: none;
    }
    
    #slider_bg {
      position: absolute;
      left: 0;
      top: 0;
      height: 100%;
      background-color: #49ba43;
      z-index: 1;
    }
    
    #label {
      width: 46px;
      position: absolute;
      left: 0;
      top: 0;
      height: 29px;
      line-height: 29px;
      border-radius:5px;
      border: 1px solid #cccccc;
      background: #fff;
      z-index: 3;
      cursor: move;
      color: #ff9e77;
      font-size: 18px;
      font-weight: 900;
    }
    
    #labelTip {
      position: absolute;
      left: 0;
      width: 100%;
      height: 100%;
      font-size: 13px;
      font-family: 'Microsoft Yahei', serif;
      color: #787878;
      line-height: 30px;
      text-align: center;
      z-index: 2;
    }

    前台调用:

    <!--HTML-->
    <div id="slider">
        <div id="slider_bg"></div>
        <span id="label">>></span>
        <span id="labelTip">
            拖动滑块验证
        </span>
    </div>
    
    //JS初始化
    var slider;
    $(function () {
        slider = new SliderUnlock("#slider");
        slider.init();
    });
    
    //重置
     slider.reset();

    说实话,如上代码,还是会出现卡顿,近期尝试了如下:

    <!DOCTYPE html>
    <html>
    <head>
       <meta charset="utf-8">
       <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
       <meta http-equiv="Pragma" content="no-cache">
       <meta http-equiv="Expires" content="0">
       <meta http-equiv="X-UA-Compatible" content="IE-Edge,chrome=1">
       <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
       <meta content="yes" name="apple-mobile-web-app-capable">
       <meta content="black" name="apple-mobile-web-app-status-bar-style"> 
       <meta content="telephone=no" name="format-detection">  
       <meta content="email=no" name="format-detection"> 
       <title>拖动滑块验证</title>
       <meta name="description" content="">
       <meta name="keywords" content="">
       <link rel="stylesheet" type="text/css" href="">
       <style>
        *{ margin:0; padding:0; }
            body{ font:12px/1.125 Microsoft YaHei; background:#fff; }
            ul, li{ list-style:none; }
            a{ text-decoration:none; }
            .ani{transition:all .3s;}
            .wrap{ width:300px; height:350px; text-align:center; margin:150px auto;}
            .inner{ padding:15px; }
            .clearfix{ overflow:hidden; _zoom:1; }
            .none{ display:none; }
            #slider{position:relative;background-color:#e8e8e8;width:300px;height:34px;line-height:34px;text-align:center;}
            #slider .handler{position:absolute;top:0px;left:0px;width:40px;height:32px;border:1px solid #ccc;cursor:move;}
            .handler_bg{background:#fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTEyNTVEMURGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTEyNTVEMUNGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTc5NzNmZS02OTQxLTQyOTYtYTIwNi02NDI2YTNkOWU5YmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YiRG4AAAALFJREFUeNpi/P//PwMlgImBQkA9A+bOnfsIiBOxKcInh+yCaCDuByoswaIOpxwjciACFegBqZ1AvBSIS5OTk/8TkmNEjwWgQiUgtQuIjwAxUF3yX3xyGIEIFLwHpKyAWB+I1xGSwxULIGf9A7mQkBwTlhBXAFLHgPgqEAcTkmNCU6AL9d8WII4HOvk3ITkWJAXWUMlOoGQHmsE45ViQ2KuBuASoYC4Wf+OUYxz6mQkgwAAN9mIrUReCXgAAAABJRU5ErkJggg==") no-repeat center;}
            .handler_ok_bg{background:#fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlBRDI3NjVGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlBRDI3NjRGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDphNWEzMWNhMC1hYmViLTQxNWEtYTEwZS04Y2U5NzRlN2Q4YTEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+k+sHwwAAASZJREFUeNpi/P//PwMyKD8uZw+kUoDYEYgloMIvgHg/EM/ptHx0EFk9I8wAoEZ+IDUPiIMY8IN1QJwENOgj3ACo5gNAbMBAHLgAxA4gQ5igAnNJ0MwAVTsX7IKyY7L2UNuJAf+AmAmJ78AEDTBiwGYg5gbifCSxFCZoaBMCy4A4GOjnH0D6DpK4IxNSVIHAfSDOAeLraJrjgJp/AwPbHMhejiQnwYRmUzNQ4VQgDQqXK0ia/0I17wJiPmQNTNBEAgMlQIWiQA2vgWw7QppBekGxsAjIiEUSBNnsBDWEAY9mEFgMMgBk00E0iZtA7AHEctDQ58MRuA6wlLgGFMoMpIG1QFeGwAIxGZo8GUhIysmwQGSAZgwHaEZhICIzOaBkJkqyM0CAAQDGx279Jf50AAAAAABJRU5ErkJggg==") no-repeat center;}
            #slider .drag_bg{background-color:#7ac23c;height:34px;width:0px;}
            #slider .drag_text{position:absolute;top:0px;width:300px;-moz-user-select:none;-webkit-user-select:none;user-select:none;-o-user-select:none;-ms-user-select:none;}
            .unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;}
            .slide_ok{color:#fff;}
       </style>
    </head>
    <body>
        
        <div class="wrap">
            <div id="slider">
                <div class="drag_bg"></div>
                <div class="drag_text" onselectstart="return false;" unselectable="on">拖动滑块验证</div>
                <div class="handler handler_bg"></div>
            </div>
        </div>
        
    
       
        <script>
        (function(window,document,undefined){
           var dog = {//声明一个命名空间,或者称为对象
               $:function(id){
                  return document.querySelector(id);
               },
               on:function(el,type,handler){
                  el.addEventListener(type,handler,false);
               },
               off:function(el,type,handler){
                  el.removeEventListener(type,handler,false);
               }
           };  
           //封装一个滑块类
           function Slider(){
              var args = arguments[0];
              for(var i in args){
                  this[i] = args[i];  //一种快捷的初始化配置
              }
              //直接进行函数初始化,表示生成实例对象就会执行初始化
              this.init();
           }
           Slider.prototype = {
              constructor:Slider,
              init:function(){
                 this.getDom();
                 this.dragBar(this.handler);
              },
              getDom:function(){
                 this.slider = dog.$('#'+this.id);
                 this.handler = dog.$('.handler');
                 this.bg = dog.$('.drag_bg');
              },
              dragBar:function(handler){
                 var that = this,
                     startX = 0,
                     lastX = 0,
                     doc = document,
                     width = this.slider.offsetWidth,
                     max = width - handler.offsetWidth,
                     drag = {
                        down:function(e){
                           var e = e||window.event;
                           that.slider.classList.add('unselect');
                           startX = e.clientX - handler.offsetLeft;
                           console.log('startX: '+startX+' px');
                           dog.on(doc,'mousemove',drag.move);
                           dog.on(doc,'mouseup',drag.up);
                           return false;
                        },
                        move:function(e){
                           var e = e||window.event;
                           lastX = e.clientX - startX;
                           lastX = Math.max(0,Math.min(max,lastX)); //这一步表示距离大于0小于max,巧妙写法
                           console.log('lastX: '+lastX+' px');
                           if(lastX>=max){
                              handler.classList.add('handler_ok_bg');
                              that.slider.classList.add('slide_ok');
                              dog.off(handler,'mousedown',drag.down);
                              drag.up();
                           }
                           that.bg.style.width = lastX + 'px';
                           handler.style.left = lastX + 'px';
    
                        },
                        up:function(e){
                           var e = e||window.event;
                           that.slider.classList.remove('unselect');
                           if(lastX < width){                         
                              that.bg.classList.add('ani');
                              handler.classList.add('ani');
                              that.bg.style.width = 0;
                              handler.style.left = 0;
                              setTimeout(function(){
                                that.bg.classList.remove('ani');
                                handler.classList.remove('ani');
                              },300);
    
                           }
                           dog.off(doc,'mousemove',drag.move);
                           dog.off(doc,'mouseup',drag.up);
                        }
                     };
    
                 dog.on(handler,'mousedown',drag.down);
              }
           };
    
           window.S = window.Slider = Slider;
           
           
    
        })(window,document);
        
        var defaults = {
           id:'slider'
        };
        new S(defaults);
        </script>
    </body>
    </html>

    附:拖动轮播图片:http://www.jssor.com/demos/image-slider.slider

     

  • 相关阅读:
    UI是一个状态机
    WPF : Binding的3个属性: Source, RelativeSource, ElementName
    业务驱动设计
    WPF : 对Collection要注意重用子控件
    WPF : UserControl的Initialized事件不会触发
    mvc3上传图片
    MVC3.0自定义视图引擎(切换皮肤)
    ASP.NET MVC 多语言解决方案
    键盘键位表
    Silverlight之IsolatedStorageSettings对象
  • 原文地址:https://www.cnblogs.com/lcawen/p/6728160.html
Copyright © 2011-2022 走看看