js 滑动拼图验证码

0.834字数 626阅读 4341

以前的验证码很简单,就是一个带些背景色或背景图和干扰线的纯数字字母类的验证码,现在已经发展变得很丰富了。我见过的就有好几种:纯字母数字类,数学计算类,依次点击图片上的文字类,从下列图片列表里选取符合描述的图片类,拼图验证码类。鉴于,本人要使用拼图验证码类,故介绍一下自己的调查使用情况。

我们先看看2种类型的滑动拼图验证码:


py-code-rect.png
py-code-polygon.png
  • 第一种:拼图是简单的矩形。 这种方式可以用css(background-size和background-position)实现抠图的ui部分。你可以此插件,还不错。兼容ie9及以上。
  • 第二种:拼图是不规则图形。 这种方式,就没法直接用css实现抠图部分了,得用canvas来做。可以参考此插件

我是需要第二种,大致记录以下本人使用过程碰到的问题和最后的解决方式。
此插件的github源码地址:https://github.com/yeild/jigsaw,demo页面地址:https://yeild.github.io/jigsaw/src/demo.html

兼容性

此插件不兼容IE浏览器。查看项目源码,发现js使用了不少es6的新语法。
然后用Babel转了一下,发现还是有不兼容IE的方法。
比如Object.assign方法。为了兼容,补上以下代码:

// 不支持assign方法的兼容写法
        if (typeof Object.assign != 'function') {
              // Must be writable: true, enumerable: false, configurable: true
              Object.defineProperty(Object, "assign", {
                value: function assign(target, varArgs) { // .length of function is 2
                  'use strict';
                  if (target == null) { // TypeError if undefined or null
                    throw new TypeError('Cannot convert undefined or null to object');
                  }

                  var to = Object(target);

                  for (var index = 1; index < arguments.length; index++) {
                    var nextSource = arguments[index];

                    if (nextSource != null) { // Skip over if undefined or null
                      for (var nextKey in nextSource) {
                        // Avoid bugs when hasOwnProperty is shadowed
                        if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                          to[nextKey] = nextSource[nextKey];
                        }
                      }
                    }
                  }
                  return to;
                },
                writable: true,
                configurable: true
              });
            }

又比如:element.classList的相关的方法addremove
想兼容,请补上:

//不支持element.classList方法的兼容写法(ie10及以下)
    if (!("classList" in document.documentElement)) {
        Object.defineProperty(HTMLElement.prototype, 'classList', {
            get: function() {
                var self = this;
                function update(fn) {
                    return function(value) {
                        var classes = self.className.split(/\s+/g),
                            index = classes.indexOf(value);

                        fn(classes, index, value);
                        self.className = classes.join(" ");
                    }
                }

                return {
                    add: update(function(classes, index, value) {
                        if (!~index) classes.push(value);
                    }),

                    remove: update(function(classes, index) {
                        if (~index) classes.splice(index, 1);
                    }),

                    toggle: update(function(classes, index, value) {
                        if (~index)
                            classes.splice(index, 1);
                        else
                            classes.push(value);
                    }),

                    contains: function(value) {
                        return !!~self.className.split(/\s+/g).indexOf(value);
                    },

                    item: function(i) {
                        return self.className.split(/\s+/g)[i] || null;
                    }
                };
            }
        });
    }

还有,当使用canvas相关相关getImageData和putImageData做抠图的代码出来时,在IE9和IE10有个图片文件跨域问题(报错:SecurityError)。
第一种解决方式:图片文件跟项目方一起就不存在跨域问题了。第二种就是不适用getImageData和putImageData方法。用其他实现方式代替,见下面带代码:

//getImageData方法和putImageData方法在IE9和IE10上,涉及到文件路径的跨域访问问题。
          //   console.log('(x:'+_this.x+',y:'+_this.y+')');
          if(navigator.userAgent.indexOf("MSIE") > -1){
            _this.block.style.marginLeft = '-'+(_this.x-3)+'px';//不抵边,空3px
          }else{
            var ImageData = _this.blockCtx.getImageData(_this.x - 3, y, L, L);
            _this.block.width = L;
            _this.blockCtx.putImageData(ImageData, 0, y);
          }

还有,在IE中,在canvas上绘图有顺序步骤的。如果在IE中出现下图抠图区未绘制成功,请调整代码顺序。


py-code-error1.png

解决方式:


py-code-sx.png

最终调整完后的demo,见js实现滑动拼图验证码

另外,提供2种三方的现成的调用api:极验腾讯防水墙

推荐阅读更多精彩内容