使用React创建虚拟键盘
在这篇文章中,我们将使用ReactJS创建虚拟键盘。该项目基本上实现了功能组件并相应地管理状态。用户可以通过点击键盘上的按键与虚拟键盘进行交互,界面将相应地作出响应,从而实现无缝的输入体验。按键和字符输入的逻辑是使用JSX实现的。
让我们来看看最终的项目是什么样子:
使用的技术/先决条件:
- ReactJS
- CSS
- JSX
- React中的功能组件
方法/功能:
虚拟键盘是一种基于软件的输入界面,模拟数字设备上的物理键盘。其主要功能包括:
- 用户输入模拟: 它允许用户通过点击虚拟键来输入文本和命令,复制物理键盘的功能。
- 可访问性: 它们提高了身体残障人士的可访问性,提供了替代的输入方法。
- 安全性: 虚拟键盘可用于安全数据输入,防止键盘记录器和其他安全威胁。
- 集成: 它们可以集成到各种应用程序中,包括信息亭、触摸屏设备和软件界面,以便促进文本输入和交互。
项目结构:
创建应用程序的步骤:
步骤1: 使用命令设置React项目
npx create-react-app <<name of project>>
步骤2: 使用以下步骤导航到项目文件夹:
cd <<Name_of_project>>
步骤3: 在”components”文件夹中创建两个新文件,分别命名为Keyboard.js和Keyboard.css。
步骤4: 在public文件夹的index.html文件中使用以下命令导入图标包。
<link rel=”stylesheet” href=”https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css” integrity=”sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==” crossorigin=”anonymous” referrerpolicy=”no-referrer” />
示例: 在相应的文件中编写以下代码
- index.html: 这是一个自动创建的文件,在public文件夹中,我们只需要在它的标签中导入图标包。
- App.js: 此文件导入键盘组件并导出它。
- Keyboard.js: 此文件包含虚拟键盘、按键和输入文本区块的逻辑,带有状态变量,计算机选择一个值。
- Keyboard.css: 此文件包含虚拟键盘元素的设计。
// App.js
import './App.css';
import Keyboard from './components/Keyboard';
function App() {
return (
<div className="App">
<Keyboard/>
</div>
);
}
export default App;
// keyboard.js
import React, { useState } from 'react';
import './Keyboard.css';
export default function Keyboard() {
const [inputText, setInputText] = useState('');
const [isCaps, setIsCaps] = useState(false);
const [isShift, setIsShift] = useState(false);
const handleKeyClick = (key) => {
if (key === 'Enter') {
handleEnterKey();
}
else if(key === "Ctrl" || key === "Alt" || key === '<' || key === '>')
{
}else if (key === ' ') {
handleSpaceKey();
} else if (key === 'Caps Lock') {
handleCapsLock();
} else if (key === '<i className="fa-solid fa-delete-left"></i>') {
handleDeleteKey();
} else if (key === 'Shift') {
handleShiftKey();
} else if (key === 'Tab') {
handleTabKey();
} else {
handleRegularKey(key);
}
};
const handleSpaceKey = () => {
const newContent = inputText + '\u00A0';
setInputText(newContent);
};
const handleEnterKey = () => {
const newContent = inputText + '\n';
setInputText(newContent);
};
const handleCapsLock = () => {
const updatedCaps = !isCaps;
setIsCaps(updatedCaps);
const keys = document.querySelectorAll('.key');
keys.forEach((key) => {
const firstSpanElement = key.querySelector('span:first-child');
if (firstSpanElement) {
const keyText = firstSpanElement.innerText.toLowerCase();
if (
!['shift', 'alt', 'ctrl', 'enter', 'caps lock', 'tab']
.includes(keyText)) {
firstSpanElement.innerText =
((updatedCaps && isShift) || (!updatedCaps && !isShift))
? keyText.toLowerCase() : keyText.toUpperCase();
}
if (keyText === 'caps lock') {
firstSpanElement.parentElement.style.backgroundColor =
(updatedCaps) ? 'blue' : '#445760';
}
}
});
};
const handleTabKey = () => {
const newContent = inputText + ' ';
setInputText(newContent);
};
const handleDeleteKey = () => {
if (inputText.length === 0) {
return;
}
const newContent = inputText.slice(0, inputText.length - 1);
setInputText(newContent);
};
const handleShiftKey = () => {
const updatedShift = !isShift;
setIsShift(updatedShift);
const keys = document.querySelectorAll('.key');
keys.forEach((key) => {
const firstSpanElement = key.querySelector('span:first-child');
if (firstSpanElement) {
const keyText = firstSpanElement.innerText.toLowerCase();
if (
!['shift', 'alt', 'ctrl', 'enter', 'caps lock', 'tab'].
includes(keyText)) {
firstSpanElement.innerText =
((updatedShift && isCaps) || (!updatedShift && !isCaps))
? keyText.toLowerCase() : keyText.toUpperCase();
}
if (keyText === 'shift') {
firstSpanElement.parentElement.style.backgroundColor =
(updatedShift) ? 'blue' : '#445760';
}
}
});
}
const handleRegularKey = (key) => {
const keys = key.split(/[._]/);
let newContent;
if (keys.length > 1) {
if (isShift) {
if (keys.length === 3) {
if (keys[0] === '>') newContent = inputText + '>';
else newContent = inputText + '_';
}
else newContent = inputText + keys[0];
} else {
if (keys.length === 3) {
if (keys[0] === '>') newContent = inputText + '.';
else newContent = inputText + '-';
}
else newContent = inputText + keys[1];
}
} else {
let character = ((isShift && isCaps) || (!isShift && !isCaps))
? key.toLowerCase() : key.toUpperCase();
newContent = inputText + character;
}
setInputText(newContent);
};
return (
<div className='keyboard'>
<div className="textcontainer">
<pre>{inputText}</pre>
</div>
<div className="keyboardcontainer">
<div className="container">
<div className="row">
{['~.`', '!.1', '@.2', '#.3', '$.4', '%.5',
'^.6', '&.7', '*.8', '(.9', ').0', '_.-', '+.=',
'<i className="fa-solid fa-delete-left"></i>']
.map((keyvalue) =>
(
<div key={keyvalue} className='key'
onClick={() => handleKeyClick(keyvalue)}>
{keyvalue.includes('.') ? (
keyvalue.split('.').map((part, index) => (
<span key={index}>{part}</span>
))
) : (
keyvalue ===
'<i className="fa-solid fa-delete-left"></i>'
? (
<i className="fa-solid fa-delete-left"></i>
) : (
<span>{keyvalue}</span>
)
)}
</div>
))}
</div>
<div className="row">
{['Tab', 'q', 'w', 'e', 'r', 't', 'y',
'u', 'i', 'o', 'p', '{_[', '}_]', '|_\\']
.map((keyvalue) => (
<div key={keyvalue} className='key'
onClick={() => handleKeyClick(keyvalue)}>
{keyvalue.includes('_') ? (
keyvalue.split('_').map((part, index) => (
<span key={index}>{part}</span>
))
) : (
<span>{keyvalue}</span>
)}
</div>
))}
</div>
<div className="row">
{['Caps Lock', 'a', 's', 'd', 'f', 'g', 'h',
'j', 'k', 'l', ':_;', `"_'`, 'Enter']
.map((keyvalue) => (
<div key={keyvalue} className='key'
onClick={() => handleKeyClick(keyvalue)}>
{keyvalue.includes('_') ? (
keyvalue.split('_').map((part, index) => (
<span key={index}>{part}</span>
))
) : (
<span>{keyvalue}</span>
)}
</div>
))}
</div>
<div className="row">
{['Shift', 'z', 'x', 'c', 'v', 'b', 'n', 'm',
'<_,', '>_.', '?_/', 'Shift'].map((keyvalue, index) => (
<div key={index} className='key'
onClick={() => handleKeyClick(keyvalue)}>
{keyvalue.includes('_') ? (
keyvalue.split('_').map((part, index) => (
<span key={index}>{part}</span>
))
) : (
<span>{keyvalue}</span>
)}
</div>
))}
</div>
<div className="row">
{['Ctrl', 'Alt', ' ', 'Ctrl', 'Alt', '<', '>']
.map((keyvalue, index) => (
<div key={index} className='key'
onClick={() => handleKeyClick(keyvalue)}>
<span>{keyvalue}</span>
</div>
))}
</div>
</div>
</div>
</div>
)
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/
css/all.min.css" integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE
+4aHK8yyUHUSCcJHgXloTyT2A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
CSS
/* keyboard.css */
.keyboard {
display: flex;
height: 100vh;
flex-direction: column;
justify-content: center;
align-items: center;
}
.textcontainer {
width: 1018px;
height: 100px;
border: 1px solid rgba(0,0,0,0.25);
overflow: auto;
border-radius: 4px;
}
.textcontainer pre{
text-align: left;
display: block;
width: calc(100% - 40px);
height: calc(100% - 40px);
margin: 0;
padding: 20px;
font-size: 20px;
}
.keyboardcontainer {
width: 90%;
display: flex;
justify-content: center;
margin-top: 15px;
}
.container {
padding: 20px 20px;
display: flex;
flex-direction: column;
max-width: 980px;
justify-content: center;
align-items: center;
border-radius: 7px;
background: #202124;
}
.row {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
}
.key {
display: flex;
width: 60px;
height: 60px;
margin: 5px;
justify-content: center;
flex-direction: column;
align-items: center;
background-color: #445760;
border-radius: 4px;
color: #ffffff;
font-size: 16px;
cursor: pointer;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
transition: background-color ease-in-out 0.15s;
}
.key:hover{
background-color: #3c4d56;
}
.row:first-child .key:first-child{
width: 40px;
}
.row:first-child .key:last-child{
width: 80px;
}
.row:nth-child(3) .key:first-child{
width: 95px;
}
.row:nth-child(3) .key:last-child{
width: 95px;
}
.row:nth-child(4) .key:first-child{
width: 130px;
}
.row:nth-child(4) .key:last-child{
width: 130px;
}
.row:nth-child(5) .key:nth-child(3){
width: 550px;
}
运行应用程序的步骤:
1. 在终端中键入以下命令。
npm start
2. 打开网络浏览器并输入以下URL
http://localhost:3000/
输出: