百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

鸿蒙滑动拼图验证组件,有点意思...

toyiye 2024-05-19 19:35 21 浏览 0 评论

基于安卓平台的滑动拼图验证组件 SwipeCaptcha(https://github.com/mcxtzhang/SwipeCaptcha),实现了其核心功能的鸿蒙化迁移和重构,代码已经开源到,欢迎各位下载使用并提出宝贵意见!

开源地址:

https://gitee.com/isrc_ohos/SwipeCaptcha

在页面登录或者注册的时候,为了确保不是机器人操作,会让用户手动验证。验证方式分为滑动拼图验证和滑动验证两种。

本文的 SwipeCaptcha 组件可以实现滑动拼图的验证方式,操作简单,安全性强,被众多 APP 使用。

01组件效果展示

鸿蒙系统的 SwipeCaptcha 组件在使用时,有两个较为重要的图片:滑块和原图。

这两张图片被放置与同一水平线上,用户拖动滑块至原图处,误差在一定范围内,即可验证成功。

每次调用 SwipeCaptcha 组件,滑块和原图的位置都会发生随机变化,登录时被暴力破解的难度增加,安全性较高。

在 SwipeCaptcha 组件的验证界面,还有当前进度值和验证状态的描述。当前进度值表示滑块在水平方向的滑动进度,进度为 100 时,表示滑块滑至最右端。

进度值下方展示的是当前的验证状态,可分为:“开始”、“验证失败,请重新验证三种状态”、“验证成功”。

下面依次展示 SwipeCaptcha 组件拼图验证失败和成功的效果图。

①验证失败效果

用户未将滑块拖至原图处,导致滑块与原图的位置误差较大,验证失败。

图 1:验证失败效果


②验证成功效果

用户拖动滑块至原图处,误差在一定范围内,验证成功。

图 2:验证成功效果

02Sample 解析

Sample 主要包含以下四个部分:

  • 拼图背景导入手机
  • 裁剪滑块
  • 绘制滑块
  • 验证拼图是否成功

下面将通过具体步骤对上述四个部分进行详解。

①数据初始化

本步骤包含三个部分的数据设置:

  • 获取手机屏幕宽度信息。
  • 设置进度值和验证状态的初始提示文字,如“当前进度值”、“请滑动滑块验证”。
  • 初始化画笔信息,定义画笔属性。
//获取手机屏幕宽度displayAttributes.width
DisplayManager displayManager = DisplayManager.getInstance();
Display display = displayManager.getDefaultDisplay(this).get();
DisplayAttributes displayAttributes = display.getAttributes();
windowWidth = displayAttributes.width;
// 进度值初始化
text = new Text(this);
text.setMarginTop(800);// 距离顶端边界的距离
text.setText("当前进度值"+ progress);// 设定文字
text.setTextSize(100);// 设定字号
myLayout.addComponent(text);// 添加进布局中
// 验证状态初始化
text2 = new Text(this);
text2.setMarginTop(1000);
text2.setText("请滑动滑块验证");
text2.setTextSize(100);
myLayout.addComponent(text2);
//初始化画笔的信息
mPaint = new Paint();
mPaint.setColor(Color.BLACK);//定义颜色
mPaint.setAntiAlias(true);//定义虚实线
mPaint.setStrokeWidth(5f);//定义宽度
mPaint.setStyle(Paint.Style.STROKE_STYLE);//定义绘图方式

②背景图片绘制

用手机屏幕的宽度除以背景图片的宽度,得到背景图片的缩放比例,当该图片显示在手机中,按照此比例缩放可与屏幕同宽。

该比例用于背景图片适配不同型号的手机屏幕。

//背景图片的缩放比例
float ratio = (float) windowWidth/(float) img.getImageInfo().size.width;
//背景图片绘制
Component image = new Component(this);
Component.DrawTask drawTask = new Component.DrawTask() {
    @Override
    public void onDraw(Component component, Canvas canvas) {
        //按照比例进行缩放
        canvas.scale(ratio , ratio);
        //绘图
        canvas.drawPixelMapHolder(pixelMapHolder, 0, 0, new Paint());
    }
};
image.addDrawTask(drawTask);
myLayout.addComponent(image);

③确定滑块和原图的位置

图 3:滑块和原图的位置示意

puzzleWidth 为滑块或者原图的宽度;top 为随机数值,表示滑块或者原图的上边距离背景图片上边的距离;puzzel2left 也为随机数值,表示原图左边距离背景图片左边的距离。

有了以上三个变量可以确定组件中滑块和原图的初始位置和大小(滑块初始时位于屏幕的最左侧)。

下面介绍上述属性是如何计算出来的:

//puzzleWidth 为屏幕宽度的1/6
puzzleWidth = windowWidth/6;

//top为图片缩放后高度与抠图高度之差再乘以随机数
top = (float) Math.random()*(img.getImageInfo().size.height*ratio - puzzleWidth);

//原图位置一定在滑块位置右面
//屏幕宽度减去两个拼图宽度 *随机数,后向右平移一个滑块的长度
puzzel2left = ((windowWidth -puzzleWidth*2) * (float)Math.random()) + puzzleWidth;

④获取滑块

本步骤需要根据原图的位置,解码出一个图片作为滑块。

首先设置滑块的形状为矩形,依据上述的 puzzel2left、puzzleWidth 属性,确定矩形所在区域,依据缩放比例,将矩形区域映射为原比例图像,并对此图像进行解码,得到滑块图像数据。

PixelMap puzzlePixelMap =
 getPuzzlePixelMap(this , ResourceTable.Media_longa , new Rect((int)(puzzel2left/ratio), (int) (top/ratio), (int) (puzzleWidth/ratio) , (int) (puzzleWidth/ratio)));
PixelMapHolder pixelMapHolder1 = new PixelMapHolder(puzzlePixelMap);

⑤绘制滑块

滑块通过画笔来绘制,其位置应该根据滑动进度条的进度来移动,并且要对不同手机屏幕的进行适配。

同时,为了和用户友好的交互,我们还需要为滑块绘制一个边框,告知用户这个边框所在就是滑块(原图也需要绘制边框,原理相同)。

绘制滑块和边框的代码如下:

//绘制滑块
Component.DrawTask puzzelDrawTask = new Component.DrawTask() {
    @Override
    public void onDraw(Component component, Canvas canvas) {
        Paint paint = new Paint();
//移动小滑块拼图
        canvas.translate(slider.getProgress()*displayAttributes.width /100 , top);
//进行适当比例缩放
        canvas.scale(ratio , ratio);
        canvas.drawPixelMapHolder(pixelMapHolder1 , 0 , 0 , paint);

    }
};
//绘制滑块边框
Component puzzleFrame = new Component(this);
Component.DrawTask drawTask2 = new Component.DrawTask() {
    @Override
    public void onDraw(Component component, Canvas canvas) {
        //方框左侧位置
        float left = slider.getProgress()*windowWidth /100;
        //绘制边框的左边
        canvas.drawLine(new Point(left , top),
                new Point(left, top + puzzleWidth), mPaint);
        //绘制边框的上边
        canvas.drawLine(new Point(left, top),
                new Point(left + puzzleWidth, top), mPaint);
        //绘制边框的右边
        canvas.drawLine(new Point(left + puzzleWidth, top),
                new Point(left + puzzleWidth, top + puzzleWidth), mPaint);
        //绘制边框的下边
        canvas.drawLine(new Point(left, top + puzzleWidth),
                new Point(left + puzzleWidth, top + puzzleWidth), mPaint);
    }
};

⑥进度条滑动更新

为进度条设置监听,拖动进度条会引起三处更新:

  • 滑块位置和滑块边框位置的更新
  • 进度值的更新
  • 验证状态的更新

在验证状态的更新中,需要对用户拖动进度条结束时的验证状态进行判断,滑块和原图的位置差距是否在误差范围内,如果在范围内,则显示验证成功,如果不在误差范围内,则显示验证失败,提示需要重新验证。

//设置进度条监听
slider.setValueChangedListener(new Slider.ValueChangedListener() {
    @Override
//拖动进度条引起的更新
public void onProgressUpdated(Slider slider, int i, boolean b) {
    //滑块的位置更新
    puzzle.invalidate();
    //滑块边框位置的更新
    puzzleFrame.invalidate();
    //进度值更新
text.setText("当前进度值 : " + slider.getProgress());
    }
}

//当用户开始滑动进度条时,验证状态变为“开始”字样。
public void onTouchStart(Slider slider) {
    //开始拖动的方法
    text2.setText("开始");
}
 //判断滑块左侧边的位置和原图的左侧边的位置是否在误差内
public void onTouchEnd(Slider slider) {
        if(((slider.getProgress()*windowWidth /100)<(puzzel2left + puzzleWidth/10))&&((slider.getProgress()*windowWidth /100)>(puzzel2left - puzzleWidth/10)))
    {
        text2.setText("验证成功");
    }else {
        text2.setText("验证失败,请重新验证");
        slider.setProgressValue(10);
    }
}

项目贡献人:赵柏屹、郑森文、朱伟、陈美汝、张馨心

作者: 朱伟ISRC

文章链接:https://mp.weixin.qq.com/s/sVeRfcEtD4T9MRftkDm8KQ

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码