React + JavaScript 实现可拖拽进度条

[复制链接]
发表于 2025-9-23 06:07:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
React + JavaScript 实现可拖拽进度条

下面是一个使用 React (JavaScript) 实现的可拖拽时间进度条组件。
代码
  1. import React, { useState, useRef, useEffect } from 'react';
  2. import './TimeProgressBar.css';
  3. const TimeProgressBar = ({
  4.   totalTime = 600, // 默认10分钟 (600秒)
  5.   initialTime = 0,
  6.   onChange,
  7. }) => {
  8.   const [currentTime, setCurrentTime] = useState(initialTime);
  9.   const [isDragging, setIsDragging] = useState(false);
  10.   const progressBarRef = useRef(null);
  11.   // 格式化时间 (秒 → HH:MM:SS)
  12.   const formatTime = (seconds) => {
  13.     const hrs = Math.floor(seconds / 3600);
  14.     const mins = Math.floor((seconds % 3600) / 60);
  15.     const secs = Math.floor(seconds % 60);
  16.    
  17.     return [
  18.       hrs.toString().padStart(2, '0'),
  19.       mins.toString().padStart(2, '0'),
  20.       secs.toString().padStart(2, '0')
  21.     ].join(':');
  22.   };
  23.   // 计算进度百分比
  24.   const getPercentage = () => {
  25.     return Math.min((currentTime / totalTime) * 100, 100);
  26.   };
  27.   // 更新进度
  28.   const updateProgress = (time) => {
  29.     const newTime = Math.max(0, Math.min(time, totalTime));
  30.     setCurrentTime(newTime);
  31.     if (onChange) onChange(newTime);
  32.   };
  33.   // 处理进度条点击
  34.   const handleProgressBarClick = (e) => {
  35.     if (progressBarRef.current) {
  36.       const rect = progressBarRef.current.getBoundingClientRect();
  37.       const pos = (e.clientX - rect.left) / rect.width;
  38.       updateProgress(pos * totalTime);
  39.     }
  40.   };
  41.   // 处理拖拽开始
  42.   const handleDragStart = (e) => {
  43.     setIsDragging(true);
  44.     e.preventDefault();
  45.   };
  46.   // 处理拖拽移动
  47.   const handleDragMove = (e) => {
  48.     if (!isDragging || !progressBarRef.current) return;
  49.    
  50.     const rect = progressBarRef.current.getBoundingClientRect();
  51.     const pos = (e.clientX - rect.left) / rect.width;
  52.     updateProgress(pos * totalTime);
  53.   };
  54.   // 处理拖拽结束
  55.   const handleDragEnd = () => {
  56.     setIsDragging(false);
  57.   };
  58.   // 添加/移除事件监听器
  59.   useEffect(() => {
  60.     document.addEventListener('mousemove', handleDragMove);
  61.     document.addEventListener('mouseup', handleDragEnd);
  62.     document.addEventListener('touchmove', handleDragMove);
  63.     document.addEventListener('touchend', handleDragEnd);
  64.     return () => {
  65.       document.removeEventListener('mousemove', handleDragMove);
  66.       document.removeEventListener('mouseup', handleDragEnd);
  67.       document.removeEventListener('touchmove', handleDragMove);
  68.       document.removeEventListener('touchend', handleDragEnd);
  69.     };
  70.   }, [isDragging]);
  71.   return (
  72.     <div className="time-progress-container">
  73.       <div
  74.         className="progress-bar"
  75.         ref={progressBarRef}
  76.         onClick={handleProgressBarClick}
  77.       >
  78.         <div
  79.           className="progress-fill"
  80.           style={{ width: `${getPercentage()}%` }}
  81.         />
  82.         <div
  83.           className="progress-thumb"
  84.           style={{ left: `${getPercentage()}%` }}
  85.           onMouseDown={handleDragStart}
  86.           onTouchStart={handleDragStart}
  87.         />
  88.       </div>
  89.       <div className="time-display">
  90.         <span className="current-time">{formatTime(currentTime)}</span>
  91.         <span className="total-time">{formatTime(totalTime)}</span>
  92.       </div>
  93.     </div>
  94.   );
  95. };
  96. export default TimeProgressBar;
复制代码
CSS 样式
  1. .time-progress-container {
  2.   width: 100%;
  3.   max-width: 600px;
  4.   margin: 0 auto;
  5.   padding: 10px 0;
  6. }
  7. .progress-bar {
  8.   position: relative;
  9.   height: 8px;
  10.   background-color: #e0e0e0;
  11.   border-radius: 4px;
  12.   cursor: pointer;
  13.   margin-bottom: 10px;
  14. }
  15. .progress-fill {
  16.   position: absolute;
  17.   height: 100%;
  18.   background-color: #4285f4;
  19.   border-radius: 4px;
  20.   transition: width 0.1s ease;
  21. }
  22. .progress-thumb {
  23.   position: absolute;
  24.   top: 50%;
  25.   transform: translate(-50%, -50%);
  26.   width: 16px;
  27.   height: 16px;
  28.   background-color: #4285f4;
  29.   border-radius: 50%;
  30.   cursor: grab;
  31.   z-index: 2;
  32.   transition: left 0.1s ease;
  33. }
  34. .progress-thumb:active {
  35.   cursor: grabbing;
  36. }
  37. .time-display {
  38.   display: flex;
  39.   justify-content: space-between;
  40.   font-size: 14px;
  41.   color: #666;
  42. }
复制代码
使用
  1. import React from 'react';
  2. import TimeProgressBar from './TimeProgressBar';
  3. function App() {
  4.   const handleTimeChange = (time) => {
  5.     console.log('当前时间:', time);
  6.   };
  7.   return (
  8.     <div style={{ padding: '20px', maxWidth: '600px', margin: '0 auto' }}>
  9.       <h2>视频播放器</h2>
  10.       <TimeProgressBar
  11.         totalTime={720} // 12分钟
  12.         initialTime={120} // 从2分钟开始
  13.         onChange={handleTimeChange}
  14.       />
  15.     </div>
  16.   );
  17. }
  18. export default App;
复制代码
功能特点


  • 完全可拖拽:可以通过鼠标或触摸拖动滑块
  • 点击跳转:点击进度条恣意位置可跳转到对应时间点
  • 相应式计划:适应差别屏幕尺寸
  • 平滑过渡:添加了CSS过渡效果
  • 触摸支持:支持移动装备触摸操纵
  • 时间表现:表现当前时间和总时间
  • 回调函数:提供onChange回调,其时间厘革时触发
自界说选项

你可以通过以下props自界说组件:

  • totalTime: 设置总时间(秒)
  • initialTime: 设置初始时间(秒)
  • onChange: 时间厘革时的回调函数

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表