import { Volume2, VolumeX } from "lucide-react" import React, { useEffect, useRef, useState } from "react" import { cn } from "@/lib/utils" import { AudioClip } from "../../services/audio-clip-editor" interface AudioClipProps { clip: AudioClip pixelsPerSecond: number trackHeight: number isSelected: boolean onSelect: () => void onPositionChange: (newStartTime: number) => void onDurationChange: (newDuration: number) => void waveformData?: Float32Array } export function AudioClipComponent({ clip, pixelsPerSecond, trackHeight, isSelected, onSelect, onPositionChange, onDurationChange, waveformData, }: AudioClipProps) { const canvasRef = useRef(null) const [isDragging, setIsDragging] = useState(false) const [isResizing, setIsResizing] = useState<"left" | "right" | null>(null) const [dragStartX, setDragStartX] = useState(0) const [initialStartTime, setInitialStartTime] = useState(0) const [initialDuration, setInitialDuration] = useState(0) const clipWidth = clip.duration * pixelsPerSecond const clipX = clip.startTime * pixelsPerSecond // Рисуем waveform useEffect(() => { const canvas = canvasRef.current if (!canvas || !waveformData) return const ctx = canvas.getContext("2d") if (!ctx) return // Устанавливаем размер canvas canvas.width = clipWidth canvas.height = trackHeight - 4 // Очищаем canvas ctx.clearRect(0, 0, canvas.width, canvas.height) // Рисуем waveform ctx.fillStyle = "#3b82f6" ctx.strokeStyle = "#60a5fa" ctx.lineWidth = 1 const samples = waveformData.length // const step = Math.max(1, Math.floor(samples / canvas.width)) const centerY = canvas.height / 2 ctx.beginPath() ctx.moveTo(0, centerY) for (let x = 0; x < canvas.width; x++) { const sampleIndex = Math.floor((x / canvas.width) * samples) const value = waveformData[sampleIndex] || 0 const y = centerY - value * centerY * 0.8 ctx.lineTo(x, y) } // Зеркалим для нижней части for (let x = canvas.width - 1; x >= 0; x--) { const sampleIndex = Math.floor((x / canvas.width) * samples) const value = waveformData[sampleIndex] || 0 const y = centerY + value * centerY * 0.8 ctx.lineTo(x, y) } ctx.closePath() ctx.fill() ctx.stroke() // Рисуем fade in/out if (clip.fadeIn > 0) { const fadeInWidth = clip.fadeIn * pixelsPerSecond const gradient = ctx.createLinearGradient(0, 0, fadeInWidth, 0) gradient.addColorStop(0, "rgba(0, 0, 0, 0.8)") gradient.addColorStop(1, "rgba(0, 0, 0, 0)") ctx.fillStyle = gradient ctx.fillRect(0, 0, fadeInWidth, canvas.height) } if (clip.fadeOut > 0) { const fadeOutWidth = clip.fadeOut * pixelsPerSecond const fadeOutStart = canvas.width - fadeOutWidth const gradient = ctx.createLinearGradient(fadeOutStart, 0, canvas.width, 0) gradient.addColorStop(0, "rgba(0, 0, 0, 0)") gradient.addColorStop(1, "rgba(0, 0, 0, 0.8)") ctx.fillStyle = gradient ctx.fillRect(fadeOutStart, 0, fadeOutWidth, canvas.height) } }, [clipWidth, trackHeight, waveformData, clip.fadeIn, clip.fadeOut, pixelsPerSecond]) const handleMouseDown = (e: React.MouseEvent, action: "drag" | "resize-left" | "resize-right") => { e.preventDefault() e.stopPropagation() onSelect() if (action === "drag") { setIsDragging(true) } else { setIsResizing(action === "resize-left" ? "left" : "right") } setDragStartX(e.clientX) setInitialStartTime(clip.startTime) setInitialDuration(clip.duration) // Добавляем глобальные обработчики document.addEventListener("mousemove", handleMouseMove) document.addEventListener("mouseup", handleMouseUp) } const handleMouseMove = (e: MouseEvent) => { const deltaX = e.clientX - dragStartX const deltaTime = deltaX / pixelsPerSecond if (isDragging) { const newStartTime = Math.max(0, initialStartTime + deltaTime) onPositionChange(newStartTime) } else if (isResizing === "left") { const newStartTime = Math.max(0, initialStartTime + deltaTime) const newDuration = Math.max(0.1, initialDuration - deltaTime) onPositionChange(newStartTime) onDurationChange(newDuration) } else if (isResizing === "right") { const newDuration = Math.max(0.1, initialDuration + deltaTime) onDurationChange(newDuration) } } const handleMouseUp = () => { setIsDragging(false) setIsResizing(null) document.removeEventListener("mousemove", handleMouseMove) document.removeEventListener("mouseup", handleMouseUp) } return (
handleMouseDown(e, "drag")} > {/* Левый край для изменения размера */}
handleMouseDown(e, "resize-left")} /> {/* Правый край для изменения размера */}
handleMouseDown(e, "resize-right")} /> {/* Waveform */} {/* Информация о клипе */}
{clip.id.split("_")[0]}
{clip.gain === 0 ? ( ) : ( )}
{/* Индикаторы fade */} {clip.fadeIn > 0 && (
↗ {clip.fadeIn.toFixed(1)}s
)} {clip.fadeOut > 0 && (
{clip.fadeOut.toFixed(1)}s ↘
)}
) }