0

0

React 中实现维吉尼亚密码表的逐步高亮动画教程

碧海醫心

碧海醫心

发布时间:2026-02-13 09:27:32

|

876人浏览过

|

来源于php中文网

原创

React 中实现维吉尼亚密码表的逐步高亮动画教程

本文详解如何在 react 中为维吉尼亚密码(vigenère cipher)加密过程中的每一对明文-密钥字母,动态高亮其在加法表中对应的行与列,实现「逐字符、分步着色」的可视化效果。

在维吉尼亚密码的 React 实现中,仅静态展示加密结果远远不够——真正的教学价值和用户体验提升,来自于可感知的算法执行过程。用户希望看到:当输入 password="cat" 和 text="rat" 时,界面依次高亮 (c,r) → (a,a) → (t,t) 在密码表中对应的行与列(即:第 r 行 + 第 c 列 → 第 a 行 + 第 a 列 → 第 t 行 + 第 t 列),形成清晰的「步骤式引导动画」。这要求状态管理必须精确到当前处理索引,而非仅记录最终位置。

✅ 核心思路:分离关注点 + 步进式状态驱动

我们不直接在 handleCipherButtonClick 中一次性计算全部结果并设置最终 row/col,而是将加密逻辑拆解为可暂停、可步进、可渲染的流程:

万相营造
万相营造

阿里妈妈推出的AI电商营销工具

下载
  • 使用 useState 管理当前处理的字符索引 stepIndex
  • 使用 useEffect 配合 setInterval 或 setTimeout 控制步进节奏
  • 每次更新 stepIndex,自动触发表格重新渲染,高亮对应行列

以下为优化后的完整实现(已适配原 Georgian 字母表):

import React, { useState, useEffect, useCallback } from 'react';

function VigenereCipher() {
  const georgianLetters = 'აბგდევზთიკლმნოპჟრსტუფქღყშჩცძწჭხჯჰ';
  const table = Array.from({ length: 33 }, (_, i) =>
    Array.from({ length: 33 }, (_, j) => georgianLetters[(i + j) % 33])
  );

  const [password, setPassword] = useState('');
  const [text, setText] = useState('');
  const [ciphered, setCiphered] = useState('');
  const [stepIndex, setStepIndex] = useState(-1); // -1: 未开始;0 ~ n-1: 当前步;n: 完成
  const [isRunning, setIsRunning] = useState(false);

  // ✅ 提取加密逻辑为纯函数,便于复用与测试
  const getStepData = useCallback(() => {
    if (!password || !text || stepIndex < 0) return null;

    const cleanText = text.split('').filter(c => c !== ' ');
    const cleanPassword = password.split('').filter(c => c !== ' ');

    if (stepIndex >= cleanText.length) return null;

    const char = cleanText[stepIndex];
    const keyChar = cleanPassword[stepIndex % cleanPassword.length];

    const rowIndex = georgianLetters.indexOf(char);
    const colIndex = georgianLetters.indexOf(keyChar);

    return { char, keyChar, rowIndex, colIndex, isSpace: text[stepIndex] === ' ' };
  }, [password, text, stepIndex]);

  // ✅ 启动/重置动画
  const startAnimation = () => {
    if (!password || !text) {
      alert('შეავსეთ პაროლის და ტექსტის ველები');
      return;
    }
    setStepIndex(0);
    setIsRunning(true);
    setCiphered('');
  };

  // ✅ 停止动画(可选)
  const stopAnimation = () => {
    setIsRunning(false);
  };

  // ✅ 步进逻辑:每次只推进 1 步
  useEffect(() => {
    if (!isRunning || stepIndex < 0) return;

    const timer = setTimeout(() => {
      const next = stepIndex + 1;
      const cleanText = text.split('').filter(c => c !== ' ');
      if (next > cleanText.length) {
        setIsRunning(false);
      } else {
        setStepIndex(next);
      }
    }, 1200); // 每步间隔 1.2 秒,可调

    return () => clearTimeout(timer);
  }, [isRunning, stepIndex, text]);

  // ✅ 实时生成高亮后的表格
  const renderTable = () => {
    const stepData = getStepData();
    const highlightRow = stepData?.rowIndex ?? -1;
    const highlightCol = stepData?.colIndex ?? -1;

    return (
      <table className="vigenere-table">
        <tbody>
          {georgianLetters.split('').map((_, i) => (
            <tr key={i}>
              {georgianLetters.split('').map((_, j) => {
                let bgColor = 'transparent';
                if (i === highlightRow && j === highlightCol) {
                  bgColor = '#8b5cf6'; // 紫色:交汇点(核心匹配)
                } else if (i === highlightRow) {
                  bgColor = '#fbbf24'; // 黄色:当前明文字母所在行
                } else if (j === highlightCol) {
                  bgColor = '#3b82f6'; // 蓝色:当前密钥字母所在列
                }
                return (
                  <td key={j} style={{ backgroundColor: bgColor }}>
                    {table[i][j]}
                  </td>
                );
              })}
            </tr>
          ))}
        </tbody>
      </table>
    );
  };

  // ✅ 动态生成加密结果(仅用于显示,非实时渲染)
  useEffect(() => {
    if (stepIndex < 0 || !password || !text) return;

    const cleanText = text.split('').filter(c => c !== ' ');
    const cleanPassword = password.split('').filter(c => c !== ' ');

    if (stepIndex > cleanText.length) {
      // 加密完成
      let k = 0;
      let result = '';
      for (let i = 0; i < text.length; i++) {
        if (text[i] === ' ') {
          result += ' ';
        } else {
          const rIdx = georgianLetters.indexOf(text[i]);
          const cIdx = georgianLetters.indexOf(password[k % password.length]);
          if (rIdx !== -1 && cIdx !== -1) {
            result += table[rIdx][cIdx];
            k++;
          }
        }
      }
      setCiphered(result);
    }
  }, [stepIndex, password, text, table]);

  return (
    <div className="main">
      <h2>ვიჟინერის ცხრილი — ნაბიჯ-ნაბიჯ გამოსახულება</h2>
      {renderTable()}

      <div className="right-side">
        <div className="pass-text">
          <label>პაროლი</label>
          <input type="text" value={password} onChange={(e) => setPassword(e.target.value)} />
          <label>ტექსტი</label>
          <textarea value={text} onChange={(e) => setText(e.target.value)} rows="4" />
        </div>

        <div className="controls">
          <button onClick={startAnimation} disabled={isRunning}>
            {isRunning ? 'გაშვებული...' : 'დაწყება'}
          </button>
          <button onClick={stopAnimation} disabled={!isRunning}>
            შეწყვეტა
          </button>
        </div>

        <div className="ciphered">
          <label>შედეგი</label>
          <textarea readOnly value={ciphered} rows="4" />
        </div>

        <div className="step-info">
          <p>
            ნაბიჯი: <strong>{stepIndex < 0 ? '—' : stepIndex === 0 ? '0 (საწყისი)' : `${stepIndex}/${text.replace(/\s/g, '').length}`}</strong>
            {getStepData() && (
              <span> | მიმდინარე წყვილი: <code>{getStepData().char}</code> × <code>{getStepData().keyChar}</code></span>
            )}
          </p>
        </div>
      </div>
    </div>
  );
}

export default VigenereCipher;

⚠️ 关键注意事项与最佳实践

  • 避免阻塞主线程:切勿在 useEffect 中使用 while 循环或同步密集计算。务必用 setTimeout/setInterval 分帧执行,保障 UI 流畅。
  • 状态原子性:stepIndex 是唯一驱动高亮的单一数据源,所有视觉状态(行/列索引、颜色、文本提示)均由此派生,杜绝多状态不同步风险。
  • 空格与边界处理:明文中的空格不参与加密,但需保留在输出中;stepIndex 应跳过空格计数,确保「第 N 个有效字符」逻辑准确。
  • 可访问性增强:为高亮单元格添加 aria-label(如 aria-label="რიგი ა, სვეტი კ — შედეგი: ლ"),提升屏幕阅读器支持。
  • 性能优化(大型表):若字母表扩展至 100+ 字符,建议改用 CSS Grid + grid-area 定位 + className 切换,避免内联样式大量重绘。

✅ 总结

通过将「算法执行」与「UI 渲染」解耦,并以 stepIndex 作为唯一真值来源,我们实现了真正符合教学逻辑的维吉尼亚密码可视化:每一步都明确、可控、可逆、可调试。这种模式不仅适用于密码学演示,还可迁移至 DFS/BFS 路径高亮、排序算法动画、状态机流转等任何需要「过程可见性」的交互场景。记住:好的动画不是炫技,而是让抽象逻辑变得可触摸、可理解。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

102

2023.09.25

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

673

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

673

2023.08.10

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

446

2023.08.14

PHP 高并发与性能优化
PHP 高并发与性能优化

本专题聚焦 PHP 在高并发场景下的性能优化与系统调优,内容涵盖 Nginx 与 PHP-FPM 优化、Opcode 缓存、Redis/Memcached 应用、异步任务队列、数据库优化、代码性能分析与瓶颈排查。通过实战案例(如高并发接口优化、缓存系统设计、秒杀活动实现),帮助学习者掌握 构建高性能PHP后端系统的核心能力。

105

2025.10.16

PHP 数据库操作与性能优化
PHP 数据库操作与性能优化

本专题聚焦于PHP在数据库开发中的核心应用,详细讲解PDO与MySQLi的使用方法、预处理语句、事务控制与安全防注入策略。同时深入分析SQL查询优化、索引设计、慢查询排查等性能提升手段。通过实战案例帮助开发者构建高效、安全、可扩展的PHP数据库应用系统。

93

2025.11.13

JavaScript 性能优化与前端调优
JavaScript 性能优化与前端调优

本专题系统讲解 JavaScript 性能优化的核心技术,涵盖页面加载优化、异步编程、内存管理、事件代理、代码分割、懒加载、浏览器缓存机制等。通过多个实际项目示例,帮助开发者掌握 如何通过前端调优提升网站性能,减少加载时间,提高用户体验与页面响应速度。

31

2025.12.30

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

12

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

7

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 5万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号