Разработайте легкий плагин скользящего кода подтверждения с нуля

внешний интерфейс GitHub JavaScript
Разработайте легкий плагин скользящего кода подтверждения с нуля

адрес демо-версии react-slider-vertify:react-slider-vertify
Примечание: ⚠️Эта статья является первой подписанной статьей сообщества Nuggets, и её перепечатка без разрешения запрещена.

делился раньшенизкий кодивизуализация, которая включает в себя много интересных моментов знаний и дизайнерских идей.Сегодня я продолжу делиться с вами очень интересным и практичным фронтовым боевым проектом - на основе нуляreact + canvasРеализуйте прокрутку капчи и опубликуйте ее наnpmдля использования другими. Конечно, если вы предпочитаетеvueНе беспокойтесь о методе разработкиvueкомпоненты и публиковать вnpmВы также можете обратиться к моей предыдущей статье:Научу разрабатывать библиотеку компонентов на основе vue с нуля до единицы.

Из этого практического проекта мы можем извлечь следующие знания:

  • Базовые идеи и навыки разработки интерфейсных компонентов
  • Базовые знания и использование холста
  • Базовые знания и использование хуков реакции
  • Основной принцип построения скользящего проверочного кода
  • Как упаковать компонент расширяемого скользящего кода подтверждения
  • Как использовать dumi для создания документации по компонентам
  • Как опубликовать свой первый пакет npm

Если вас интересует какой-либо из вышеперечисленных пунктов знаний, я считаю, что эта статья вдохновит вас.

Демонстрация эффекта

slider.gif

Базовое использование и техническая реализация компонентов скользящей проверки

На приведенном выше рисунке показана демонстрация эффекта реализованного компонента скользящей проверки.Конечно, есть много элементов конфигурации на выбор, чтобы поддерживать большеНастройкаместо действия. Далее я сначала расскажу, как установить и использовать этот подключаемый модуль кода подтверждения, чтобы у вас был интуитивно понятный опыт, а затем я подробно представлю идеи реализации скользящего кода подтверждения.Если у вас есть определенная техническая база, вы также можете сразу перейти к части технической реализации.

основное использование

так какreact-slider-vertifyЯ выпустил этот компонент дляnpmпоэтому вы можете установить и использовать его следующим образом:

  1. Установить
# 或者 yarn add @alex_xu/react-slider-vertify
npm i @alex_xu/react-slider-vertify -S
  1. использовать
import React from 'react';
import { Vertify } from '@alex_xu/react-slider-vertify';

export default () => {
    return <Vertify 
            width={320}
            height={160}
            onSuccess={() => alert('success')} 
            onFail={() => alert('fail')} 
            onRefresh={() => alert('refresh')} 
        />
};

Выполнив два вышеуказанных шага, мы можем легко использовать этот компонент скользящего кода подтверждения, это очень просто?image.png

Конечно, я также предоставил множество настраиваемых свойств, чтобы дать вам лучший контроль над компонентами. Ссылка выглядит следующим образом:

image.png

Техническая реализация

Прежде чем заняться этим проектом, я также изучил некоторые знания о скользящем коде подтверждения и существующих технических решениях и многому научился. Далее я познакомлю вас с тем, как использовать мои идеи дизайна компонентов.reactЧтобы реализовать и инкапсулировать компонент скользящего кода подтверждения, если у вас есть лучшие идеи и предложения, вы также можете в любое время оставить отзыв в области комментариев.

1. Идеи и навыки компонентного дизайна

У каждого свой способ и стиль проектирования компонентов, но конечная цель состоит в том, чтобы быть болеемилостьмилостьМетрики проектирования компонентов:

  • удобочитаемость(Формат кода унифицирован, аннотация полная, структура кода четкая, используется парадигма программирования)

  • Доступность(Код полностью функционален, хорошо совместим в разных сценариях, покрытие бизнес-логики)

  • возможность повторного использования(Код может быть повторно использован другими бизнес-модулями)

  • ремонтопригодность(Код прост в обслуживании и расширении, с некоторой обратной/нисходящей совместимостью)

  • высокая производительность

Выше приведены соображения для моих собственных компонентов дизайна, вы можете обратиться к ним.

Кроме того, нам необходимо уточнить требования перед проектированием компонентов.В качестве примера возьмем компонент скользящего кода проверки, нам нужно знать сценарии его использования (Служба человеко-машинной проверки для бизнес-сценариев с высоким риском, таких как регистрация входа, события, форумы и SMS.) и требования (Логика взаимодействия, как проверить, какие свойства нужно выставить).

image.png

Вышеизложенное является общим требованием к разработке компонентов, с которым я разобрался.Перед разработкой конкретных компонентов, если мы столкнемся со сложной бизнес-логикой, мы также можем перечислить каждый шаг реализации, а затем реализовать их один за другим, что поможет организовать наши идеи. более эффективное развитие.

2. Основной принцип реализации скользящего проверочного кода

После ознакомления с идеями проектирования компонентов и анализа требований давайте взглянем на принцип реализации кода скользящей проверки.

image.png

Мы все знаем, что основная цель разработки проверочных кодов — предотвратить незаконное и насильственное вторжение машин в наши приложения.Определите, кто управляет приложением(люди or машина), поэтому обычное решениеслучайная идентификация.

На приведенном выше рисунке мы видим, что проверка проходит успешно только в том случае, если пользователь вручную перетаскивает ползунок в соответствующую пустую область, а положение пустой области является случайным (проверка случайности временно реализована во внешнем интерфейсе, и более безопасный способ - передать бэкэнд, чтобы вернуть местоположение и изображение).

Основываясь на приведенном выше анализе, мы можем нарисовать базовую принципиальную схему разработки скользящего кода проверки:

image.png

Далее мы упакуем вместе этот масштабируемый компонент кода скользящей проверки.

3. Инкапсулируйте расширяемый компонент скользящего кода проверки

Согласно моему обычному стилю разработки компонентов, я сначала напишу базовый фреймворк компонентов на основе требований:

import React, { useRef, useState, useEffect, ReactNode } from 'react';

interface IVertifyProp {
    /**
     * @description   canvas宽度  
     * @default       320
     */
    width:number, 
    /**
     * @description   canvas高度  
     * @default       160
     */
    height:number, 
    /**
     * @description   滑块边长  
     * @default       42
     */
     l:number,
     /**
     * @description   滑块半径 
     * @default       9
     */
      r:number,
     /**
     * @description   是否可见
     * @default       true
     */
      visible:boolean,
     /**
     * @description   滑块文本
     * @default       向右滑动填充拼图
     */
      text:string | ReactNode,
      /**
     * @description   刷新按钮icon, 为icon的url地址
     * @default       -
     */
       refreshIcon:string,
     /**
     * @description   用于获取随机图片的url地址
     * @default       https://picsum.photos/${id}/${width}/${height}, 具体参考https://picsum.photos/, 只需要实现类似接口即可
     */
       imgUrl:string,
    /**
     * @description   验证成功回调  
     * @default       ():void => {}
     */
    onSuccess:VoidFunction, 
    /**
     * @description   验证失败回调  
     * @default       ():void => {}
     */
    onFail:VoidFunction, 
    /**
     * @description   刷新时回调  
     * @default       ():void => {}
     */
    onRefresh:VoidFunction
}

export default ({ 
    width = 320,
    height = 160,
    l = 42,
    r = 9,
    imgUrl,
    text,
    refreshIcon = 'http://yourimgsite/icon.png',
    visible = true,
    onSuccess,
    onFail,
    onRefresh
 }: IVertifyProp) => {
     return <div className="vertifyWrap">
        <div className="canvasArea">
            <canvas width={width} height={height}></canvas>
            <canvas className="block" width={width} height={height}></canvas>
        </div>
        <div className={sliderClass}>
            <div className="sliderMask">
                <div className="slider">
                    <div className="sliderIcon">&rarr;</div>
                </div>
            </div>
            <div className="sliderText">{ textTip }</div>
        </div>
        <div className="refreshIcon" onClick={handleRefresh}></div>
        <div className="loadingContainer">
            <div className="loadingIcon"></div>
            <span>加载中...</span>
        </div>
    </div>
 }

Выше приведена базовая структура фрейма наших компонентов. Из кода видно, что свойства компонента понятны с первого взгляда, что является преимуществом предварительной организации требований, что позволяет нам более четко мыслить при написании компонентов. написание основныхcssИнтерфейс, который мы видим после стилизации, выглядит так:

image.png

Далее нам нужно реализовать следующие основные функции:

  • эффект пустотыcanvasреализация изображения
  • ажурный узорcanvasвыполнить
  • Движение ползунка и реализация логики проверки

Приведенное выше описание может быть абстрактным, поэтому позвольте мне нарисовать картинку для иллюстрации:

image.png

Поскольку реализация компонента полностью принимаетreact hooks, если все правыhooksЕсли вы не знакомы с ним, вы также можете обратиться к моей предыдущей статье:

1. Для достижения эффекта пустотыcanvasрисунок

image.png

В началеcodingПрежде чем нам нужноcanvasСуществует базовое понимание, рекомендуется, чтобы незнакомые друзья могли обратиться к эффективнымcanvasУчебные документы:Canvas of MDN.

Как видно из рисунка выше, первая проблема, которую нужно решить, это как использоватьcanvasЧтобы нарисовать неправильные формы, здесь я просто рисую набросок:

image.png

нам просто нужно использоватьcanvasкоторый предоставилпуть APIНарисуйте путь, показанный выше, и залейте путь любым полупрозрачным цветом. Рекомендуется, чтобы, если вы не знакомы с ним, вы могли сначала понять следующееapi :

  • beginPath() запускает отрисовку пути
  • moveTo() перемещает штрих в указанную точку
  • arc() рисует дугу
  • lineTo() рисовать линию
  • ход() ход
  • заполнить () заполнить
  • clip() обтравочный контур

Метод реализации выглядит следующим образом:

const drawPath  = (ctx:any, x:number, y:number, operation: 'fill' | 'clip') => {
    ctx.beginPath()
    ctx.moveTo(x, y)
    ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI)
    ctx.lineTo(x + l, y)
    ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI)
    ctx.lineTo(x + l, y + l)
    ctx.lineTo(x, y + l)
    // anticlockwise为一个布尔值。为true时,是逆时针方向,否则顺时针方向
    ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true)
    ctx.lineTo(x, y)
    ctx.lineWidth = 2
    ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)'
    ctx.stroke()
    ctx.globalCompositeOperation = 'destination-over'
    // 判断是填充还是裁切, 裁切主要用于生成图案滑块
    operation === 'fill'? ctx.fill() : ctx.clip()
}

Эта реализация также относится к нативной версии Yield.jsРеализация, пункт, который необходимо добавить здесь, заключается в том, чтоcanvasизglobalCompositeOperationсвойство, основной целью которого является установка способа рисования исходного (нового) изображения на целевом (существующем) изображении.

  • исходное изображение = рисунок, который мы собираемся разместить на холсте

  • целевое изображение = рисунок, который мы разместили на холсте

На w3c есть пример изображения:

image.png

Причина, по которой это свойство задано здесь, заключается в том, что на выдолбленную форму не влияет фоновая базовая карта, и она накладывается поверх фоновой базовой карты. следующее:

image.png

Далее нам просто нужно нарисовать изображение на холсте:

const canvasCtx = canvasRef.current.getContext('2d')
// 绘制镂空形状
drawPath(canvasCtx, 50, 50, 'fill')

// 画入图片
canvasCtx.drawImage(img, 0, 0, width, height)

Конечно, что касается того, как генерировать случайные картинки и случайные позиции, способ реализации тоже очень прост.Math.randomВот и все.

2. Осознайте полый паттернcanvas

Полая форма реализована выше, тогда полый узор аналогичен, нам нужно только использоватьclip()Метод Обрежьте изображение в маску формы и поместите полый узор в левой части холста. код показывает, как показано ниже:

const blockCtx = blockRef.current.getContext('2d')
drawPath(blockCtx, 50, 50, 'clip')
blockCtx.drawImage(img, 0, 0, width, height)

// 提取图案滑块并放到最左边
const y1 = 50 - r * 2 - 1
const ImageData = blockCtx.getImageData(xRef.current - 3, y1, L, L)
// 调整滑块画布宽度
blockRef.current.width = L
blockCtx.putImageData(ImageData, 0, y1)

Мы использовали код вышеgetImageDataиputImageData, дваapiиспользуется в основном для полученияcanvasПиксельные данные сцены холста и запись пиксельных данных в сцену. Эффект после внедрения следующий:

image.png

3. Реализуйте логику движения ползунка и проверки

Решение для реализации движения ползунка также относительно простое, нам нужно только использовать мышь.eventСобытия могут быть:

  • onMouseDown
  • onMouseMove
  • onMouseUp

image.png

Выше приведена простая схематическая диаграмма, конкретный код реализации выглядит следующим образом:

const handleDragMove = (e) => {
    if (!isMouseDownRef.current) return false
    e.preventDefault()
    // 为了支持移动端, 可以使用e.touches[0]
    const eventX = e.clientX || e.touches[0].clientX
    const eventY = e.clientY || e.touches[0].clientY
    const moveX = eventX - originXRef.current
    const moveY = eventY - originYRef.current
    if (moveX < 0 || moveX + 36 >= width) return false
    setSliderLeft(moveX)
    const blockLeft = (width - l - 2r) / (width - l) * moveX
    blockRef.current.style.left = blockLeft + 'px'
}

Конечно, нам также нужно отслеживать события после остановки перетаскивания, чтобы определить, прошла ли проверка успешно, и похоронить обратные вызовы успеха и неудачи. код показывает, как показано ниже:

const handleDragEnd = (e) => {
    if (!isMouseDownRef.current) return false
    isMouseDownRef.current = false
    const eventX = e.clientX || e.changedTouches[0].clientX
    if (eventX === originXRef.current) return false
    setSliderClass('sliderContainer')
    const { flag, result } = verify()
    if (flag) {
      if (result) {
        setSliderClass('sliderContainer sliderContainer_success')
        // 成功后的自定义回调函数
        typeof onSuccess === 'function' && onSuccess()
      } else {
        // 验证失败, 刷新重置
        setSliderClass('sliderContainer sliderContainer_fail')
        setTextTip('请再试一次') 
        reset()
      }
    } else {
      setSliderClass('sliderContainer sliderContainer_fail')
      // 失败后的自定义回调函数
      typeof onFail === 'function' && onFail()
      setTimeout(reset.bind(this), 1000)
    }
}

Эффект после внедрения следующий:

chrome-capture (4).gif

Конечно, есть еще некоторые детали, которые нужно оптимизировать, вотgithubНа нем есть полный код, вы можете обратиться к нему и изучить его.Если вы хотите внести свой вклад в этот компонент, вы также можете упомянуть его в любое время.issue.

4. Как использовать dumi для создания документации по компонентам

Чтобы компоненты лучше понимались и использовались другими, мы можем создавать документацию по компонентам. Как фронтенд, который любит открытый исходный кодcoder, написание документации по компонентам также является хорошей привычкой разработчиков. Далее мы такжеreact-slider-vertifyНапишите компонентный документ, здесь я используюdumiКонечно, для создания составных документов можно использовать и другие решения (например, сборник рассказов). Давайте посмотрим на эффект после строительства:

image.png

image.png

dumiСобрать документацию по компоненту очень просто.Далее я расскажу вам, как ее установить и использовать.

  1. Установить
$ npx @umijs/create-dumi-lib        # 初始化一个文档模式的组件库开发脚手架
# or
$ yarn create @umijs/dumi-lib

$ npx @umijs/create-dumi-lib --site # 初始化一个站点模式的组件库开发脚手架
# or
$ yarn create @umijs/dumi-lib --site
  1. работать локально
npm run dev
# or
yarn dev
  1. писать документацию

dumiУсловно определяет место и способ написания документа.На его официальном сайте также есть специальные вводные для еды.Вот краткое введение к предыдущему.dumiСхема структуры каталогов встроенных компонентов:

image.png

мы можемdocsИнструкции по написанию первой страницы и страницы руководства документации библиотеки компонентов ниже используются в папке одного компонента.index.mdНаписать документацию по использованию самого компонента, конечно, весь процесс очень простой, вот пример документации:

image.png

этим способомdumiЭто может помочь нам автоматически отображать компонент с помощью документа. Если вы хотите узнать больше о содержании документации по компонентам, вы также можете посетитьdumiИсследование на официальном сайте.

5. Опубликуйте свой первый пакет компонентов npm

Последняя проблема — публикация компонентов. Многие друзья спрашивали меня, как опубликовать мои компоненты вnpmПусть им воспользуется больше людей, в Интернете есть много информации, чтобы изучить этот фрагмент знаний, а затем используйте скользящий проверочный код сегодня.@alex_xu/react-slider-vertifyНапример, позвольте мне дать вам краткое введение.

  1. ИмеетсяnpmУчетная запись и вход

Если у вас нетnpmсчет, доступный по адресуофициальный сайт нпмПодпишитесь на один, затем используйте наш знакомыйIDEВход в терминал один раз:

npm login

После запроса на ввод имени пользователя и пароля мы можем опубликовать пакет компонента через командную строку:

npm publish --access public

Причина, по которой за командой следуетpublicЭтот параметр позволяет избежать проблем с разрешениями, из-за которых не удается успешно опубликовать пакет компонента. Чтобы избежать проблем, мы также можем настроить команду освобождения наpackage.json, который автоматически публикуется после упаковки компонента:

{
    "scripts": {
        "start": "dumi dev",
        "release": "npm run build && npm publish --access public",
  }
}

Это позволяет нам легко публиковать наши компоненты вnpmОн доступен для использования другими! Я также открыл исходный код многих библиотек компонентов ранее. Если у вас есть какие-либо вопросы о деталях упаковки компонентов и процессе создания, вы также можете обратиться к моим предыдущим решениям проекта с открытым исходным кодом. Опубликовать вnpmПосле эффекта:

image.png

Наконец

Если вы заинтересованы в визуальном конструировании или low-code/zero-code, вы также можете обратиться к моим предыдущим статьям или обменяться мыслями и опытом в области комментариев.Добро пожаловать, чтобы вместе изучить настоящую фронтенд-технологию.

github: react-slider-vertify
Стартер:Технологическое сообщество Nuggets
Столбец:гитхаб проект с открытым исходным кодом
Официальный аккаунт: Интересный интерфейс разговора

больше рекомендаций