当前位置: 首页 > news >正文

Vue 使用接口返回的背景图片和拼图图片进行滑动拼图验证

一、背景

前两天发了一篇 vue-monoplasty-slide-verify 滑动验证码插件使用及踩坑_vue-monoplasty-slide-verify 引用后不显示-CSDN博客

这两天项目又需要通过接口校验,接口返回了背景图片和拼图图片,于是在网上找了一篇帖子,vue + 图片滑动验证_基于vue图片滑动验证-CSDN博客

写的不错,代码拿过来就能用;但是感觉源码和vue-monoplasty-slide-verify的比较像,vue-monoplasty-slide-verify的icon图片拿过来直接就能在参考帖子里用。

二、获取验证码接口返回数据示例

三、校验接口返回数据示例

 

四、封装与后端配合的滑动组件

//在参考帖基础上修改的
<template><div><el-dialog :visible.sync="showSlideVerify" title="向右滑动通过验证" :width=" w +48 + 'px'" :close-on-click-modal="false" :close-on-press-escape="false"><div class="slide-verify" :style="{width: w + 'px'}" id="slideVerify" onselectstart="return false;"><!-- 图片加载遮蔽罩 --><div :class="{'slider-verify-loading': loadBlock}"></div><canvas :width="w" :height="h" ref="canvas"></canvas><div v-if="showRefresh" @click="refresh" class="slide-verify-refresh-icon"></div><canvas :width="block_width" :height="h" ref="block" class="slide-verify-block"></canvas><!-- container --><div class="slide-verify-slider" :class="{'container-active': containerActive, 'container-success': containerSuccess, 'container-fail': containerFail}"><div class="slide-verify-slider-mask" :style="{width: sliderMaskWidth}"><!-- slider --><div @mousedown="sliderDown" @touchstart="touchStartEvent" @touchmove="touchMoveEvent" @touchend="touchEndEvent" class="slide-verify-slider-mask-item" :style="{left: sliderLeft}"><div class="slide-verify-slider-mask-item-icon"></div></div></div><span class="slide-verify-slider-text">{{sliderText}}</span></div></div></el-dialog></div></template>
<script>
import { getCanvasAndPuzzle, checkPuzzle } from '@/api/modules/setting'export default {name: 'SlideVerify',props: {sliderText: {type: String,default: '向右滑动'},showRefresh: {type: Boolean,default: true}},data () {return {showSlideVerify: false,containerActive: false, // container active classcontainerSuccess: false, // container success classcontainerFail: false, // container fail classnonceStr: '',canvasCtx: null,blockCtx: null,block: null,block_src: undefined,block_y: undefined,block_width: undefined,block_height: undefined,block_radius: undefined,w: 0,h:0,img: undefined,originX: undefined,originY: undefined,isMouseDown: false,trail: [],sliderLeft: 0, // block right offsetsliderMaskWidth: 0, // mask width,success: false, // Bug Fixes 修复了验证成功后还能滑动loadBlock: true, // Features 图片加载提示,防止图片没加载完就开始验证timestamp: null}},methods: {show () {Object.assign(this.$data, {success: false,containerActive: false,containerSuccess: false,containerFail: false,nonceStr: '',w: 0,h: 0,img: undefined,loadBlock: true,block_src: undefined,block_y: undefined,block_width: undefined,block_height: undefined,block_radius: undefined,sliderLeft: 0,sliderMaskWidth: 0});this.getCanvasAndPuzzle();},getCanvasAndPuzzle () { //从接口获取滑动组件背景图片、图片宽高与拼图图片、拼图宽高、block_radius、垂直方向上的位置getCanvasAndPuzzle().then(res => {Object.assign(this.$data, {nonceStr: res.data.nonceStr, //根据接口的校验逻辑,校验时需传递给后台w: res.data.canvasWidth,h: res.data.canvasHeight,img: res.data.canvasSrc,block_src: res.data.blockSrc,block_y: res.data.blockY,block_width: res.data.blockWidth,block_height: res.data.blockHeight,block_radius: res.data.blockRadius,showSlideVerify: true});this.$nextTick(() => {this.init();});}).catch(error => {this.$message.error(error);});},init () {this.initDom();this.initImg();this.bindEvents();},initDom () {this.block = this.$refs.block;this.canvasCtx = this.$refs.canvas.getContext('2d');this.blockCtx = this.block.getContext('2d');},initImg () {let _this = this, image = new Image(), blockImage = new Image();image.src = this.img;blockImage.src = this.block_src;image.onload = () => {_this.canvasCtx.drawImage(image, 0, 0, _this.w, _this.h);};blockImage.onload = () => {_this.loadBlock = false;// 第二个、三个参数分别是被拖动的拼图在水平、垂直方向的偏移量_this.blockCtx.drawImage(blockImage, 0, _this.block_y, _this.block_width, _this.block_height);};},sliderDown (event) {if (this.success) return;this.originX = event.clientX;this.originY = event.clientY;this.isMouseDown = true;this.timestamp = + new Date();},touchStartEvent (e) {if (this.success) return;this.originX = e.changedTouches[0].pageX;this.originY = e.changedTouches[0].pageY;this.isMouseDown = true;this.timestamp = + new Date();},bindEvents () {document.addEventListener('mousemove', (e) => {if (!this.isMouseDown) return false;const moveX = e.clientX - this.originX;const moveY = e.clientY - this.originY;if (moveX < 0 || moveX + 38 >= this.w) return false;this.sliderLeft = moveX + 'px';let blockLeft = (this.w - 40 - 20) / (this.w - 40) * moveX;this.block.style.left = blockLeft + 'px';this.containerActive = true;this.sliderMaskWidth = moveX + 'px';this.trail.push(moveY);});document.addEventListener('mouseup', (e) => {if (!this.isMouseDown) return false;this.isMouseDown = false;if (e.clientX === this.originX) return false;this.containerActive = false;this.timestamp = + new Date() - this.timestamp;this.verify();});},touchMoveEvent (e) {if (!this.isMouseDown) return false;const moveX = e.changedTouches[0].pageX - this.originX;const moveY = e.changedTouches[0].pageY - this.originY;if (moveX < 0 || moveX + 38 >= this.w) return false;this.sliderLeft = moveX + 'px';let blockLeft = (this.w - 40 - 20) / (this.w - 40) * moveX;this.block.style.left = blockLeft + 'px';this.containerActive = true;this.sliderMaskWidth = moveX + 'px';this.trail.push(moveY);},touchEndEvent (e) {if (!this.isMouseDown) return false;this.isMouseDown = false;if (e.changedTouches[0].pageX === this.originX) return false;this.containerActive = false;this.timestamp = + new Date() - this.timestamp;this.verify();},verify () {
//将拼图水平方向拖动量传递给接口,接口来校验是否拼好返回校验结果,我也不是很理解这个操作,但没办法,就让这样做,只能自己网上找例子,然后改出来了checkPuzzle({nonceStr: this.nonceStr,value: parseInt(this.block.style.left) //被拖动拼图在水平方向上的移动量}).then(res => {if(res.code===-1 || !res.data) {//校验通过,res.data的值为true,否则为falsethis.containerFail = true;this.$message.error(res.message);this.refresh();} else {this.$emit('verify-success');Object.assign(this.$data, {containerSuccess: true,success: true,showSlideVerify: false});}}).catch(error => {this.$message.error(error);});},refresh () {let { w, h, block_width } = this;this.canvasCtx.clearRect(0, 0, w, h);this.blockCtx.clearRect(0, 0, block_width, h);this.block.style.left = 0;Object.assign(this.$data, {success: false,containerActive: false,containerSuccess: false,containerFail: false,nonceStr: '',img: undefined,loadBlock: true,sliderLeft: 0,sliderMaskWidth: 0});this.getCanvasAndPuzzle();}}
}
</script>
<style scoped>
.slide-verify {position: relative;
}/* 图片加载样式 */
.slider-verify-loading {position: absolute;top: 0;right: 0;left: 0;bottom: 0;background: rgba(255, 255, 255, 0.9);z-index: 999;animation: loading 1.5s infinite;
}@keyframes loading {0% {opacity: 0.7;}100% {opacity: 9;}
}.slide-verify-block {position: absolute;left: 0;top: 0;
}.slide-verify-refresh-icon {position: absolute;right: 0;top: 0;width: 34px;height: 34px;cursor: pointer;background: url('./imgs/icon.png') 0 -437px;background-size: 34px 471px;
}.slide-verify-slider {position: relative;text-align: center;width: 100%;height: 40px;line-height: 40px;/* margin-top: 15px; */background: #f7f9fa;color: #45494c;border: 1px solid #e4e7eb;
}.slide-verify-slider-mask {position: absolute;left: 0;top: 0;height: 40px;border: 0 solid #1991fa;background: #d1e9fe;
}.slide-verify-slider-mask-item {position: absolute;top: 0;left: 0;width: 40px;height: 40px;background: #fff;box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);cursor: pointer;transition: background 0.2s linear;
}.slide-verify-slider-mask-item:hover {background: #1991fa;
}.slide-verify-slider-mask-item:hover .slide-verify-slider-mask-item-icon {background-position: 0 -13px;
}.slide-verify-slider-mask-item-icon {position: absolute;top: 15px;left: 13px;width: 14px;height: 12px;background: url('./imgs/icon.png') 0 -26px;background-size: 34px 471px;
}
.container-active .slide-verify-slider-mask-item {height: 38px;top: -1px;border: 1px solid #1991fa;
}.container-active .slide-verify-slider-mask {height: 38px;border-width: 1px;
}.container-success .slide-verify-slider-mask-item {height: 38px;top: -1px;border: 1px solid #52ccba;background-color: #52ccba !important;
}.container-success .slide-verify-slider-mask {height: 38px;border: 1px solid #52ccba;background-color: #d2f4ef;
}.container-success .slide-verify-slider-mask-item-icon {background-position: 0 0 !important;
}.container-fail .slide-verify-slider-mask-item {height: 38px;top: -1px;border: 1px solid #f57a7a;background-color: #f57a7a !important;
}.container-fail .slide-verify-slider-mask {height: 38px;border: 1px solid #f57a7a;background-color: #fce1e1;
}.container-fail .slide-verify-slider-mask-item-icon {top: 14px;background-position: 0 -82px !important;
}.container-active .slide-verify-slider-text,
.container-success .slide-verify-slider-text,
.container-fail .slide-verify-slider-text {display: none;
}
</style>

五、 接口

意义不太大,要根据项目实际情况来的

 六、CSS 代码里用到的图片资源

https://download.csdn.net/download/hrcsdn13/89709217

七、CSS与组件文件位置

八、效果图

相关文章:

Vue 使用接口返回的背景图片和拼图图片进行滑动拼图验证

一、背景 前两天发了一篇 vue-monoplasty-slide-verify 滑动验证码插件使用及踩坑_vue-monoplasty-slide-verify 引用后不显示-CSDN博客 这两天项目又需要通过接口校验&#xff0c;接口返回了背景图片和拼图图片&#xff0c;于是在网上找了一篇帖子&#xff0c;vue 图片滑动…...

1-7 掩膜的运用 opencv树莓派4B 入门系列笔记

目录 一、提前准备 二、代码详解 num_pixels np.sum(mask 255) contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) c max(contours, keycv2.contourArea) x, y, w, h cv2.boundingRect(c) M cv2.moments(contours[0]) if contours…...

EG边缘计算网关连接华为云物联网平台(MQTT协议)

需求概述 实现一个流程&#xff1a;EG8200mini采集Modbus RTU数据&#xff0c;通过MQTT协议连接华为云物联网平台 Modbus RTU采集此处不做过多赘述&#xff0c;可参考其他案例&#xff08;串口读取Modbus传感器数据&#xff09;介绍。下文默认已经采集到Modbus RTU数据。 要…...

List中常见的方法和五种遍历方式

有序&#xff1a;存取的顺序一致 有索引&#xff1a;可以通过索引操作元素 可重复&#xff1a;存储的元素可以重复 package mylist;import java.util.ArrayList; import java.util.List;public class A01_LIstDemo1 {public static void main(String[] args) {List<String…...

华为 HCIP-Datacom H12-821 题库 (8)

有需要题库的可以看主页置顶 1.在 DHCP 运行过程中&#xff0c;如果客户端 IP 地址在相约过去 87.5%还没有完成续约的话&#xff0c;客户将发送什么报文进行再次续约&#xff1f; A、DHCP discover 广播报文 B、DHCP release 单播报文 C、DHCP request 广播报文 D、DHCP reques…...

12. GIS地图制图工程师岗位职责、技术要求和常见面试题

本系列文章目录&#xff1a; 1. GIS开发工程师岗位职责、技术要求和常见面试题 2. GIS数据工程师岗位职责、技术要求和常见面试题 3. GIS后端工程师岗位职责、技术要求和常见面试题 4. GIS前端工程师岗位职责、技术要求和常见面试题 5. GIS工程师岗位职责、技术要求和常见面试…...

ORACLE 统计信息的备份与恢复

备份 --需要先创建统计信息基础表 exec dbms_stats.create_stat_table(USER1,STAT_TIMESTAMP); --导出某个用户的所有统计信息 exec dbms_stats.export_schema_stats(USER1,STAT_TIMESTAMP);--测试(插入100条&#xff0c;更新统计信息&#xff0c;略) select num_rows,last_ana…...

2. GIS数据工程师岗位职责、技术要求和常见面试题

本系列文章目录&#xff1a; 1. GIS开发工程师岗位职责、技术要求和常见面试题 2. GIS数据工程师岗位职责、技术要求和常见面试题 3. GIS后端工程师岗位职责、技术要求和常见面试题 4. GIS前端工程师岗位职责、技术要求和常见面试题 5. GIS工程师岗位职责、技术要求和常见面试…...

Spark MLlib模型训练—文本算法 LDA(Latent Dirichlet Allocation)

Spark MLlib模型训练—文本算法 LDA(Latent Dirichlet Allocation) Latent Dirichlet Allocation(LDA)是一种用于主题建模的生成式概率模型,广泛应用于文本分析和自然语言处理。LDA 的目标是从一组文档中发现潜在的主题,并将每个文档表示为这些主题的概率分布。它通过推断…...

C++ ─── List的模拟实现

目录 ​编辑 一&#xff0c; List的模拟实现 二&#xff0c;代码实现 三、list和vector的区别 一&#xff0c; List的模拟实现 List 是一个双向循环链表,由于List的节点不连续&#xff0c;不能用节点指针直接作为迭代器&#xff0c;因此我们要对结点指针封装&#xff0c;来…...

Spring Boot详解

好的&#xff01;Spring Boot 是一个基于 Spring 框架的项目&#xff0c;它为简化配置、快速启动项目而生。它使得构建独立运行、生产级别的 Spring 应用变得非常简单&#xff0c;让开发者专注于业务逻辑而不再被繁琐的配置所困扰。接下来&#xff0c;我将从以下几个方面为你详…...

Proxfier+burpsuite抓包配置问题

1、burp证书配置 导出证书 后缀为cer 打开浏览器设置 搜索证书--》点安全 管理证书 在圈起来的三个地方添加证书 2、Proxifer配置 配置代理服务器 配置ip和port 配置代理规则 注意画圈部分...

sqli-lab靶场学习(一)——Less1-4

前言 最近一段时间想切入安全领域&#xff0c;因为本身有做数据库运维工作&#xff0c;就打算从sql注入方向切入。而sql注入除了学习日常书本上的概念外&#xff0c;需要有个实践的环境&#xff0c;刚好看到sqli-lab这个靶场&#xff0c;就打算先用这个来学习。 安装部署 网上…...

el-select如何同时获取value和label?

在element ui 中 下拉框默认获取下拉框value的值&#xff0c;但是有时候根据 业务需求&#xff0c;我们需要label值也发送给后端&#xff0c;在这提供一下获取value、和label 的方式 1、在给el-option绑定:value值时使用对象的方式&#xff0c;将value和label同时绑定到:value…...

1.初识ChatGPT:AI聊天机器人的革命(1/10)

引言 在当今的数字化世界中&#xff0c;人工智能&#xff08;AI&#xff09;正以其独特的方式重塑我们的生活和工作。其中&#xff0c;AI聊天机器人作为人机交互的前沿技术&#xff0c;已经成为企业与客户沟通、提供个性化服务的重要工具。这些机器人通过模拟人类的对话方式&a…...

API安全 | 发现API的5个小tips

在安全测试目标时&#xff0c;最有趣的测试部分是它的 API。API 是动态的&#xff0c;它们比应用程序的其他部分更新得更频繁&#xff0c;并且负责许多后端繁重的工作。在现代应用程序中&#xff0c;我们通常会看到 REST API&#xff0c;但也会看到其他形式&#xff0c;例如 Gr…...

数据结构---单向链表

单向链表 //链表的创建 Link_t *create_link() {Link_t *plink malloc(sizeof(Link_t));if(NULL plink){perror("fail plink");return NULL;}plink->phead NULL;plink->clen 0;return plink; } //头插 int push_link_head(Link_t *plink, DataType data…...

基于STM32设计的ECG+PPG人体参数测量系统(华为云IOT)(217)

文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】整体构架【3】上位机开发思路【4】ESP8266工作模式配置1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要【5】项目背景1.4 开发…...

SpringBoot教程(十五) | SpringBoot集成RabbitMq(死信队列、延迟队列)

SpringBoot教程&#xff08;十五&#xff09; | SpringBoot集成RabbitMq&#xff08;死信队列、延迟队列&#xff09; &#xff08;一&#xff09;死信队列使用场景具体用法前提示例: &#xff08;二&#xff09;延迟队列使用场景方法一&#xff1a;通过死亡队列实现方法二&…...

Dubbo依赖包

Dubbo 是一个高性能的 RPC 框架&#xff0c;用于构建分布式服务治理系统。要使用 Dubbo&#xff0c;项目中需要引入一些关键的依赖包。这些依赖包提供了 Dubbo 的核心功能、服务注册与发现、网络通信、序列化等能力。 一、Dubbo 核心依赖包 Dubbo 的核心依赖包包含了实现 RPC…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...