#yew #checkcode #ui-controller #canvas2d

wasm-yew-canvas-checkcode

纯前端的,运行于WASM中的,基于Canvas 2D绘图引擎的,Yew.rs图形验证码控件

1个不稳定版本

0.1.0 2023年12月5日

#571 in WebAssembly

MIT许可证

28KB
375 代码行(不含注释)

wasm-yew-canvas-checkcode

纯前端yew.rs图形验证码控件。不同于从后端拉取图形验证码图片,该控件以更“轻量级”的技术手段抑制UI用户重复地连续提交表单。

工作原理

  1. 借助rand crate,本地生成随机字符串。

  2. 经由web_sys crate,操作Canvas 2D平面渲染引擎,生成图形验证码图片。在图片中的

    1. 背景色
    2. 背景星型图案
    3. 每个星型图案的角数(3 ~ 8)、位置、旋转、颜色、密度
    4. 每位验证字符的位置、旋转、颜色,间距

    都是被即时演算出来的。

  3. 通过被传入控件的【回调函数】on_check_code_change(CheckCode),将被生成的随机字符串验证码返回给父控件。

::wasm_yew_canvas_checkcode::CanvasCheckCode图形验证码控件自身。在渲染函数中,其被记为<CanvasCheckCode>

  1. ::wasm_yew_canvas_checkcode::Message控件的枚举类内部状态集
  2. ::wasm_yew_canvas_checkcode::CheckCode包装了图形验证码字符串的枚举类
  3. ::CheckCode::Initialize(String)代表控件初始化过程生成的图形验证码
  4. ::CheckCode::Update(String)代表由UI鼠标点击事件或父控件程序触发生成的图形验证码
    • 控件输入参数列表

    • width

      • u64
      • 可选参数

      单位:像素

图形验证码canvas画布的宽度

  1. 默认值优先次序: 150
    • height
    • u64
    • 图形验证码canvas画布的高度
    • 默认值
      1. 50
      2. star_size
  2. u64: 150
    • height
    • u64
    • 可选参数
    • 默认值
      1. 50
      2. 单位:像素
  3. 背景随机星型图案的大小尺寸。因为星型图案的BBox是正方形,所以这里仅需要设置一个值。: 150
    • height
    • u64
    • 默认值
    • 7
  4. star_count: u8
    1. height
    2. 单位:个
    3. 背景随机星型图案的最多个数。
    4. 默认值
  5. 25: 150
    • height
    • u64
    • font_size
    • u64
  6. 可选参数: u8
    1. height
    2. 单位:个
    3. 单位:像素
    4. 验证码单个字符的最大尺寸
  7. 默认值: 22<check_code_len>
    1. u8
    2. 可选参数
      1. 验证码的字符个数
        1. 控件输入参数列表
        2. CheckCode::Update(String)表示由UI点击事件或程序触发的图形验证码
      2. 没有返回值
    3. 功能:向父控件反馈最新生成的验证码字符串。
  8. reversed_hook: 22<作用域<CanvasCheckCode>>
    1. height

    2. 可选参数

      1. 形式参数Scope<CanvasCheckCode>代表<CanvasCheckCode>控件的【作用域】对象。
      2. 没有返回值
    3. 功能:向父控件传递<CanvasCheckCode>【作用域】对象(副本),以允许从控件外部程序地触发新图形验证码的生成操作。例如,

      1. 首先,通过Rc<RefCell<Option<Scope<CanvasCheckCode>>>>字段值,缓存被上传的<CanvasCheckCode>【作用域】对象副本。
      2. 其次,在fn view(..) -> bool生命周期函数内,程序地触发<CanvasCheckCode>子控件重新生成图形验证码。
      self.check_code_scope.borrow().as_ref().map(|scope| {
         scope.send_message(CanvasCheckCodeMessage::UpdateCheckCode);
      });
      
    4. 默认值表示不执行任何操作

总结,最后两个控件输入参数都是回调函数。它们的功能都是从下向上,从<CanvasCheckCode>向父控件传递返回值的

  1. on_check_code_change返回最新的图形验证码字符串。
  2. reversed_hook返回程序触发生成新图形验证码的“操作句柄”。

控件输出回调函数钩子

<CanvasCheckCode>控件以回调函数的方式向父控件回传

  1. 最新被生成的图形验证码字符串 —— 用以校对UI用户敲入的图形验证码字符串是否正确。
  2. 自身作用域对象Scope<CanvasCheckCode> —— 用以程序地从父控件触发新图形验证码的生成。

从父控件获取最新图形验证码字符串

回调函数签名on_check_code_change: |check_code: CheckCode| -> () { .. }

  • 回调函数的返回值是unit type
  • 形参是枚举类CheckCode
    • 控件输入参数列表

    • width

      • u64
      • 可选参数

      单位:像素

例程

use ::wasm_yew_canvas_checkcode::CheckCode;
//
yew::props![CanvasCheckCodeProps {
   on_check_code_change: |check_code| {
      let check_code = match check_code {
            CheckCode::Initialize(value) => value,
            CheckCode::Update(value) => value,
      };
      console::info!("从父组件收到的校验码", check_code);
   }
}]

从父控件程序地刷新图形验证码

回调函数签名reversed_hook: |my_scope: Scope<CanvasCheckCode>| -> () { .. }

  • 回调函数的返回值是unit type
  • 形参是Scope<CanvasCheckCode>

首先,获取<CanvasCheckCode>子控件的作用域对象Scope<CanvasCheckCode>

然后,在父控件的结构体字段<child1_scope: Rc<RefCell<Option<Scope<CanvasCheckCode>>>>内缓存该作用域对象。

use ::wasm_yew_canvas_checkcode::CheckCode;
//
yew::props![CanvasCheckCodeProps {
   reversed_hook: |my_scope| {
      // 在父控件中,缓存子控件的`scope`对象
      child1_scope.borrow_mut().replace(my_scope);
   }
}]

最后,在父控件的fn update( .. ) -> bool生命周期函数内,修改子控件<CanvasCheckCode>的状态集以触发新的图形验证码被生成。

fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
   let props = ctx.props();
   match msg {
      Message::SubmitForm => {
         self.child1_scope.borrow().as_ref().map(|child1_scope| { // 从父控件,触发子控件刷新图形验证码
            child1_scope.send_message(CanvasCheckCodeMessage::UpdateCheckCode);
         });
         return false;
      }
      _ => ()
   }
   true
}

附赠两个例程

crate以【**(有脸)**集成测试】的方式,提供两个例程

仅图形验证码控制简单例程

例程文件:tests\simple.rs

启动命令行指令:wasm-pack test --chrome --test=simple

演示内容:

  1. <CanvasCheckCode>控件被直接加到DOM流中,作为整个wasm-webapp的根组件。
  2. 点击<CanvasCheckCode>控件会刷新图形验证码字符串

例程1

登录表单半成品(实战)例程

例程文件:tests\form.rs

启动命令行指令:wasm-pack test --chrome --test=form

演示内容:

  1. wasm-webapp的根组件是一个【用户名/密码/图形验证码】的常规网页登录表单。
  2. 集成测试执行流被阻塞。只有当UI用户输入了正确的图形验证码,才能开始表单验证。
  3. 点击<CanvasCheckCode>控件会刷新图形验证码字符串,同时清空图形验证码的文本输入框。
  4. 点击【登录】按钮,会比较从<CanvasCheckCode>控件回传给父控件的图形验证码“真身”与用户输入的图形验证码字符串是否一致。
  5. 如果两个图形验证码字符串一致,则集成测试成功通过。
  6. 否则,集成测试失败

image

依赖项

~11–15MB
~264K SLoC