vue开发H5 实现滑动图片获取验证码

在这里插入图片描述

<template>
  <div>
    <van-button type="primary" @click="sendVerification">获取验证码</van-button>
    <van-popup
      v-model="captchaVisible"
      closeable
      position="bottom"
      class="login-captcha"
      :close-on-click-overlay="false"
      safe-area-inset-bottom
    >
      <div class="login-captcha-title">拖动下方滑块完成验证</div>
      <div class="login-captcha-main">
        <img alt="网络错误" ref="shade" class="login-captcha-shade" />
        <img alt="网络错误" ref="puzzle" class="login-captcha-puzzle" />
        <div class="login-captcha-refresh" @click="getCaptchaPuzzle"></div>
      </div>
      <van-slider
        class="login-captcha-slider"
        active-color="transparent"
        v-model="slider"
        @change="getVerification"
      >
        <template #button>
          <div class="login-captcha-slider__button"></div>
        </template>
      </van-slider>
    </van-popup>
  </div>
</template>

<script>
import { getCaptchaPuzzle, getVerification } from '@/api/utils'

export default {
  data() {
    return {
      captchaVisible: false,
      // 滑块位置 和 滑块图
      captchaPuzzle: {
        x: 0,
        y: 0,
        shadeImageUrl: '',
        cutoutImageUrl: '',
      },
      loginForm: {
        mobile: '13333333333',
      },
      slider: 13,
      puzzleLeft: 0,
    }
  },
  watch: {
    slider(val) {
      const max = (1 - this.$refs.puzzle.width / this.$refs.shade.width) * 100
      const slope = max / 74
      this.puzzleLeft = Math.min(Math.max(0, slope * (val - 13)), max)
      this.$refs.puzzle.style.left = this.puzzleLeft + '%'
    },
    captchaVisible(val) {
      if (val) {
        this.$nextTick(() => {
          this.calcPuzzle()
        })
      }
    },
  },
  methods: {
    sendVerification() {
      this.getCaptchaPuzzle().then((val) => {
        if (val) {
          this.captchaVisible = true
        }
      })
    },
    getVerification() {
      const { mobile } = this.loginForm
      const { y } = this.captchaPuzzle
      const x = ((this.puzzleLeft / 100) * this.$refs.shade.naturalWidth).toFixed(0)
      getVerification({
        Mobile: mobile,
        X: x,
        Y: y + '',
      })
        .then(({ data: res }) => {
          if (res.code !== '0') {
            this.$toast(res.msg || '验证码发送失败,请重试')
            this.slider = 13
            this.getCaptchaPuzzle()
          } else {
            this.$toast('短信验证已发送')
            this.slider = 13
            this.captchaVisible = false
          }
        })
        .catch((err) => {
          if (err) {
            this.$toast('系统或网络异常')
            this.slider = 13
            this.getCaptchaPuzzle()
          }
        })
    },
    async getCaptchaPuzzle() {
      const { mobile } = this.loginForm
      return getCaptchaPuzzle({
        Mobile: mobile,
      })
        .then((data) => {
          const res = data.data
          if (res.code !== '0') {
            this.$toast(res.msg || '系统或网络异常')
            return false
          }
          this.captchaPuzzle = res.data
          if (this.captchaVisible) {
            this.calcPuzzle()
          } else {
            this.captchaVisible = false
          }
          return true
        })
        .catch((err) => {
          if (err) {
            this.$toast('系统或网络异常')
          }
          return false
        })
    },
    async calcPuzzle() {
      const { x, y } = this.captchaPuzzle,
        shade = this.$refs.shade,
        puzzle = this.$refs.puzzle
      await this.loadImage(shade, this.captchaPuzzle.shadeImageUrl)
      puzzle.style.top = (((y + 1) / shade.naturalHeight) * 100).toFixed(6) + '%'
      await this.loadImage(puzzle, this.captchaPuzzle.cutoutImageUrl)
      puzzle.style.left = x + 'px'
    },
    async loadImage(img, url) {
      return new Promise((resolve, reject) => {
        img.onload = () => resolve(img)
        img.onerror = reject
        img.src = url
      })
    },
  },
}
</script>

<style lang="less" scoped>
.login {
  &-captcha {
    height: 408px;
    text-align: center;
    padding: 0 24px;
    box-sizing: border-box;
    border-radius: 20px 20px 0px 0px;

    &-title {
      height: 28px;
      font-size: 20px;
      font-weight: 600;
      color: #292b2e;
      line-height: 28px;
      padding: 32px 0 20px;
    }
    &-main {
      width: 327px;
      margin: 0 auto;
      border-radius: 8px;
      position: relative;
      overflow: hidden;
    }
    &-shade {
      display: block;
      width: 100%;
    }
    &-puzzle {
      position: absolute;
      width: 50px;
    }
    &-refresh {
      position: absolute;
      top: 6px;
      right: 12px;
      width: 24px;
      height: 24px;
      background: url('../../assets/images/icon_login_refresh.png');
    }
    &-slider {
      display: inline-block;
      margin-top: 32px;
      width: 290px;
      height: 52px;
      background: rgba(188, 191, 200, 0.3);
      border-radius: 27px;
      pointer-events: none;

      &::before {
        // 向右滑动验证;
        content: '\5411\53f3\6ed1\52a8\9a8c\8bc1';
        font-size: 16px;
        line-height: 52px + 8px + 8px;
        color: #8b91a0;
      }
      .van-slider__bar {
        min-width: 13%;
        max-width: 87%;
      }
      .van-slider__button-wrapper {
        pointer-events: auto;
      }
      &__button {
        pointer-events: auto;
        width: 61px;
        height: 44px;
        background-size: cover !important;
        background: url('../../assets/images/btn_verify.png');
      }
    }
  }
}
</style>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java接入Apache Spark(入门环境搭建、常见问题)

Java接入Apache Spark&#xff08;环境搭建、常见问题&#xff09; 背景介绍 Apache Spark 是一个快速的&#xff0c;通用的集群计算系统。它对 Java&#xff0c;Scala&#xff0c;Python 和 R 提供了的高层 API&#xff0c;并有一个经优化的支持通用执行图计算的引擎。它还支…

腾讯云服务器建站教程——2024更新部署网站教程

使用腾讯云服务器搭建网站全流程&#xff0c;包括轻量应用服务器和云服务器CVM建站教程&#xff0c;轻量可以使用应用镜像一键建站&#xff0c;云服务器CVM可以通过安装宝塔面板的方式来搭建网站&#xff0c;腾讯云服务器网txyfwq.com分享使用腾讯云服务器建站教程&#xff0c;…

UCB Data100:数据科学的原理和技巧:第二十一章到第二十六章

二十一、SQL II 原文&#xff1a;SQL II 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 学习成果 介绍过滤组的能力 在 SQL 中执行数据清理和文本操作 跨表连接数据 在本讲座中&#xff0c;我们将继续上次的工作&#xff0c;介绍一些高级的 SQL 语法。 首先&…

【kafka】记录用-----------1

主题&#xff08;topic&#xff09;&#xff1a;消息的第一次分类 根据人为的划分条件将消息分成不同的主题 主题的划分是人为的根据不同的任务情景去划分 比如&#xff0c;我们有两个主题&#xff0c;一个是"订单"&#xff0c;另一个是"库存"。每个主题代…

eureka-server项目工程搭建、linux集群部署

Eureka是Netflix开发的服务发现框架&#xff0c;本身是一个基于REST的服务&#xff0c;主要用于定位运行在AWS域中的中间层服务&#xff0c;以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中&#xff0c;以实现SpringCloud的服…

与纸质合同相比,电子合同有哪些优势?

在无纸化办公的当下&#xff0c;电子合同软件成为了企业数字化转型必不可少的工具。而随着国内电子合同软件功能的完善&#xff0c;电子合同拥有便捷&#xff0c;安全&#xff0c;功能等要素&#xff0c;因此&#xff0c;电子合同是更多人的选择方式。 电子合同指的是双方或者多…

antd时间选择器,设置显示中文

需求 在实现react&#xff0c;里面引入antd时间选择器&#xff0c;默认显示为英文 思路 入口处使用ConfigProvider全局化配置&#xff0c;设置 locale 属性为中文来实现。官方文档介绍全局化配置 ConfigProvider - Ant Design 代码 import React from react; import { Prov…

Shutter Encoder多媒体转换v17.8

软件介绍 多媒体包含种类繁多的各种文件格式&#xff0c;每种格式都有其不同的特征和所谓的“怪癖”。 因此&#xff0c;如果使用多种图像、视频或音频格式&#xff0c;找到一个集中的软件来从一个地方处理所有这些格式可能会非常棘手。 这就是 Shutter Encoder 基本上允许做的…

Git的安装

1、下载 官网地址&#xff1a; https://git-scm.com/或https://github.com/git-for-windows/git/releases 百度网盘链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/13_asGO-XQb5KWWH_V7rq6g?pwd0630 2、安装 ①查看GNU协议&#xff0c;可以直接点击下一步。 ②…

加速 Android Studio 依赖项下载

在某些网络环境中&#xff0c;访问互联网可能受到限制&#xff0c;在Android Studio中&#xff0c;项目构建时可能需要下载依赖项&#xff0c;如果网络受到限制&#xff0c;就无法下载或下载速度非常慢只有十几 kb/s &#xff0c;设置可以帮助解决下载问题。 进入设置页面找到…

HTTP数据请求

文章目录 1 概述2 什么是HTTP3 如何发起HTTP请求4 参考链接 1 概述 日常生活中我们使用应用程序看新闻、发送消息等&#xff0c;都需要连接到互联网&#xff0c;从服务端获取数据。例如&#xff0c;新闻应用可以从新闻服务器中获取最新的热点新闻&#xff0c;从而给用户打造更…

vivado ip manager cache

https://china.xilinx.com/video/hardware/configuring-managing-reusable-ip-vivado.html “Core Containers”&#xff08;核容器&#xff09;&#xff1a;勾选Use Core Containers for IP&#xff08;为 IP 使用核容器&#xff09;即可使用核容器功能&#xff0c;该功能支持…

基于SSM+vue的新生报到服务管理系统(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

【Linux实用篇】Linux软件安装 JDK Tomcat MySQL lrzsz

1. 软件安装 1.1 软件安装方式 在Linux系统中&#xff0c;安装软件的方式主要有四种&#xff0c;这四种安装方式的特点如下&#xff1a; 安装方式特点二进制发布包安装软件已经针对具体平台编译打包发布&#xff0c;只要解压&#xff0c;修改配置即可rpm安装软件已经按照red…

Gitlab Gitee GitHub 远程仓库显示图片

大家好我是苏麟 , 今天出一期开发之外的如何在远程仓库展示图片 . 以GitLab为例 1.首先我们要把一张图片上传到远程仓库 . 2.第二步,点击图片 3.鼠标右键点击下载左键点击复制连接 4.找到我们要上传的md文件 , 把连接复制到 ( ) 里 , 这样上传md之后就可以看到图片了 . 这期就到…

Python学习从0到1 day2 python注释

那就祝我们 all is well ——24.1.12 一、python中的注释 1.注释的作用 注释代码与非注释代码对比&#xff0c;可以发现&#xff0c;添加了注释的代码更加易于程序的阅读 2.注释的分类及方法 注释在python中有两种形式&#xff1a;单行注释和多行注释。 单行注释只能注释一行…

POI:对Excel的基本读操作 整理2

1 简单读取操作 public class ExcelRead {String PATH "D:\\Idea-projects\\POI\\POI_projects";// 读取的一系列方法// ...... } 因为07版本和03版本操作流程大差不差&#xff0c;所以这边就以03版本为例 Testpublic void testRead03() throws IOException {//获取…

代码随想录刷题笔记(DAY11)

今日总结&#xff1a;继续准备期末&#xff0c;今天的算法题目比较简单&#xff0c;晚上看看能不能再整理一篇前端的笔记。 Day 11 01. 有效的括号&#xff08;No. 20&#xff09; 题目链接 代码随想录题解 1.1 题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff…

AMEYA360报导:瑞萨宣布收购Transphorm,大举进军GaN

全球半导体解决方案供应商瑞萨电子与全球氮化镓(GaN)功率半导体供应商Transphorm, Inc.(以下“Transphorm”)于今天宣布双方已达成最终协议&#xff0c;根据该协议&#xff0c;瑞萨子公司将以每股5.10美元现金收购Transphorm所有已发行普通股&#xff0c;较Transphorm在2024年1…

XYplorer:双栏多标签文件资源管理器的高效选择

在文件管理的世界中&#xff0c;效率和便捷性是用户追求的关键。XYplorer作为一款专为Windows设计的文件资源管理器&#xff0c;以其独特的双栏多标签浏览、强大的文件搜索功能、以及高度可定制的界面&#xff0c;为用户提供了一种全新的文件管理体验。 XYplorer&#xff1a;速…