使用React的活动倒计时计时器
活动倒计时计时器是一个应用程序,您可以在其中创建一个带有名称、日期和类别的事件,并创建一个卡片,显示事件剩余时间。在到达当天这个时间后,它将通知您。
该应用程序将提供启动、停止和暂停倒计时计时器的选项。项目将包含优雅的用户界面来显示倒计时计时器。所以让我们开始构建它。
最终输出的预览:
先决条件和技术:
- React
- Bootstrap
- JSX
方法:
我们将使用React构建一个单页面应用程序,该应用程序将在主页上显示倒计时器。事件倒计时器将作为React的单独组件创建。然后在应用程序文件中渲染该组件。将添加Bootstrap以显示事件倒计时器的选项。计时器将通过从用户获取输入来开始计时。
功能:
- 添加计时器: 这将根据需要添加多个倒计时器。设置倒计时器的标题、类别和时间。
- 移除计时器: 这将移除一个倒计时器。
- 计算时间: calculateTimeRemaining将计算每个计时器的剩余时间。
- 格式化时间: formatTime将把时间从秒转换为天、小时、分钟和秒。
- 添加时间: addTimer和removeTimer将通过更新计时器状态来添加和移除计时器。
最后,我们将使用useEffect设置具有时间的间隔。时间将在间隔内更新。当时间达到0时,isRunning状态设置为false。现在我们可以添加渲染代码了。渲染代码将包括用于以秒为单位输入时间的输入字段。这将在我们的代码中更新时间状态。然后,我们将在division中显示当前时间。分别为三个功能使用三个按钮。
创建应用程序的步骤:
步骤1: 首先,我们需要使用以下命令创建React应用程序
npx create-react-app <<Project_Name>>
步骤2: 前往文件夹
cd <<Project_Name>>
步骤3: 使用以下命令安装Bootstrap来设置CSS。
npm install bootstrap
步骤4: 在src目录下创建一个名为components的文件夹,然后在这个文件夹内创建Countdown.js和Countdown.css两个文件。
项目结构:
示例: 在这里我们创建了两个JS文件App.js,Countdown.js和一个CSS文件来样式化界面。
// src/App.js
import './App.css';
import Countdown from './components/Countdown';
function App() {
return (
<div className="App">
<Countdown />
</div>
);
}
export default App;
// src/components/Countdown.js
import React, { useState, useEffect } from "react";
import "bootstrap/dist/css/bootstrap.css";
import "./Countdown.css";
function Countdown() {
const [timers, setTimers] = useState([]);
const [newTimerTitle, setNewTimerTitle] = useState("");
const [newTimerCategory, setNewTimerCategory] = useState("");
const [newTimerDateTime, setNewTimerDateTime] = useState("");
const categoryColors = {
Meeting: "bg-primary",
Birthday: "bg-danger",
Reminder: "bg-success",
};
useEffect(() => {
const intervalIds = {};
const updateTimers = () => {
setTimers((prevTimers) =>
prevTimers.map((timer) => {
const targetTime = new Date(timer.targetDateTime)
.getTime();
const currentTime = new Date().getTime();
const timeRemaining = Math.max(
Math.floor((targetTime - currentTime) / 1000),
0
);
if (timeRemaining === 0) {
clearInterval(intervalIds[timer.id]);
return {
...timer, isRunning: false, timeRemaining: 0 };
}
return { ...timer, timeRemaining };
})
);
};
timers.forEach((timer) => {
if (timer.isRunning && timer.timeRemaining > 0) {
intervalIds[timer.id] = setInterval(updateTimers, 1000);
}
});
return () => {
Object.values(intervalIds).forEach((intervalId) =>
clearInterval(intervalId)
);
};
}, [timers]);
const removeTimer = (timerId) => {
setTimers((prevTimers) =>
prevTimers.filter((timer) => timer.id !== timerId)
);
};
const calculateTimeRemaining = (targetTime) => {
const currentTime = new Date().getTime();
const timeDifference = targetTime - currentTime;
const secondsRemaining =
Math.max(Math.floor(timeDifference / 1000), 0);
return secondsRemaining;
};
const formatTimeRemaining = (seconds) => {
const days = Math.floor(seconds / (3600 * 24));
const hours = Math.floor((seconds % (3600 * 24)) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const remainingSeconds = seconds % 60;
return {
days,
hours,
minutes,
seconds: remainingSeconds,
};
};
const addTimer = () => {
if (!newTimerTitle || !newTimerCategory || !newTimerDateTime)
return;
// Convert to milliseconds since epoch
const targetDateTime = new Date(newTimerDateTime).getTime();
const newTimer = {
id: timers.length + 1,
category: newTimerCategory,
targetDateTime,
// Calculate time remaining here
timeRemaining: calculateTimeRemaining(targetDateTime),
isRunning: true,
title: newTimerTitle,
showTitleInput: false,
};
setTimers([...timers, newTimer]);
setNewTimerTitle("");
setNewTimerCategory("");
setNewTimerDateTime("");
};
return (
<div className="countdown-container">
<div className="main-container">
<div className="input-container m-3">
<h1 className="text-center text-success">
GeeksForGeeks Countdown Timer
</h1>
<input
type="text"
className="form-control m-2"
placeholder="Timer Title"
value={newTimerTitle}
onChange={
(e) => setNewTimerTitle(e.target.value)
}
/>
<select
className="form-select m-2"
value={newTimerCategory}
onChange={
(e) => setNewTimerCategory(e.target.value)
}
>
<option value="">Select a Category</option>
<option value="Meeting">Meeting</option>
<option value="Birthday">Birthday</option>
<option value="Reminder">Reminder</option>
</select>
<input
className="form-control m-2"
type="datetime-local"
value={newTimerDateTime}
onChange={
(e) => setNewTimerDateTime(e.target.value)
}
/>
<button
className="btn btn-primary m-2"
onClick={addTimer}
disabled={
!newTimerTitle ||
!newTimerCategory ||
!newTimerDateTime
}
>
Add Timer
</button>
</div>
<div className="timers-div m-auto d-flex">
{timers.map((timer) => {
const timeRemaining = formatTimeRemaining(
timer.timeRemaining
);
return (
<div
key={timer.id}
className={`card m-4 ${
categoryColors[timer.category] || ""
}`}
>
<h3 className="card-title m-2 text-light">
{timer.title}
</h3>
<h4 className="card-title m-2 text-dark">
{timer.category}
</h4>
<div className="card-body d-flex">
{timeRemaining.days > 0 && (
<div className="container
bg-light
text-dark
rounded m-2">
<div>
<h1>
<strong>
{timeRemaining.days}
</strong>
</h1>
</div>
<div>days </div>
</div>
)}
<div className="container bg-light
text-dark rounded m-2">
<div>
<h1>
<strong>
{timeRemaining.hours}
</strong>
</h1>
</div>
<div>hours </div>
</div>
<div className="container
bg-light
text-dark
rounded m-2">
<div>
<h1>
<strong>
{timeRemaining.minutes}
</strong>
</h1>
</div>
<div>minutes </div>
</div>
<div className="container
bg-light
text-dark
rounded m-2">
<div>
<h1>
<strong>
{timeRemaining.seconds}
</strong>
</h1>
</div>
<div>seconds </div>
</div>
</div>
<button
className="btn btn-dark m-2"
onClick={() => removeTimer(timer.id)}
disabled={timer.timeRemaining <= 0}
>
Remove
</button>
</div>
);
})}
</div>
</div>
</div>
);
}
export default Countdown;
CSS
body {
background-color: rgb(230, 227, 223);
}
.main-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: auto;
}
.timers {
height: fit-content;
margin: auto;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.card {
display: flex;
flex-direction: column;
}
运行应用的步骤:
步骤1: 在项目文件夹中打开终端并运行以下命令
npm start
步骤2: 在浏览器中打开以下链接
http://localhost:3000/
输出: