js+canvas实现滑动拼图验证码功能


Posted in Javascript onMarch 26, 2018

js+canvas实现滑动拼图验证码功能 

上图为网易云盾的滑动拼图验证码,其应该有一个专门的图片库,裁剪的位置是固定的。我的想法是,随机生成图片,随机生成位置,再用canvas裁剪出滑块和背景图。下面介绍具体步骤。

首先随便找一张图片渲染到canvas上,这里#canvas作为画布,#block作为裁剪出来的小滑块。

<canvas width="310" height="155" id="canvas"></canvas>
<canvas width="310" height="155" id="block"></canvas>
var canvas = document.getElementById('canvas')
 var block = document.getElementById('block')
 var canvas_ctx = canvas.getContext('2d')
 var block_ctx = block.getContext('2d')
 var img = document.createElement('img')
 img.onload = function() {
  canvas_ctx.drawImage(img, 0, 0, 310, 155)
  block_ctx.drawImage(img, 0, 0, 310, 155)
 };
 img.src = 'img.jpg'

js+canvas实现滑动拼图验证码功能 

下面考虑如何裁剪出拼图的形状,拼图形状比较复杂,首先我们画一个正方形,接着上边的代码写:

var x = 150, y = 40, w = 42, r = 10, PI = Math.PI 
 function draw(ctx) {
  ctx.beginPath()
  ctx.moveTo(x, y)
  ctx.lineTo(x + w, y)
  ctx.lineTo(x + w, y + w)
  ctx.lineTo(x, y + w)
  ctx.clip()
 }
 draw(canvas_ctx)
 draw(block_ctx)

x,y为正方形左上角的坐标,现在先随便写后边生成的时候用随机数,w为正方形的边长,r为后边画缺口的圆的半径。我们先把绘图过程用函数封装起来,方便后面同时操作背景和滑块。用clip()方法裁剪图片后生成一个正方形。

js+canvas实现滑动拼图验证码功能 

接下来画正方形上边和右边的圆形:

function draw(ctx) {
  ctx.beginPath()
  ctx.moveTo(x,y)
+  ctx.lineTo(x+w/2,y)
+  ctx.arc(x+w/2,y-r+2, r,0,2*PI) //
+  ctx.lineTo(x+w/2,y)
  ctx.lineTo(x+w,y)
+  ctx.lineTo(x+w,y+w/2)
+  ctx.arc(x+w+r-2,y+w/2,r,0,2*PI) //
+  ctx.lineTo(x+w,y+w/2)
  ctx.lineTo(x+w,y+w)
  ctx.lineTo(x,y+w)
  ctx.lineTo(x,y)
  ctx.clip()
 }

js+canvas实现滑动拼图验证码功能 

两处注释的位置将圆心往内偏移了2px,实现缺口的样式。然后是左边空心的部分,由于clip是裁剪路径内的部分,因此直接像上面画圆是不行的,我们开启一条新的路径,然后画圆将这个正方形“遮盖”出一个缺口,这里会用到 globalCompositeOperation 属性,'xor'顾名思义。代码接上边:

function draw(ctx) {
  ctx.beginPath()
  ...
  ctx.lineTo(x,y)
  ctx.clip()
+  ctx.beginPath()
+  ctx.arc(x,y+w/2, r,1.5*PI,0.5*PI) // 只需要画正方形内的半圆就行,方便背景图片的裁剪
+  ctx.globalCompositeOperation = "xor"
+  ctx.fill()
}

js+canvas实现滑动拼图验证码功能 

现在一个基本的拼图形状有了,我们调整#block的大小,并将裁剪出来的滑块放入#block中:

img.onload = function() {
  ctx.drawImage(img, 0, 0, 310, 155)
  block_ctx.drawImage(img, 0, 0, 310, 155)
+  var blockWidth = w + r * 2
+  var _y = y - r * 2 + 2 // 滑块实际的y坐标
+  var ImageData = block_ctx.getImageData(x, _y, blockWidth, blockWidth)
+  block.width = blockWidth
+  block_ctx.putImageData(ImageData, 0, _y)
 }

js+canvas实现滑动拼图验证码功能 

现在我们需要把左边画布展示原来的图片,并且抠掉中间滑块的部分,这里画路径的过程都是一样的,唯一不同只是clip()那里改成fill()即可实现效果,我们前面已经把画路径的过程封装成函数了,稍作改动即可:

- function draw(ctx) {
+ function draw(ctx, operation) {
  ...
- ctx.clip()
+ ctx.fillStyle = '#fff'
+ ctx[operation]()
  ...
}
+ draw(canvas_ctx, 'fill')
+ draw(block_ctx, 'clip')

js+canvas实现滑动拼图验证码功能 

接下来就是写样式了,略过:

js+canvas实现滑动拼图验证码功能 

然后就是写拖动事件,我们可以在鼠标按下时记录鼠标位置,然后在拖动时给滑块设置left值。最后在松开鼠标时,判断滑块此时的left值和最开始裁剪滑块时的x值,如果在一定范围内就算验证通过,否则验证失败。

最后再加上随机图片和随机剪切位置,基本就ok了。另外可以判断下鼠标移动时y轴的变化,以判断是否是“人”在操作,当然web安全这块神魔乱舞的,我就不班门弄斧了,只是做个简单判断就行。

由于没有给切片边缘加上边框或者阴影,导致某些图片的滑块可识别度不高,需要后边完善下(其实是我还没折腾出来- -),希望懂这块的大神帮我完善下//

js+canvas实现滑动拼图验证码功能 

后边代码比较杂乱,就不贴上来了, 查看完整代码点这里 演示地址 点这里

总结

以上所述是小编给大家介绍的js+canvas实现滑动拼图验证码功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
用Javascript数组处理多个字符串的连接问题
Aug 20 Javascript
清空上传控件input file的值
Jul 03 Javascript
window.open关于浏览器拦截问题分析及解决方法
Feb 05 Javascript
解析使用JS 清空File控件的路径值
Jul 08 Javascript
使用Script元素发送JSONP请求的方法
Jun 12 Javascript
微信小程序实现多个按钮toggle功能的实例
Jun 13 Javascript
vue-cli中安装方法(图文详细步骤)
Dec 12 Javascript
ES6中字符串的使用方法扩展
Jun 04 Javascript
layui点击按钮页面会自动刷新的解决方案
Oct 25 Javascript
浅谈webpack和webpack-cli模块源码分析
Jan 19 Javascript
京东优选小程序的实现代码示例
Feb 25 Javascript
JS高级程序设计之class继承重点详解
Jul 07 Javascript
JS从非数组对象转数组的方法小结
Mar 26 #Javascript
深入理解Node module模块
Mar 26 #Javascript
利用Console来Debug的10个高级技巧汇总
Mar 26 #Javascript
关于vuejs中v-if和v-show的区别及v-show不起作用问题
Mar 26 #Javascript
vue中使用iview自定义验证关键词输入框问题及解决方法
Mar 26 #Javascript
Vue中v-show添加表达式的问题(判断是否显示)
Mar 26 #Javascript
使用Vue构建可重用的分页组件
Mar 26 #Javascript
You might like
php中用memcached实现页面防刷新功能
2014/08/19 PHP
php简单实现多字节字符串翻转的方法
2015/03/31 PHP
php输出全球各个时区列表的方法
2015/03/31 PHP
php实现在服务器端调整图片大小的方法
2015/06/16 PHP
反射调用private方法实践(php、java)
2015/12/21 PHP
php mysql PDO 查询操作的实例详解
2017/09/23 PHP
PHP实现用session来实现记录用户登陆信息
2018/10/15 PHP
学习JS面向对象成果 借国庆发布个最新作品与大家交流
2009/10/03 Javascript
js操作textarea方法集合封装(兼容IE,firefox)
2011/02/22 Javascript
JSCode all of Brower 全局屏蔽网页右键功能 具体实现
2013/06/05 Javascript
jQuery EasyUI中的日期控件DateBox修改方法
2016/11/09 Javascript
解决jQuery使用append添加的元素事件无效的问题
2018/08/30 jQuery
vue3.0 CLI - 2.4 - 新组件 Forms.vue 中学习表单
2018/09/14 Javascript
JavaScript实现的联动菜单特效示例
2019/07/08 Javascript
Vue的click事件防抖和节流处理详解
2019/11/13 Javascript
vue项目使用高德地图的定位及关键字搜索功能的实例代码(踩坑经验)
2020/03/07 Javascript
JS自定义右键菜单实现代码解析
2020/07/16 Javascript
探究一道价值25k的蚂蚁金服异步串行面试题
2020/08/21 Javascript
多个Vue项目部署到服务器的步骤记录
2020/10/22 Javascript
vue实现动态给id赋值,点击事件获取当前点击的元素的id操作
2020/11/09 Javascript
30分钟搭建Python的Flask框架并在上面编写第一个应用
2015/03/30 Python
使用Python判断质数(素数)的简单方法讲解
2016/05/05 Python
Django中的CBV和FBV示例介绍
2018/02/25 Python
对python sklearn one-hot编码详解
2018/07/10 Python
Python判断对象是否为文件对象(file object)的三种方法示例
2019/04/26 Python
浅谈CSS3 动画卡顿解决方案
2019/01/02 HTML / CSS
The Kooples美国官方网站:为情侣提供的法国当代时尚品牌
2019/01/03 全球购物
Douglas意大利官网:购买香水和化妆品
2020/05/27 全球购物
某/etc/fstab文件中的某行如下: /dev/had5 /mnt/dosdata msdos defaults,usrquota 1 2 请解释其含义
2013/04/11 面试题
大学校园活动策划书
2014/02/04 职场文书
2015年大学社团工作总结
2015/04/09 职场文书
居住证明范文
2015/06/17 职场文书
忆童年!用Python实现愤怒的小鸟游戏
2021/06/07 Python
Redis缓存-序列化对象存储乱码问题的解决
2021/06/21 Redis
详解TypeScript的基础类型
2022/02/18 Javascript
SQL Server删除表中的重复数据
2022/05/25 SQL Server