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

// 类型定义
type MotionDataPoint = {
  t: number; // 时间 (s)
  v: number; // 速度 (m/s)
  a: number; // 加速度 (m/s²)
};

type MotionProfile = 'constantAcceleration' | 'zeroAcceleration' | 'decelerating';

const AccelerationVelocityChart: React.FC = () => {
  // 状态管理
  const [timeRange, setTimeRange] = useState<number>(10); // 总时间 (s)
  const [acceleration, setAcceleration] = useState<number>(2); // 加速度 (m/s²)
  const [initialVelocity, setInitialVelocity] = useState<number>(0); // 初速度 (m/s)
  const [profile, setProfile] = useState<MotionProfile>('constantAcceleration');
  const [isPlaying, setIsPlaying] = useState<boolean>(false);
  const [currentTime, setCurrentTime] = useState<number>(0);
  const [chartData, setChartData] = useState<MotionDataPoint[]>([]);
  
  const animationRef = useRef<number>(0);
  const startTimeRef = useRef<number>(0);
  const durationRef = useRef<number>(0);

  // 生成图表数据（静态）
  const generateData = (): MotionDataPoint[] => {
    const data: MotionDataPoint[] = [];
    const dt = 0.2;
    
    for (let t = 0; t <= timeRange; t += dt) {
      let v = 0;
      let a = 0;
      
      switch (profile) {
        case 'constantAcceleration':
          a = acceleration;
          v = initialVelocity + a * t;
          break;
        case 'zeroAcceleration':
          a = 0;
          v = initialVelocity;
          break;
        case 'decelerating':
          a = -Math.abs(acceleration);
          v = Math.max(0, initialVelocity + a * t);
          break;
      }
      
      data.push({ t, v, a });
    }
    
    return data;
  };

  // 初始化图表数据
  useEffect(() => {
    setChartData(generateData());
    setCurrentTime(0);
  }, [timeRange, acceleration, initialVelocity, profile]);

  // 动画逻辑
  useEffect(() => {
    if (!isPlaying) return;

    const animate = (timestamp: number) => {
      if (!startTimeRef.current) startTimeRef.current = timestamp;
      const elapsed = timestamp - startTimeRef.current;
      durationRef.current = timeRange * 1000; // 转换为毫秒
      
      const progress = (elapsed % durationRef.current) / durationRef.current;
      const t = progress * timeRange;
      
      setCurrentTime(t);
      animationRef.current = requestAnimationFrame(animate);
    };

    animationRef.current = requestAnimationFrame(animate);

    return () => {
      cancelAnimationFrame(animationRef.current);
      startTimeRef.current = 0;
    };
  }, [isPlaying, timeRange]);

  // 停止动画
  const stopAnimation = () => {
    setIsPlaying(false);
    cancelAnimationFrame(animationRef.current);
    startTimeRef.current = 0;
  };

  // 重置动画
  const resetAnimation = () => {
    stopAnimation();
    setCurrentTime(0);
  };

  // 获取当前时刻的数据点（用于高亮）
  const getCurrentPoint = (): MotionDataPoint | null => {
    if (chartData.length === 0) return null;
    
    // 找到最接近 currentTime 的点
    const closest = chartData.reduce((prev, curr) => 
      Math.abs(curr.t - currentTime) < Math.abs(prev.t - currentTime) ? curr : prev
    );
    
    return closest;
  };

  const currentPoint = getCurrentPoint();

  // 图表尺寸
  const width = 800;
  const height = 400;
  const margin = { top: 40, right: 30, bottom: 60, left: 60 };
  const chartWidth = width - margin.left - margin.right;
  const chartHeight = height - margin.top - margin.bottom;

  // 坐标映射函数
  const xScale = (t: number): number => margin.left + (t / timeRange) * chartWidth;
  const vScale = (v: number): number => {
    const maxV = Math.max(...chartData.map(d => d.v), initialVelocity + acceleration * timeRange, 0);
    const minV = Math.min(...chartData.map(d => d.v), 0);
    const range = Math.max(maxV - minV, 1);
    return margin.top + chartHeight - ((v - minV) / range) * chartHeight;
  };
  const aScale = (a: number): number => {
    const maxA = Math.max(...chartData.map(d => d.a), acceleration, 0);
    const minA = Math.min(...chartData.map(d => d.a), -Math.abs(acceleration), 0);
    const range = Math.max(maxA - minA, 1);
    return margin.top + chartHeight - ((a - minA) / range) * chartHeight;
  };

  // 绘制速度曲线
  const velocityPath = chartData.map((d, i) => {
    if (i === 0) return `M ${xScale(d.t)} ${vScale(d.v)}`;
    return `L ${xScale(d.t)} ${vScale(d.v)}`;
  }).join(' ');

  // 绘制加速度曲线
  const accelerationPath = chartData.map((d, i) => {
    if (i === 0) return `M ${xScale(d.t)} ${aScale(d.a)}`;
    return `L ${xScale(d.t)} ${aScale(d.a)}`;
  }).join(' ');

  // 获取图例颜色
  const getVelocityColor = () => '#3b82f6'; // blue-500
  const getAccelerationColor = () => '#ef4444'; // red-500

  return (
    <div className="p-6 bg-gray-50 min-h-screen flex flex-col items-center">
      <h1 className="text-2xl font-bold text-gray-800 mb-2">加速度与速度的函数图像对比</h1>
      <p className="text-gray-600 mb-6">七年级数学 · 运动学基础</p>

      {/* 控制面板 */}
      <div className="bg-white rounded-xl shadow-md p-6 mb-6 w-full max-w-4xl">
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              总时间 (s)
            </label>
            <input
              type="range"
              min="2"
              max="20"
              step="0.5"
              value={timeRange}
              onChange={(e) => setTimeRange(parseFloat(e.target.value))}
              className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-blue-600"
            />
            <div className="flex justify-between text-xs text-gray-500 mt-1">
              <span>2</span>
              <span>{timeRange.toFixed(1)}</span>
              <span>20</span>
            </div>
          </div>

          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              加速度 (m/s²)
            </label>
            <input
              type="range"
              min="-5"
              max="5"
              step="0.5"
              value={acceleration}
              onChange={(e) => setAcceleration(parseFloat(e.target.value))}
              className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-blue-600"
            />
            <div className="flex justify-between text-xs text-gray-500 mt-1">
              <span>-5</span>
              <span>{acceleration.toFixed(1)}</span>
              <span>5</span>
            </div>
          </div>

          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              初速度 (m/s)
            </label>
            <input
              type="range"
              min="0"
              max="20"
              step="0.5"
              value={initialVelocity}
              onChange={(e) => setInitialVelocity(parseFloat(e.target.value))}
              className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-blue-600"
            />
            <div className="flex justify-between text-xs text-gray-500 mt-1">
              <span>0</span>
              <span>{initialVelocity.toFixed(1)}</span>
              <span>20</span>
            </div>
          </div>

          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              运动类型
            </label>
            <select
              value={profile}
              onChange={(e) => setProfile(e.target.value as MotionProfile)}
              className="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
            >
              <option value="constantAcceleration">匀加速运动</option>
              <option value="zeroAcceleration">匀速运动</option>
              <option value="decelerating">匀减速运动</option>
            </select>
          </div>
        </div>

        {/* 动画控制按钮 */}
        <div className="flex flex-wrap gap-3 mb-6">
          <button
            onClick={() => setIsPlaying(!isPlaying)}
            className={`px-4 py-2 rounded-lg font-medium transition-colors ${
              isPlaying 
                ? 'bg-red-500 hover:bg-red-600 text-white' 
                : 'bg-green-500 hover:bg-green-600 text-white'
            }`}
          >
            {isPlaying ? '⏸️ 暂停' : '▶️ 播放'}
          </button>
          <button
            onClick={resetAnimation}
            className="px-4 py-2 bg-gray-500 hover:bg-gray-600 text-white rounded-lg font-medium transition-colors"
          >
            🔄 重置
          </button>
          <div className="flex items-center text-sm text-gray-600">
            <span className="mr-2">当前时间:</span>
            <span className="font-mono bg-gray-100 px-2 py-1 rounded">
              {currentTime.toFixed(1)} s
            </span>
          </div>
        </div>

        {/* 当前状态显示 */}
        {currentPoint && (
          <div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
            <h3 className="font-medium text-blue-800 mb-2">当前时刻状态</h3>
            <div className="grid grid-cols-2 md:grid-cols-4 gap-2 text-sm">
              <div>
                <span className="text-gray-600">时间:</span>
                <span className="ml-1 font-mono">{currentPoint.t.toFixed(1)} s</span>
              </div>
              <div>
                <span className="text-gray-600">速度:</span>
                <span className="ml-1 font-mono text-blue-600">{currentPoint.v.toFixed(1)} m/s</span>
              </div>
              <div>
                <span className="text-gray-600">加速度:</span>
                <span className="ml-1 font-mono text-red-600">{currentPoint.a.toFixed(1)} m/s²</span>
              </div>
              <div>
                <span className="text-gray-600">运动类型:</span>
                <span className="ml-1 capitalize">{profile.replace(/([A-Z])/g, ' $1').trim()}</span>
              </div>
            </div>
          </div>
        )}
      </div>

      {/* 图表区域 */}
      <div className="bg-white rounded-xl shadow-md p-6 w-full max-w-4xl">
        <h2 className="text-xl font-semibold text-gray-800 mb-4">速度与加速度随时间变化图</h2>
        
        <div className="relative">
          <svg width={width} height={height} className="border border-gray-200 rounded-lg">
            {/* 坐标轴 */}
            <line
              x1={margin.left}
              y1={height - margin.bottom}
              x2={width - margin.right}
              y2={height - margin.bottom}
              stroke="#94a3b8"
              strokeWidth="2"
            />
            <line
              x1={margin.left}
              y1={margin.top}
              x2={margin.left}
              y2={height - margin.bottom}
              stroke="#94a3b8"
              strokeWidth="2"
            />

            {/* X轴刻度和标签 */}
            {Array.from({ length: Math.floor(timeRange) + 1 }).map((_, i) => (
              <g key={i}>
                <line
                  x1={xScale(i)}
                  y1={height - margin.bottom}
                  x2={xScale(i)}
                  y2={height - margin.bottom + 5}
                  stroke="#94a3b8"
                  strokeWidth="1"
                />
                <text
                  x={xScale(i)}
                  y={height - margin.bottom + 20}
                  textAnchor="middle"
                  className="text-xs fill-gray-600"
                >
                  {i}
                </text>
              </g>
            ))}

            {/* Y轴刻度和标签 - 速度 */}
            {(() => {
              const maxV = Math.max(...chartData.map(d => d.v), initialVelocity + acceleration * timeRange, 0);
              const minV = Math.min(...chartData.map(d => d.v), 0);
              const range = Math.max(maxV - minV, 1);
              const step = Math.ceil(range / 5);
              const labels = Array.from(
                { length: 6 },
                (_, i) => minV + i * step
              ).filter(v => v <= maxV);
              
              return labels.map((v, i) => (
                <g key={i}>
                  <line
                    x1={margin.left - 5}
                    y1={vScale(v)}
                    x2={margin.left}
                    y2={vScale(v)}
                    stroke="#94a3b8"
                    strokeWidth="1"
                  />
                  <text
                    x={margin.left - 10}
                    y={vScale(v) + 4}
                    textAnchor="end"
                    className="text-xs fill-gray-600"
                  >
                    {v.toFixed(0)}
                  </text>
                </g>
              ));
            })()}

            {/* Y轴刻度和标签 - 加速度 */}
            {(() => {
              const maxA = Math.max(...chartData.map(d => d.a), acceleration, 0);
              const minA = Math.min(...chartData.map(d => d.a), -Math.abs(acceleration), 0);
              const range = Math.max(maxA - minA, 1);
              const step = Math.ceil(range / 5);
              const labels = Array.from(
                { length: 6 },
                (_, i) => minA + i * step
              ).filter(a => a <= maxA);
              
              return labels.map((a, i) => (
                <g key={i}>
                  <line
                    x1={width - margin.right + 5}
                    y1={aScale(a)}
                    x2={width - margin.right}
                    y2={aScale(a)}
                    stroke="#94a3b8"
                    strokeWidth="1"
                  />
                  <text
                    x={width - margin.right + 15}
                    y={aScale(a) + 4}
                    textAnchor="start"
                    className="text-xs fill-gray-600"
                  >
                    {a.toFixed(0)}
                  </text>
                </g>
              ));
            })()}

            {/* 速度曲线 */}
            <path
              d={velocityPath}
              fill="none"
              stroke={getVelocityColor()}
              strokeWidth="3"
              strokeLinecap="round"
              strokeLinejoin="round"
            />
            
            {/* 加速度曲线 */}
            <path
              d={accelerationPath}
              fill="none"
              stroke={getAccelerationColor()}
              strokeWidth="3"
              strokeLinecap="round"
              strokeLinejoin="round"
            />

            {/* 当前时刻垂直线 */}
            {currentPoint && (
              <>
                <line
                  x1={xScale(currentPoint.t)}
                  y1={margin.top}
                  x2={xScale(currentPoint.t)}
                  y2={height - margin.bottom}
                  stroke="#64748b"
                  strokeWidth="1"
                  strokeDasharray="4,4"
                />
                {/* 当前速度点 */}
                <circle
                  cx={xScale(currentPoint.t)}
                  cy={vScale(currentPoint.v)}
                  r="5"
                  fill={getVelocityColor()}
                  stroke="white"
                  strokeWidth="2"
                />
                {/* 当前加速度点 */}
                <circle
                  cx={xScale(currentPoint.t)}
                  cy={aScale(currentPoint.a)}
                  r="5"
                  fill={getAccelerationColor()}
                  stroke="white"
                  strokeWidth="2"
                />
              </>
            )}

            {/* 坐标轴标签 */}
            <text
              x={width / 2}
              y={height - 10}
              textAnchor="middle"
              className="text-sm font-medium fill-gray-700"
            >
              时间 t (秒)
            </text>
            <text
              x={20}
              y={height / 2}
              textAnchor="middle"
              transform={`rotate(-90, 20, ${height / 2})`}
              className="text-sm font-medium fill-gray-700"
            >
              速度 v (m/s) 和 加速度 a (m/s²)
            </text>
          </svg>

          {/* 图例 */}
          <div className="flex justify-center mt-4 space-x-6">
            <div className="flex items-center">
              <div 
                className="w-5 h-5 rounded-sm mr-2" 
                style={{ backgroundColor: getVelocityColor() }}
              ></div>
              <span className="text-sm text-gray-700">速度 v(t)</span>
            </div>
            <div className="flex items-center">
              <div 
                className="w-5 h-5 rounded-sm mr-2" 
                style={{ backgroundColor: getAccelerationColor() }}
              ></div>
              <span className="text-sm text-gray-700">加速度 a(t)</span>
            </div>
          </div>
        </div>
      </div>

      {/* 解释说明 */}
      <div className="bg-white rounded-xl shadow-md p-6 w-full max-w-4xl mt-6">
        <h3 className="text-lg font-semibold text-gray-800 mb-3">📊 图像解读</h3>
        <div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
          <div className="p-4 bg-blue-50 rounded-lg">
            <h4 className="font-medium text-blue-800 mb-2">速度图像</h4>
            <p className="text-gray-700">
              速度是位移对时间的变化率。图像中斜率为正表示加速，水平线表示匀速，斜率为负表示减速。
            </p>
          </div>
          <div className="p-4 bg-red-50 rounded-lg">
            <h4 className="font-medium text-red-800 mb-2">加速度图像</h4>
            <p className="text-gray-700">
              加速度是速度对时间的变化率。图像中水平线表示加速度恒定，值为零表示匀速运动。
            </p>
          </div>
          <div className="p-4 bg-green-50 rounded-lg">
            <h4 className="font-medium text-green-800 mb-2">两者关系</h4>
            <p className="text-gray-700">
              加速度图像的纵坐标值等于速度图像在该时刻的斜率。加速度为零时，速度图像为水平直线。
            </p>
          </div>
        </div>
      </div>
    </div>
  );
};

export default AccelerationVelocityChart;
```