【前端开发】一个滑动滑块校验登录的组件思路(用vue写的)

复制代码
<template>
  <el-dialog
    :visible.sync="dialogVisible"
    custom-class="slideVerifyDialog"
    :close-on-click-modal="false"
    title="身份验证"
    width="360px"
  >
    <section class="slider-section">
      <div class="img-box">
        <img :src="bigImgSrc" class="bg-img" ref="bgImg" />
        <img :src="sliderImgSrc" class="slider-img" ref="sliderImg" />
        <i class="refresh-btn el-icon-refresh" @click="init" />
      </div>
      <div class="slider-box">
        <span class="slider-text">向右滑动滑块填充拼图</span>
        <div class="slider-icon" @mousedown="rangeMove">></div>
      </div>
    </section>
  </el-dialog>
</template>
<script lang="ts">
import { Vue, Component, Prop, Ref } from 'vue-property-decorator'
import { getSlideImg, checkSlide } from '@/modules/login/api/login'

@Component({
  name: 'SlideVerifyDialog'
})
export default class SlideVerifyDialog extends Vue {
  @Prop() visible!: boolean
  @Ref() bgImg: any
  @Ref() sliderImg: any
  bigImgSrc = ''
  sliderImgSrc = ''
  disX = 0 // 滑块距离背景图左侧的位置
  slide: any = {
    bigHeight: 0,
    bigImageBase64: '',
    bigWidth: 0,
    code: '',
    posX: 0,
    posY: 0,
    smallHeight: 0,
    smallImageBase64: '',
    smallWidth: 0
  }

  get dialogVisible() {
    return this.visible
  }

  set dialogVisible(val: boolean) {
    this.$emit('update:visible', val)
  }

  mounted() {
    this.init()
  }

  getSide() {
// 这是获取滑块code的
return getSlideImg().then((res: any) => { this.slide = res.data }) } checkSlide() {
// 这里把滑块的code和滑块x轴滑动的距离传给后端 checkSlide({ code:
this.slide.code, posX: this.disX }) .then(() => { this.dialogVisible = false this.$emit('submitPic', { code: this.slide.code, posX: this.disX }) }) .catch(() => { this.init() }) } async init() { await this.getSide() this.disX = 0 // 初始化滑块位置 this.bigImgSrc = 'data:image/png;base64,' + this.slide.bigImageBase64 this.sliderImgSrc = 'data:image/png;base64,' + this.slide.smallImageBase64 this.sliderImg.style.width = this.slide.smallWidth + 'px' // 设置滑块图片宽度 this.sliderImg.style.height = this.slide.smallHeight + 'px' // 设置滑块图片高度 this.sliderImg.style.top = `${Number(this.slide.posY) + 1}px` // 设置滑块距离背景图顶部的距离 this.sliderImg.style.left = 0 // 设置滑块距离背景图左侧的距离 } // 移动事件触发 rangeMove(e: any) { const ele = e.target const startX = e.clientX const eleWidth = ele.offsetWidth const parentWidth = ele.parentElement.offsetWidth const MaxX = parentWidth - eleWidth document.onmousemove = (event: any) => { const endX = event.clientX this.disX = endX - startX this.sliderImg.style.left = this.disX + 'px' if (this.disX <= 0) { this.disX = 0 this.sliderImg.style.left = 0 } if (this.disX >= MaxX - eleWidth) { // 减去滑块的宽度,体验效果更好 this.disX = MaxX this.sliderImg.style.left = parentWidth - this.sliderImg.width + 'px' } ele.style.transition = '.1s all' ele.style.transform = 'translateX(' + this.disX + 'px)' event.preventDefault() } document.onmouseup = () => { this.checkSlide() // this.$emit('submitPic', { code: this.slide.code, posX: this.disX }); setTimeout(() => { ele.style.transition = '.1s all' // 初始化滑块位置 ele.style.transform = 'translateX(0)' }, 200) document.onmousemove = null document.onmouseup = null } } } </script> <style lang="scss" scoped> .slideVerifyDialog { margin: 0 !important; position: absolute !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; .el-dialog__body { padding: 16px !important; } } </style> <style scoped lang="scss"> .slider-section { // margin: 20px 0; .img-box { position: relative; .bg-img { width: 100%; } .refresh-btn { position: absolute; cursor: pointer; bottom: 16px; right: 16px; width: 20px; height: 20px; font-size: 20px !important; color: #fff; z-index: 20; } .slider-img { position: absolute; left: 0; top: 0; z-index: 30; } } .slider-box { margin-top: 20px; background: #f7f9fa; color: #666; border: 1px solid #e4e7eb; position: relative; height: 30px; width: 100%; &:hover { box-shadow: 0 0 3px #ccc; } .slider-text { font-size: 14px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .slider-icon { cursor: move; width: 30px; height: 30px; line-height: 30px; background: #c8923a; text-align: center; font-size: 20px !important; color: #fff; box-shadow: 0 0 6px #ccc; } } } </style>
复制代码

效果

 

posted @   JeckHui  阅读(891)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示