图片滑块验证功能很难吗?做个可以自己扣形状的图片滑块验证组件

说在前面

在当今数字化世界中,网络安全和用户验证变得至关重要。随着恶意机器人和自动化攻击的增加,传统的验证码系统已经不再足够保障网站的安全性。为了提高用户体验和防止恶意攻击,图片滑块验证成为了一个热门的选择。今天,我们一起来实现一个可以自己扣形状的图片滑块验证组件

效果展示

体验地址

jyeontu.xyz/jvuewheel/#...

实现步骤

一、使用canvas展示背景图片

首先我们应该先了解一下怎么在canvas上绘制图片:

  • 1.获取Canvas元素和2D上下文:首先获取到需要绘制图片的Canvas元素,并从中获取2D上下文(Context)。可以使用以下代码获取Canvas元素和2D上下文:
javascript 复制代码
const canvas = document.getElementById('myCanvas'); // 获取Canvas元素
const ctx = canvas.getContext('2d'); // 获取2D上下文
  • 2.创建Image对象并设置src:创建一个Image对象,然后设置其src属性为要绘制的图片的URL。确保图片加载完成后再进行绘制操作。
javascript 复制代码
const image = new Image();
image.onload = function() {
  // 在图片加载完成后进行绘制操作
};
image.src = 'path_to_your_image.jpg'; // 设置图片路径
  • 3.绘制图片,在图片加载完成后,可以使用ctx.drawImage()方法在Canvas上绘制图片。
javascript 复制代码
image.onload = function() {
  ctx.drawImage(image, x, y, width, height); // 在Canvas上绘制图片
};

在上面的代码中,x和y表示图片在Canvas上的起始坐标,width和height表示图片的宽度和高度。

二、背景图片抠出滑块缺口

1、获取到canvas元素和2D上下文ctx

javascript 复制代码
const canvas = this.$refs.canvas;
const ctx = canvas.getContext("2d");

2、创建一个image对象,将图片绘制到canvas上

在图片加载完成后,函数设置了图片的宽度和高度,并将canvas的宽度和高度设置为与图片相同,然后通过ctx.drawImage()方法绘制图片。

javascript 复制代码
const image = new Image();
image.onload = () => {
    image.width = parseInt(this.width);
    image.height = parseInt(this.height);
    canvas.width = image.width;
    canvas.height = image.height;
    // 绘制图片
    ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
};
image.src = this.imgSrc;

3、根据抠图路径,将区域镂空

这里的镂空区域我们可以设置为透明,也可以填充上我们自己喜欢的颜色。

javascript 复制代码
// 创建镂空区域的路径
this.cutImg(ctx, this.cutPath, image, canvas);
// 在路径内部清除像素
if (this.fillStyle) {
    ctx.fillStyle = this.fillStyle; // 设置填充颜色
} else {
    ctx.globalCompositeOperation = "destination-out";
}
ctx.fill();
resolve();

然后我们就可以得到这么一张图片

三、抠出一个滑块图片

前面我们生成了一张扣出了滑块缺口的图片,那么我们还需要一张图片可以来填充这个缺口,所以我们需要再抠出一张图片

1、获取到canvas元素和2D上下文ctx

javascript 复制代码
const canvas = this.$refs.canvas2;
const ctx = canvas.getContext("2d");

2、创建一个image对象,将图片绘制到canvas上

在图片加载完成后,函数设置了图片的宽度和高度,并将canvas的宽度和高度设置为与图片相同。

javascript 复制代码
const image = new Image();
image.onload = () => {
    image.width = parseInt(this.width);
    image.height = parseInt(this.height);
    canvas.width = image.width;
    canvas.height = image.height;
    ......
};
image.src = this.imgSrc;

3、根据抠图路径,抠出指定区域图片

创建了一个剪切路径,如果定义了strokeStyle属性,则设置绘制路径的颜色,然后用ctx.stroke()方法绘制路径。接着,使用ctx.clip()方法将当前路径设置为剪切路径。这意味着后续绘制的所有内容都将被剪切成路径内部的形状。

最后,使用ctx.drawImage()方法将图片绘制到Canvas上。

javascript 复制代码
// 定义剪切路径
this.cutImg(ctx, this.cutPath, image, canvas);
if (this.strokeStyle) {
    ctx.strokeStyle = this.strokeStyle;
}
ctx.stroke();
ctx.clip();

// 绘制图片
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
resolve();

然后我们就可以得到这么一张图片

四、滑动条控制滑块滑动

1、图块跟随滑动条滑动

  • 初始滑动回调 使用startSliding来标记是否初始滑动,是初始滑动时执行start回调。

  • 滑动位置计算 滑动条滑动距离 = 图片总宽度 * 当前滑动比例;

  • 控制图片滑块不滑出图片区域

我们假设背景图片的宽度为width,滑块最左边的x坐标为minX,最右端的X坐标为maxX,那么滑块的最大宽度则为maxX - minX,则滑块的可滑动范围应该是[0,widht - maxX + minX],如下图:

这样想那你就错了,滑块整个的大小其实是和原图片一样的,如下图:

所以其移动范围的计算方式应该是这样的:

还是假设背景图片的宽度为width,滑块最左边的x坐标为minX,最右端的X坐标为maxX,那么滑块的最大宽度则为maxX - minX,则滑块的可滑动范围应该是:[-minX,width - maxX],如下图:

javascript 复制代码
onSliderChange(sliderValue) {
    if (!this.startSliding) {
        this.startSliding = true;
        this.$emit("start");
    }
    const left = parseInt(this.width) * (sliderValue / 100);
    this.startLeft = Math.min(
        parseInt(this.originLeft) + parseInt(left),
        parseInt(this.width) - this.sliderInfo.maxX
    );
}

2、判断滑块结束位置是否通过

滑块和缺口完全重合的时候,滑块滑动的距离应该是0,这里我们设置一个误差属性passDiff,默认为3px,最后判断滑块滑动的距离是否在误差范围里即可,具体代码如下:

javascript 复制代码
confirmSlider() {
    if (Math.abs(this.startLeft) <= this.passDiff) {
        this.$JToast("验证通过");
    } else if (this.failedText) {
        this.$JToast(this.failedText);
    }
    setTimeout(() => {
        this.init();
    }, 1000);
    this.startSliding = false;
    this.$emit("end", Math.abs(this.startLeft) <= this.passDiff);
}

五、更换自己喜欢的滑块形状

1、抠图工具

默认的滑块形状是下面这样的:

如果你不喜欢的话也可以换成自己喜欢的形状,前面我分享过一篇文章《使用canvas实现一个锚点抠图功能》,看过这篇文章的同学可能记得我在里面留了一个坑,现在就把它填上,我们可以利用这个工具来获取到我们自定义的滑块形状路径:

工具地址:jyeontu.xyz/JDemo/#/img...

如上图,我们现在的滑块形状也是通过这个工具获取到的,我们也可以做成下面这些样子的:

总之就是想要什么形状都可以自己抠出来,当然,喜欢直接算坐标的直接算也可以

2、注意

抠图注意将宽高设置为与组件宽高一致,不然滑块大小可能会和你想象中的不一样

源码地址

gitee

gitee.com/zheng_yongt...

公众号

关注公众号『前端也能这么有趣』发送 组件库即可获取源码。

组件使用

目前该组件库已经发布到npm,除了图片滑块验证之外还有其他许多好玩的组件,后续会继续维护,源码也已经开源,感兴趣的朋友可以瞧瞧,觉得有点意思的可以顺手点个star

组件文档:jyeontu.xyz/jvuewheel/#...

组件仓库:gitee.com/zheng_yongt...

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax