canvas模拟妙味课堂拖动验证码

很久没写博客了,很紧张,很忐忑。

其实一直记挂着,也总想发点什么,不是没有内容说,当然时间也不是最主要的原因,就像某位博友所说时间就像乳沟,挤一挤,总会有的,归根结底,一个字,懒!相比之前自己确实懒了很多,在工作了一天回到家,就不想再碰电脑了,更别说写点代码。

当然懒是最根本的原因,其他原因也是有的。主要吧,我觉得虽然是工作笔记,但是至少也要能给来我博客的博友带去一些东西吧,所以发的东西要有价值,而且至少要有一个demo吧,加上自己的文笔不太好,经常是写好了一个demo,懒得去写描述,但是直接放代码似乎又不太好,想好了描述吧,又懒得去写demo,然后就这样不了了之了。

好了,扯了这么多,进入正题吧,今天我写的是一个用canvas来模拟妙味课堂验证码的小东西,其实之前也有用canvas写过12306坑爹的图片验证码(点击这里穿越),原理其实都差不多,写这个东西,完全就是一时兴起。最近我从同事那边知道了妙味课堂这个网站,之前只知道慕课网,极客学院。我发现妙味确实做的比慕课和极客学院好,这个上面的教程讲的很细腻,这算不算打广告,我去又扯远了[流汗] 。 今天看他在那里看妙味的验证码,确实还挺好看的,然后就模仿着用canvas写了一个,原理就不讲了,真的很简单,直接贴代码了,上次12306图片验证码的代码被人吐槽了,确实写的很不规范,而且有bug,毕竟本人水平还是很有限,几个小时写出的代码,我不敢保证没有bug。这个代码个人觉得写的也是稀烂,仅仅是抛砖引玉,希望能帮助博友在此基础上做出更好的东西。

;(function(window, document, undefined) {
  const vCode = (function() {
    var bgPath = 'images/bg/',
        bgCount = 8,
        codeHeight = 70,
        codeBarWidth = 69,
        codeBarHeight = 56,
        codeBarTop = (codeHeight - codeBarHeight) / 2,
        el, code;
    var init = function(selector) {
      el = document.querySelector(selector);
      mkCode();
    }
    var refreshCode = function() {
      clearCode();
      mkCode();
    }
    var mkCode = function() {
      var bgCanvas = createElement('canvas'),
          bgCtx = bgCanvas.getContext('2d'),
          bg = getRandomBg(),
          im = new Image();
      im.onload = function() {
        bgCanvas.width = this.width;
        bgCanvas.height = this.height;
        bgCtx.drawImage(im, 0, 0);
        var codeBarLeft = rand(codeBarWidth+10, this.width-codeBarWidth),
            imgData = bgCtx.getImageData(codeBarLeft, codeBarTop, codeBarWidth, codeBarHeight);
        code = codeBarLeft;
        mkCodeBar(imgData, function(data, img) {
          var barCanvas = createElement('canvas'),
              ctx = barCanvas.getContext('2d');
          barCanvas.width = data.width;
          barCanvas.height = data.height;
          ctx.putImageData(data, 0, 0);
          var im = new Image();
          barCanvas.className = 'bar';
          barCanvas.style.top = codeBarTop + 'px';
          im.src = 'images/code-1.png';
          im.onload = function() {
            ctx.drawImage(im, 0, 0);
            el.appendChild(barCanvas);
          }
          bgCtx.globalAlpha = 0.7;
          bgCtx.drawImage(img, codeBarLeft, codeBarTop, codeBarWidth, codeBarHeight);
          attachEvents(bgCanvas, barCanvas);
        });
      }
      im.src = bg;
      el.appendChild(bgCanvas);
    }
    var mkCodeBar = function(imgData, callback) {
      var canvas = createElement('canvas'),
          ctx = canvas.getContext('2d'),
          im = new Image();
      im.src = 'images/code.png';
      im.onload = function() {
        canvas.width = this.width;
        canvas.height = this.height;
        ctx.drawImage(im, 0, 0);
        var iData = ctx.getImageData(0, 0, this.width, this.height);
        for (var i=0; i< iData.width * iData.height; i++) {
          var r = iData.data[i*4],
              g = iData.data[i*4+1],
              b = iData.data[i*4+2],
              a = iData.data[i*4+3];
          if (r ===0 && g === 0 && b===0 && a===0) {
            imgData.data[i*4+3] = 0;
          }
        }
        callback && callback(imgData, im);
      }
    }
    var attachEvents = function(bg, node) {
      bg.onclick = function() {
        refreshCode();
      }
      node.onmousedown = function(event) {
        var disX = event.pageX - node.offsetLeft, vcode;
        document.onmousemove = function(e) {
          var event = e || window.event;
          vcode = Math.floor(event.pageX - disX);
          css(node, {
            left: vcode + 'px'
          });
        }
        document.onmouseup = function() {
          if (check(vcode)) {
            alert('验证成功!');
            refreshCode();
          } else {
            startMove(node, {
              left: 0
            });
          }
          document.onmousemove = null;
          document.onmouseup = null;
        }
      }
    }
    var check = function(vcode) {
      return Math.abs(code-vcode)<=3; } var css = function(node, css) { for (var index in css) { if (css.hasOwnProperty(index)) { node.style[index] = css[index]; } } } var clearCode = function() { el.innerHTML = ''; } var createElement = function(tagName) { return document.createElement(tagName); } var getRandomBg = function() { var index = Math.floor(Math.random() * (bgCount - 1)) + 1; return bgPath + index + '.png'; } var rand = function(min, max) { return Math.floor(Math.random() * (max-min) + min); } var startMove = function(obj, json) { var iCur = 0, iSpeed = 0; clearInterval(obj.timer); obj.timer = setInterval(function() { var iBtn = true; for (var attr in json) { var iTarget = json[attr]; if (attr === 'opacity') { iCur = Math.round(getStyle(obj, 'opacity') * 100); } else { iCur = parseInt(getStyle(obj, attr)); } if (iCur != iTarget) { iBtn = false; iSpeed = (iTarget - iCur) / 8; if (iSpeed>0) {
              iSpeed = Math.ceil(iSpeed);
            } else {
              iSpeed = Math.floor(iSpeed);
            }
            if (attr === 'opacity') {
                obj.style.opacity = (iCur + iSpeed) / 100;
                obj.style.filter = 'opacity(opacity=' + (iCur + iSpeed) + ')';
            } else {
              obj.style[attr] = iCur + iSpeed + 'px'
            }
          }
        }
        if (iBtn) {
          clearInterval(obj.timer);
        }
      }, 16);
    }
    var getStyle = function(node, attr) {
      if (node.currentStyle) {
        return node.currentStyle[attr];
      } else {
        return getComputedStyle(node, false)[attr];
      }
    }
    return {
      init: init,
      refreshCode: refreshCode
    };
  })();
  window.vCode = vCode;
})(window, document);

猛戳这里查看实例

  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章