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与组件文件位置

八、效果图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/418895.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安卓玩机工具------小米工具箱扩展工具 小米机型功能拓展

小米工具箱扩展版 小米工具箱扩展版 iO_Box_Mi_Ext是由晨钟酱开发的一款适用于小米&#xff08;MIUI&#xff09;、多亲&#xff08;2、2Pro&#xff09;、多看&#xff08;多看电纸书&#xff09;的多功能工具箱。该工具所有功能均可以免root实现&#xff0c;使用前&…

2024/9/6黑马头条跟学笔记(三)

D3 内容介绍 jdk8新特性&#xff0c;stream流&#xff0c;lambda表达式 ​ 自媒体前后端搭建 步骤 sql—— 实体—— 微服务拷贝&#xff0c;配置nacos—— spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.233.136:3306/leadnews_…

基于Spring Boot的火车订票管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JAVA语言 Spring Boot框架 工具&#xff1a;IDEA/Eclipse、Navicat、Tomcat 系统展示 首页 管理…

Android Jetpact Lifecycle 解析

认识 Lifecycle Lifecycle 是什么 Lifecycle 是 Jetpack 组件库中的一个生命周期感知型组件。在 Lifecycle 出现之前&#xff0c;需要手动从外部宿主&#xff08;如 Activity、Fragment 或自定义宿主&#xff09;中将生命周期事件分发到功能组件内部&#xff0c;这势必会造成…

SAM 2:分割图像和视频中的任何内容

文章目录 摘要1 引言2 相关工作3 任务&#xff1a;可提示视觉分割4 模型5 数据5.1 数据引擎5.2 SA-V数据集 6 零样本实验6.1 视频任务6.1.1 提示视频分割6.1.2 半监督视频对象分割6.1.3 公平性评估 6.2 图像任务 7 与半监督VOS的最新技术的比较8 数据和模型消融8.1 数据消融8.2…

RT-Thread(Nano版本)的快速移植(基于NUCLEO-F446RE)

目录 概述 1 RT-Thread 1.1 RT-Thread的版本 1.2 认识Nano版本 2 STM32F446U上移植RT-Thread 2.1 STM32Cube创建工程 2.2 移植RT-Thread 2.2.1 安装RT-Thread Packet 2.2.2 加载RT-Thread 2.2.3 匹配相关接口 2.2.3.1 初次编译代码 2.2.3.2 匹配端口 2.2.4 移植FinSH…

时间同步服务

多主机协作工作时&#xff0c;各个主机的时间同步很重要&#xff0c;时间不一致会造成很多重要应用的故障&#xff0c;如&#xff1a;加密协 议&#xff0c;日志&#xff0c;集群等。 利用NTP&#xff08;Network Time Protocol&#xff09; 协议使网络中的各个计算机时间达到…

OceanBase 4.x 存储引擎解析:如何让历史库场景成本降低50%+

据国际数据公司&#xff08;IDC&#xff09;的报告显示&#xff0c;预计到2025年&#xff0c;全球范围内每天将产生高达180ZB的庞大数据量&#xff0c;这一趋势预示着企业将面临着更加严峻的海量数据处理挑战。随着数据日渐庞大&#xff0c;一些存储系统会出现诸如存储空间扩展…

AF透明模式/虚拟网线模式组网部署

透明模式组网 实验拓扑 防火墙基本配置 接口配置 eth1 eth3 放通策略 1. 内网用户上班时间&#xff08;9:00-17:00&#xff09;不允许看视频、玩游戏及网上购物&#xff0c;其余时 间访问互联网不受限制&#xff1b;&#xff08;20 分&#xff09; 应用控制策略 2. 互联…

IBM Storwize V7000存储控制器故障节点报错574

背景&#xff1a;由于客户机房搬迁&#xff0c;需要下电迁移设备。该存储自2016年投入生产使用后&#xff0c;从未关过机&#xff0c;已正常运行七八年时间&#xff0c;期间只更换过硬盘&#xff0c;无其他硬件故障。 在GUI界面点击关闭系统后&#xff0c;大概等了40分钟&…

说一下解除docker限制内存警告

有时候docker要对容器使用的内存做出限制&#xff0c;通常的做法是使用参数 -m 例如&#xff1a; docker run -m 512M表示容器内存最大不能超过512M。 但这样做&#xff0c;在ubuntu会看到以下警告 WARNING: Your kernel does not support swap limit capabilitiesdocker官方…

从监控到智能:EasyCVR视频汇聚平台助力加油站安全监管升级转型

随着科技的不断进步&#xff0c;视频监控技术在各个行业的应用日益广泛&#xff0c;尤其在加油站这一关键领域&#xff0c;视频智能监管系统的应用显得尤为重要。TSINGSEE青犀视频EasyCVR视频汇聚平台作为一款基于“云-边-端”一体化架构的视频融合与AI智能分析平台&#xff0c…

JAVA读写Excel(jxl,poi,easyExcel)

目录 一、需求描述 二、具体操作Excel的常用方法 方法一&#xff1a; 使用jxl 方法二&#xff1a; POI 方法三&#xff1a;EasyExcel 三、总结 一、需求描述 前端有时候会传送 Excel 文件给后端&#xff08;Java&#xff09;去解析&#xff0c;那我们作为后端该如何实现…

Jenkins+Svn+Vue自动化构建部署前端项目(保姆级图文教程)

目录 介绍 准备工作 配置jenkins 构建部署任务 常见问题 介绍 在平常开发前端vue项目时,我们通常需要将vue项目进行打包构建,将打包好的dist目录下的静态文件上传到服务器上,但是这种繁琐的操作是比较浪费时间的,可以使用jenkins进行自动化构建部署前端vue 准备工作 准备…

AI模型的未来之路:全能与专精的博弈与共生

人工智能(AI)领域正迅速发展,伴随着技术的不断进步,AI模型的应用范围也在不断扩展。当前,AI模型的设计和使用面临两个主要趋势:全能型模型和专精型模型。这两者之间的博弈与共生将塑造未来的AI技术格局。本文将从以下七个方面探讨AI模型的未来之路,并提供实用的代码示例…

ROS1 + Realsense d455 固件安装+读取rostopic数据

目录 安装固件&#xff08;一定要匹配&#xff09;ROS1 wrapper 安装方法Realsense SDK 安装方法Realsense Firmware 安装方法 修改roslaunch配置文件&#xff0c;打开双目图像和IMU数据其他坑点参考链接 安装固件&#xff08;一定要匹配&#xff09; 如果你是使用ROS1获取rea…

Python数据分析-绘制图表

示例1&#xff1a; from pyecharts.charts import Bar # 柱状图 from pyecharts import options as optsfrom pyecharts.render import make_snapshotbar Bar() bar.add_xaxis([一月, 二月, 三月, 四月, 五月]) bar.add_yaxis("销售额", [10, 20, 15, 25, 30])# 配…

安卓framework单屏幕Display秒双/多屏互动相关需求改进-wms实战开发

背景 前面已经给学员朋友们分享过单屏秒变双屏的成果展示&#xff0c;具体详情可以点击这里&#xff1a; https://mp.weixin.qq.com/s/KdYTLMuXiBdjM0kZmYKzPg 一些vip学员朋友也纷纷求助马哥的实现patch代码&#xff0c;想用于公司的实战项目实现。但是在公司需求实现要求和…

Python(TensorFlow)和MATLAB及Java光学像差导图

&#x1f3af;要点 几何光线和波前像差计算入瞳和出瞳及近轴光学计算波前像差特征矩阵方法计算光谱反射率、透射率和吸光度透镜像差和绘制三阶光线像差图和横向剪切干涉图分析瞳孔平面焦平面和大气湍流建模神经网络光学像差计算透镜光线传播几何偏差计算像差和像散色差纠正对齐…

八、Maven总结

1.为什么要学习Maven&#xff1f; 2.Maven 也可以配华为云和腾讯云等。 3.IDEA整合Maven 4.IDEA基于Maven进行工程的构建 5.基于Maven进行依赖管理&#xff08;重点&#xff09; 6. Maven的依赖传递和依赖冲突 7. Maven工程继承和聚合 8.仓库及查找顺序