纯js+cavans实现图片滑块验证,兼容移动端和pc端(兼容到ie9),完美干货!

js已封装好,拿来即用,兼容pc端和移动端,

效果:

移动端 

 

pc端:

原理就不解释了,我之前的博客已经说过,只不过这个版本是结合了canvas实现,又兼容了pc端,直接拿代码就能用了,如果觉得不错就给个赞呗!😀

html代码:

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
 
 
        .sliderModel {
            position: fixed;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            display: none;
         
        }
        .sliderModel .cont{padding: 20px; width: 280px; background: #fff;border-radius: 6px;margin: 50px auto;}
        .showMessage {
            text-align: center;
            font-size: 14px;
            height: 30px;
            line-height: 30px;
            /*避免活动的过程中选择文字*/
            -moz-user-select:none;
            -webkit-user-select:none;
            user-select:none;   
        }
       
        #canvas_wrap{
            width: 280px;
        }
        #canvas_wrap canvas{
            display: block; 
        }
 
    </style>
</head>
 
<body>
  <div class="sliderModel">
      <div class="cont">
         <div id="canvas_wrap"></div>
         <div class="showMessage"></div>
      </div>
      <div id="close">关闭</div>
   </div>
   <div id="open">打开</div>
</body>
<script src="newSlider.js"></script>
<script>
    function showMessage(msg,color){
        var showMessage = document.querySelector('.showMessage');
        showMessage.innerHTML=msg;
        showMessage.style.color=color;
    }
    var obj={
        el:'#canvas_wrap',
        w:280,
        h:150,
        imgArr:['images/sliderz/1.jpg','images/sliderz/2.jpg','images/sliderz/3.jpg','images/sliderz/4.jpg'],
        sliderIcon:'images/sliderz/sangangy.png',
        refresh:function(){
            showMessage('','#333')
        },
        finish:function(e){     
            e? showMessage('验证成功!','green') : showMessage('验证失败,请重试','red');
        }
    }
    
 
   document.querySelector('#open').onclick=function(){ //打开
    document.querySelector('.sliderModel').style.display="block";
    new window.$newSlider(obj);
 
   }
    
   document.querySelector('#close').onclick=function(){ //关闭
       document.querySelector('.sliderModel').style.display="none";
   }
</script>
 
</html>


newSlider.js:

(function(){
    function slider(params){
        var obj={
            el:params.el,
            w:params.w || 280, //canvas的宽度
            h:params.h || 150,  //canvas的高度
            range:params.range || 5, //相差多少像素内触发成功
            imgArr:params.imgArr || [], //图片数组
            sliderW:36, //slider的边长
            sliderIcon:params.sliderIcon || '',
            refresh:params.refresh, //刷新回调
            finish:params.finish , //完成回调
 
        };
 
           //创建canvas的父元素
           var container=document.querySelector(obj.el);
           container.innerHTML='';
           var canvas_wrap=document.createElement('div');
           canvas_wrap.className="canvas_wrap";
           canvas_wrap.style.cssText="position:relative;overflow:hidden;border-radius:4px;width:"+obj.w+"px;height:"+obj.h+"px;background:#fff"
       //创建大小canvas元素
           var bigCanvas=document.createElement('canvas');
           var smartCanvas=bigCanvas.cloneNode(true);
           bigCanvas.width=smartCanvas.width=obj.w;
           bigCanvas.height=smartCanvas.height=obj.h;
           bigCanvas.style.cssText=smartCanvas.style.cssText="position:absolute;left:0;top:0";
           var bcxt=bigCanvas.getContext('2d'),scxt=smartCanvas.getContext('2d'),img=new Image();
       //创建标题和刷新按钮
          var titleDom=document.createElement('div');
          var refreshDom=document.createElement('div');
          titleDom.className="slider_title";
          refreshDom.className="slider_refresh";
          titleDom.style.cssText="position:relative;width:"+obj.w+"+px;height:60px;text-align:center;font-size:18px; line-height:60px";
          refreshDom.style.cssText="position:absolute;top:0;right:14px;font-size:14px;color:green;cursor: pointer";
          titleDom.innerHTML="图形验证";
          refreshDom.innerHTML="刷新";
 
       //创建拖拽区域
         var slider_wrap=document.createElement('div'),slider=document.createElement('div'),sliderCover=document.createElement('div');
           slider_wrap.className="slider_wrap";
           slider.className="canvas_slider";
           sliderCover.className="sliderCover";
           slider_wrap.innerText="拖动左边滑块完成上方拼图";
           slider_wrap.style.cssText="width:"+obj.w+"px;height:30px; border-radius:30px;line-height:30px; position:relative;margin-top:10px;text-align:center;box-shadow: inset 0 0 4px #ccc;font-size: 14px;color:#999";
           slider.style.cssText="cursor: pointer;position: absolute;left: 0;top: 50%;z-index: 2;height: "+obj.sliderW+"px;width: "+obj.sliderW+"px;background:rgb(0, 124, 255) url("+obj.sliderIcon+") no-repeat center;background-size: 60% 60%;border-radius: "+obj.sliderW+"px;line-height:"+obj.sliderW+"px;text-align:center;transform: translateY(-50%);";
           sliderCover.style.cssText="position: absolute;left: 0;top:0;width:0;height:100%;background:#eee;border-radius:30px;"
          
           slider_wrap.appendChild(slider);
           slider_wrap.appendChild(sliderCover);
           canvas_wrap.appendChild(bigCanvas);
           canvas_wrap.appendChild(smartCanvas);
           titleDom.appendChild(refreshDom);
           container.appendChild(titleDom);
           container.appendChild(canvas_wrap);
           container.appendChild(slider_wrap);
       
        
        var canvasCoverL=0,startDownX=0,smartCanvasBL=0,sliderMaxRange=obj.w-obj.sliderW;  
        /*
        canvasCoverL:随机生成占位块canvas的x轴位置
        startDownX://鼠标按下时x轴位置
        smartCanvasBL: 可移动canvas的left初始值
        sliderMaxRange:slider可移动的最大距离
        */
 
        //生成canvas图案
        function creatCanvas(){
            //重置初始值
            canvasCoverL=0;startDownX=0;smartCanvasBL=0;  
            slider.style.left = sliderCover.style.width = 0;
 
            var l= 40, //滑块的正方形边长,不包括小圆点
            r = 10,   //小圆点半径
            PI = Math.PI,
            sliderW=l+2*r, //滑块边长
            rand=canvasSize(sliderW,r), //获取随机生成的x,y,left值
            x = canvasCoverL= rand.x,  //占位块x轴
            y = rand.y;  //占位块y轴
            
            smartCanvasBL=rand.left;
            //先清空画布
            bcxt.clearRect(0, 0, obj.w, obj.h)
            scxt.clearRect(0, 0, obj.w, obj.h)
            smartCanvas.width=obj.w;
 
            var srcIndex=Math.floor(Math.random()*(obj.imgArr.length-1));
            img.src=obj.imgArr[srcIndex];
            draw(scxt,x,y,l,r,PI,'clip');
            draw(bcxt,x,y,l,r,PI,'fill');
            img.onload = function() { //一定要在onload里调用,否则canvas里不能放进图片
                bcxt.drawImage(img,0,0,obj.w,obj.h);
                scxt.drawImage(img,0,0,obj.w,obj.h);
                //裁剪滑块长度
                var ImageData = scxt.getImageData(x, y-2*r, sliderW, sliderW)
                smartCanvas.width = sliderW;
                smartCanvas.style.left=rand.left+"px";
                scxt.putImageData(ImageData, 0, y-2*r)
            } 
            obj.refresh && obj.refresh();
        }
 
        //随机生成canvas滑块和占位块,到左边的距离和到顶部的距离
        function canvasSize(cw,r){
           // cw为占位块和的宽度,r为绘制圆点的半径
           var random =Math.random();
           var x=Math.floor(obj.w/2 + random*(obj.w/2 - cw)); //x为占位块x坐标位置,保证占位块始终在画布的右半区域
           var y=Math.floor(r*2+random*(obj.h - cw - r*2)); //y为占位块y坐标位置,(值至少为小圆半径的2倍才能完全显示,因为绘制的原点是小正方形的左上角)
           var left =Math.floor(random*(obj.w/2 - cw)); //canvas滑块的left值,这里的值范围保证它始终在画布的左半区域
           return {x:x,y:y,left:left}
        }
 
        //绘制canvas滑块和占位块
        function draw(ctx,x,y,l,r,PI,operation) {
            ctx.beginPath()
                ctx.moveTo(x, y)
                ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI)
                ctx.lineTo(x + l, y)
                ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI)
                ctx.lineTo(x + l, y + l)
                ctx.lineTo(x, y + l)
                ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true)
                ctx.lineTo(x, y)
                ctx.lineWidth = 1
                ctx.fillStyle = 'rgba(200, 200, 200, 1)'
                ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'
                ctx.stroke()
                ctx[operation]()
                ctx.globalCompositeOperation = 'destination-over'
          }
        
 
        
 
        //滑块被按下
        function moveStart(e){
            var ev = e || window.event;
            startDownX = ev.touches!=undefined?  ev.touches[0].clientX : ev.clientX; 
            // 解决开始滑动时文字被选中的bug
            document.onselectstart = function() { return false; }; 
        }
        //滑块移动
        function moveProcess(e){
            var ev = e || window.event,downX = (ev.touches!=undefined)?  ev.touches[0].clientX : (startDownX!=0? ev.clientX : 0),range=downX-startDownX;
          console.log(downX)
            var sliderRange= range<=0? 0 : (range<sliderMaxRange ? range : sliderMaxRange);
            slider.style.left=sliderRange+"px";
            sliderCover.style.width=obj.sliderW/2 + sliderRange +"px";
            smartCanvas.style.left=smartCanvasBL+sliderRange+"px";
        }
 
        //停止滑动
        function moveEnd(e){
            document.ontouchmove = null;
            document.onmousemove = null;
            document.onselectstart = null;
            var ev = e || window.event;
            var smartCanvasL= parseInt(smartCanvas.style.left);
            if(Math.abs(canvasCoverL - smartCanvasL) < obj.range){
                obj.finish && obj.finish(true);
            }else{
                obj.finish && obj.finish(false);
                var timer = null,step = 10;
                var sliderL = parseInt(slider.style.left)
                timer = setInterval(function () {
                    sliderL -= step;
                    step += 5;
                    if (sliderL <= 0) {
                        clearInterval(timer);
                        sliderL = 0;
                        slider.style.left = sliderCover.style.width = 0;
                        smartCanvas.style.left = smartCanvasBL + "px"
                    }
                    slider.style.left =  sliderL + "px";
                    sliderCover.style.width = sliderL+obj.sliderW/2 +"px";
                    smartCanvas.style.left = sliderL + smartCanvasBL+ "px";
                }, 20)
            }
 
        }
        
        
       //事件调用
        creatCanvas();
        refreshDom.onclick=refreshDom.ontouchstart=creatCanvas;
        slider.ontouchstart=function(){
            moveStart();
            document.ontouchmove=moveProcess;
            document.ontouchend=moveEnd;
        };
        slider.onmousedown=function(){
            moveStart();
            document.onmousemove=moveProcess;
            document.onmouseup=moveEnd;
        };
       
    }
 
    window.$newSlider=slider
})()


落魄前端-小陈
0
0
0
评论
浏览
收藏