JavaScript与Canvas实现滑动拼图验证码的完整流程

作者:像素猫

时间:2026-10-22

浏览:500

本文详细介绍如何使用JavaScript结合Canvas API实现滑动拼图验证码。通过随机生成图片与位置,利用clip()和globalCompositeOperation属性绘制复杂的拼图形状,并处理滑块裁剪与背景还原。最后通过监听鼠标拖动事件判断验证结果,提供了一套完整的前端验证码实现方案。

文章目录

滑动拼图验证码实现概述 

滑动拼图验证码实现概述

如上图所示,这是网易云盾的滑动拼图验证码示例。该机制通常依赖一个专门维护的图片库,且裁剪位置是固定的。我的实现思路是:随机生成图片资源,随机确定裁剪坐标,然后利用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'

滑动拼图验证码实现概述 

绘制正方形基础形状

接下来考虑如何裁剪出拼图的形状。由于拼图形状较为复杂,我们先绘制一个正方形,具体代码实现如下:


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()方法裁剪图片后,即可生成一个正方形区域。

滑动拼图验证码实现概述 

绘制拼图缺口形状

随后,在正方形的上边和右边绘制圆形:


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()
 }

滑动拼图验证码实现概述 

代码中两处注释位置将圆心向内偏移了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()
}

滑动拼图验证码实现概述 

生成滑块与背景处理

此时,一个基本的拼图形状已经生成。我们需要调整#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)
 }

滑动拼图验证码实现概述 

现在,我们需要在左侧画布上展示原始图片,并抠除中间滑块的部分。路径绘制过程与之前相同,唯一的区别是将clip()改为fill()即可实现效果。由于我们已将画路径的过程封装为函数,只需稍作改动即可:


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

滑动拼图验证码实现概述 

接下来编写CSS样式部分,此处省略具体代码。

滑动拼图验证码实现概述 

拖动事件与验证逻辑

随后处理拖动事件。我们可以在鼠标按下时记录初始位置,在拖动过程中动态设置滑块的left值。当鼠标松开时,判断滑块当前的left值与最初裁剪滑块时的x值是否在一定误差范围内。若在范围内,则验证通过;否则验证失败。

最后,加入随机图片和随机剪切位置的逻辑,基本功能即可完成。此外,还可以判断鼠标移动时y轴的变化,以此辅助判断是否为“人”在操作。当然,Web安全领域技术复杂多变,此处仅作简单判断,不做深入探讨。

由于未给切片边缘添加边框或阴影,导致部分图片的滑块可识别度不高,后续需要完善(目前尚未找到最佳方案)。希望熟悉此领域的大神能协助完善。

滑动拼图验证码实现概述 

后续代码较为杂乱,此处不再赘述。查看完整代码请点击这里,演示地址请点击这里。

总结

以上介绍了利用JS和Canvas实现滑动拼图验证码的功能,希望对大家有所帮助。如有任何疑问,请留言,小编会及时回复。在此感谢大家对本站的支持!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章