鴻蒙第三方組件——SwipeCaptcha滑動拼圖驗證組件

目錄:
一、組件效果展現
二、Sample解析
三、《鴻蒙第三方組件》系列文章合集git

前言github

    基於安卓平臺的滑動拼圖驗證組件SwipeCaptcha( https://github.com/mcxtzhang/SwipeCaptcha),實現了其核心功能的鴻蒙化遷移和重構,代碼已經開源到(https://gitee.com/isrc_ohos/SwipeCaptcha),歡迎各位下載使用並提出寶貴意見!canvas

  背景 安全

        在頁面登陸或者註冊的時候,爲了確保不是機器人操做,會讓用戶手動驗證。驗證方式分爲滑動拼圖驗證和滑動驗證兩種。本文的SwipeCaptcha組件能夠實現滑動拼圖的驗證方式,操做簡單,安全性強,被衆多APP使用。dom

組件效果展現 ide

        鴻蒙系統的SwipeCaptcha組件在使用時,有兩個較爲重要的圖片:滑塊和原圖。這兩張圖片被放置與同一水平線上,用戶拖動滑塊至原圖處,偏差在必定範圍內,便可驗證成功。每次調用SwipeCaptcha組件,滑塊和原圖的位置都會發生隨機變化,登陸時被暴力破解的難度增長,安全性較高。佈局

       在SwipeCaptcha組件的驗證界面,還有當前進度值和驗證狀態的描述。當前進度值表示滑塊在水平方向的滑動進度,進度爲100時,表示滑塊滑至最右端。進度值下方展現的是當前的驗證狀態,可分爲:「開始」、「驗證失敗,請從新驗證三種狀態」、「驗證成功」。下面依次展現SwipeCaptcha組件拼圖驗證失敗和成功的效果圖。post

一、驗證失敗效果this

       用戶未將滑塊拖至原圖處,致使滑塊與原圖的位置偏差較大,驗證失敗。url

鴻蒙第三方組件——SwipeCaptcha滑動拼圖驗證組件

圖1  驗證失敗效果

二、驗證成功效果

      用戶拖動滑塊至原圖處,偏差在必定範圍內,驗證成功。

鴻蒙第三方組件——SwipeCaptcha滑動拼圖驗證組件

圖2  驗證成功效果

Sample解析

        Sample主要包含如下四個部分:1)拼圖背景導入手機。2)裁剪滑塊。3)繪製滑塊。4)驗證拼圖是否成功。下面將經過具體步驟對上述四個部分進行詳解。 一、數據初始化

       本步驟包含三個部分的數據設置:(1)獲取手機屏幕寬度信息;(2)設置進度值和驗證狀態的初始提示文字,如「當前進度值」、「請滑動滑塊驗證」;(3)初始化畫筆信息,定義畫筆屬性;

//獲取手機屏幕寬度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. 肯定滑塊和原圖的位置

鴻蒙第三方組件——SwipeCaptcha滑動拼圖驗證組件

圖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;

4. 獲取滑塊

        本步驟須要根據原圖的位置,解碼出一個圖片做爲滑塊。首先設置滑塊的形狀爲矩形,依據上述的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);

5.繪製滑塊

        滑塊經過畫筆來繪製,其位置應該根據滑動進度條的進度來移動,而且要對不一樣手機屏幕的進行適配。同時,爲了和用戶友好的交互,咱們還須要爲滑塊繪製一個邊框,告知用戶這個邊框所在就是滑塊(原圖也須要繪製邊框,原理相同)。繪製滑塊和邊框的代碼以下:

//繪製滑塊
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);
    }
};

6. 進度條滑動更新

       爲進度條設置監聽,拖動進度條會引發三處更新:(1)滑塊位置和滑塊邊框位置的更新;(2)進度值的更新;(3)驗證狀態的更新。在驗證狀態的更新中,須要對用戶拖動進度條結束時的驗證狀態進行判斷,滑塊和原圖的位置差距是否在偏差範圍內,若是在範圍內,則顯示驗證成功,若是不在偏差範圍內,則顯示驗證失敗,提示須要從新驗證。

//設置進度條監聽
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
想了解更多內容,請訪問51CTO和華爲合做共建的鴻蒙社區:https://harmonyos.51cto.com/

相關文章
相關標籤/搜索