#夏日挑战赛# HarmonyOS 实现一个滑块验证 原创 精华

lxj29
发布于 2022-7-30 16:59
浏览
3收藏

本文正在参加星光计划3.0–夏日挑战赛

前言

日常我们经常能见到验证码,网站上的验证码的作用是保护网站安全,一般网站都要通过验证码来防止机器大规模注册等危害。一般验证码有:图像验证、算数验证、滑动验证等。有些验证码验证起来有些麻烦,对我来说,最方便的验证方式是滑动滑块验证,滑块验证的使用体验非常好。

所以本篇文章我来尝试着实现一个滑动验证码。当然,这种验证码一般都是第三方来处理的,因为它不仅仅只是滑动,还会判断用户的拖放轨迹是否符合真实用户的行为特征,所以我只是简单的实现。

介绍

这是一个滑块验证码,用户只需要将滑块滑到最右侧,即可判断用户是否验证成功。

效果展示

我为滑块验证添加了验证条件,用户可以对滑块速度做限制,例如:滑块滑倒右侧时,平均速度小于3,如果用户滑动速度大于3时,就验证失败

#夏日挑战赛# HarmonyOS 实现一个滑块验证-鸿蒙开发者社区

我一共滑动了三次

  • 第一次:没有滑倒最右侧,认证失败
  • 第二次:滑动的速度太块,认证失败
  • 第三次:滑动速度符合限制,认证成功

使用

1.参数支持

参数名称 参数描述 参数类型 默认值
width 滑块宽度 Number 300
height 滑块高度 Number 50
limit 滑块的速率限制 Number 4

2.事件支持

事件名称 事件描述
getMsg 验证通过或不通过事件

用户可以设置限制体速率,可以通过自定义事件getMsg,获取到验证的结果

#夏日挑战赛# HarmonyOS 实现一个滑块验证-鸿蒙开发者社区

原理分析

1.滑动原理

首先,我们需要在组件加载完成时,获取到滑块可以滑动的最大距离,我们用得到的最大距离,来判断滑块是否滑倒最右侧

注意组件的生命周期,在自定义组件中,是没有onShow的,需要用onLayoutReady(),这个钩子函数是自定义组件布局完成调用的。

然后,在触摸屏幕事件中,获取触摸的X坐标,此坐标为起始点;在触摸移动事件中,获取最新的X坐标,再减去起始坐标,就能得到偏移量

最后,判断偏移量是否大于滑块可以滑动的最大距离,如果不大于,将偏移量设置为滑块的滑动距离

为了更好理解,我把滑块隐藏部分显示出来

#夏日挑战赛# HarmonyOS 实现一个滑块验证-鸿蒙开发者社区

    touchstart (e) {
        //设置X轴的始点
        this.startPositionX = e.touches[0].localX;
        this.startTime = 0
        this.s = 0
        this.num = 0
    },
    //滑块移动中执行的事件
    touchmove (e) {
            const offsetX = e.touches[0].localX - this.startPositionX
            // 如果验证成功后仍允许滑动,则执行下面代码块(初始值默认为允许)
            if (this.isSlide) {
                //当x坐标大于最大可移动距离,那么当前x坐标即为最大可移动距离
                if (offsetX >= this.max) {
                    this.x = this.max
                } else {
                    // 将当前鼠标x坐标给滑块移动的距离
                    this.x = offsetX;
                }
            }
    },

2.验证原理

这里的验证不严谨,只是一个小尝试

验证原理主要是通过滑动的平均速度来判断的,如果用户滑动速度超过设定速度,则验证失败

所以我们需要使用到时间戳

第一步,我们在移动事件一开始,获取到当前的时间戳;在移动事件结束将当前时间戳赋值给上一个时间,这样通过当前时间戳 -上一个时间就能获取到时间间隔

第二步,我们还需要获取到偏移量,上面滑动原理已经介绍了如何获取

第三步,有了时间间隔和偏移量,我们可以计算出本次滑动的速度,再利用总的滑动次数来获取到平均速度。

最后,我们只需要在touchend事件中做判断,判断滑块是否到达滑动的最大距离,并且滑块滑动的平均速度是否符合限制。

    touchmove (e) {
            const offsetX = e.touches[0].localX - this.startPositionX
            const currTime = Date.now()
            if (this.startTime !== 0) {
                const duration = currTime - this.startTime
                // 传入倒数第二个点和最后一个点,和持续时间,会返回加速度
                const v = parseInt(offsetX / duration)
                this.num++
                this.s = this.s + v

            }
            this.startTime = currTime
            // 如果验证成功后仍允许滑动,则执行下面代码块(初始值默认为允许)
            if (this.isSlide) {
                //当x坐标大于最大可移动距离,那么当前x坐标即为最大可移动距离
                if (offsetX >= this.max) {
                    this.x = this.max
                } else {
                    // 将当前鼠标x坐标给滑块移动的距离
                    this.x = offsetX;
                }
            }
    },
    //松开滑块执行的事件
    touchend (e) {
//        计算平均速度
        const avg = this.s / this.num
        console.log(avg)
        //自定义组件触发事件时提供的data对象
        var data = {};
        //如果触摸的X轴坐标大于等于限定的可移动范围,并且滑动的平均速度不能超过100,则验证成功
        if (this.x == this.max && avg < this.limit) {
            //设置验证成功提示语
            this.status = '验证成功';
            //设置data对象的返回值
            data.msg = true;
            //验证成功后,禁止滑块滑动
            this.isSlide = false;
        } else {
            //元素X轴坐标归0
            this.x = 0;
            //清空验证成功提示语
            this.status = '';
            this.tip = '验证失败'
            //设置data对象的返回值
            data.msg = false;
        }
        this.$emit('getMsg', data)
    }

完整代码

index.js

// @ts-nocheck
export default{
    data:{
      tip: '右滑验证',
      x: 0,//X轴的初始值
      startPositionX: 0,//触摸时X轴的值
      max: 0,//滑块可移动的X轴范围
      status: '',//验证完后的提示信息
      isSlide: true,//是否允许验证成功后继续滑动
      positionList: {}, // 存储坐标位置
      startTime: 0,
      num: 0, // 总次数
      s: 0 // 速度之和
    },
    props: {
        limit: {
            type: Number,
            default: 4
        },
        width: {
            type: Number,
            default: 400
        },
        height: {
            type: Number,
            default: 100
        }
    },
    onLayoutReady(){
        let ball = this.$element("ball")
        let box = this.$refs.container
        // 滑块可以移动的最大距离
        this.max = box.getBoundingClientRect().width - ball.getBoundingClientRect().width
    },
    touchstart (e) {
        //设置X轴的始点
        this.startPositionX = e.touches[0].localX;
        this.startTime = 0
        this.s = 0
        this.num = 0
    },
    //滑块移动中执行的事件
    touchmove (e) {
            const offsetX = e.touches[0].localX - this.startPositionX
            const currTime = Date.now()
            if (this.startTime !== 0) {
                const duration = currTime - this.startTime
                // 传入倒数第二个点和最后一个点,和持续时间,会返回加速度
                const v = parseInt(offsetX / duration)
                this.num++
                this.s = this.s + v

            }
            this.startTime = currTime
            // 如果验证成功后仍允许滑动,则执行下面代码块(初始值默认为允许)
            if (this.isSlide) {
                //当x坐标大于最大可移动距离,那么当前x坐标即为最大可移动距离
                if (offsetX >= this.max) {
                    this.x = this.max
                } else {
                    // 将当前鼠标x坐标给滑块移动的距离
                    this.x = offsetX;
                }
            }
    },
    //松开滑块执行的事件
    touchend (e) {
//        计算平均速度
        const avg = this.s / this.num
        //自定义组件触发事件时提供的data对象
        var msg = {};
        //如果触摸的X轴坐标大于等于限定的可移动范围,并且滑动的平均速度不能超过100,则验证成功
        if (this.x == this.max && avg < this.limit) {
            //设置验证成功提示语
            this.status = '验证成功';
            //设置data对象的返回值
            msg = true;
            //验证成功后,禁止滑块滑动
            this.isSlide = false;
        } else {
            //元素X轴坐标归0
            this.x = 0;
            //清空验证成功提示语
            this.status = '';
            this.tip = '验证失败'
            //设置data对象的返回值
            msg = false;
        }
        this.$emit('getMsg', msg)
    }
}

总结📝

不足点:验证条件比较简单

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
slider.zip 2.1K 26次下载
已于2022-7-30 17:00:32修改
5
收藏 3
回复
举报
1条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

是没见过的验证方式,如果设定为滑到某个随机标记点会不会好一点?

回复
2022-8-1 14:22:01
回复
    相关推荐