136
src/WaveForm.jsx
136
src/WaveForm.jsx
@@ -1,5 +1,4 @@
|
||||
import { useRef, useEffect, useState } from "react";
|
||||
import useSize from "./useSize";
|
||||
import { useRef, useEffect } from "react";
|
||||
|
||||
const BLUE_SHADES = [
|
||||
"rgba(255,255,255,0.9)",
|
||||
@@ -8,63 +7,20 @@ const BLUE_SHADES = [
|
||||
"rgba(255,255,255,0.3)",
|
||||
];
|
||||
|
||||
// Fallback animation for Tizen browsers without Web Audio API
|
||||
const animateFallbackBars = (canvas, ctx, time) => {
|
||||
const HEIGHT = canvas.height;
|
||||
const WIDTH = canvas.width;
|
||||
const barCount = 64;
|
||||
const barWidth = WIDTH / barCount;
|
||||
|
||||
// Set rendering properties for better Tizen compatibility
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
|
||||
for (let i = 0; i < barCount; i++) {
|
||||
// Create animated wave pattern with smaller, more realistic bar heights
|
||||
const wave1 = Math.sin(time * 0.003 + i * 0.3) * 0.4;
|
||||
const wave2 = Math.sin(time * 0.002 + i * 0.2) * 0.3;
|
||||
const normalizedHeight = Math.max(0.1, Math.min(0.4, 0.2 + wave1 + wave2));
|
||||
const barHeight = Math.max(10, normalizedHeight * HEIGHT * 0.3); // Smaller bars like original
|
||||
|
||||
// Use original blue/white gradient colors
|
||||
const intensity = normalizedHeight;
|
||||
const blueShade = Math.min(3, Math.floor(intensity * 4));
|
||||
|
||||
// Create gradient for better visibility (bottom to top)
|
||||
const barX = i * barWidth + 2;
|
||||
const barW = barWidth - 4;
|
||||
const barY = HEIGHT - barHeight; // Start from bottom
|
||||
|
||||
const gradient = ctx.createLinearGradient(0, HEIGHT, 0, barY);
|
||||
gradient.addColorStop(0, BLUE_SHADES[3]);
|
||||
gradient.addColorStop(0.5, BLUE_SHADES[blueShade] || BLUE_SHADES[0]);
|
||||
gradient.addColorStop(1, BLUE_SHADES[0]);
|
||||
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fillRect(barX, barY, barW, barHeight);
|
||||
|
||||
// Add glow effect like the Web Audio version
|
||||
ctx.shadowColor = "rgba(255,255,255,0.8)";
|
||||
ctx.shadowBlur = 5;
|
||||
ctx.fillRect(barX, barY, barW, barHeight);
|
||||
ctx.shadowBlur = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Real Web Audio API animation
|
||||
const animateBars = (analyser, canvas, ctx, dataArray, bufferLength) => {
|
||||
try {
|
||||
analyser.getByteFrequencyData(dataArray);
|
||||
const HEIGHT = canvas.height;
|
||||
const barCount = Math.min(64, bufferLength); // Reduced for better visibility
|
||||
const barWidth = Math.max(6, Math.floor(canvas.width / barCount));
|
||||
const barCount = Math.min(128, bufferLength); // More bars for thinner appearance
|
||||
const barWidth = Math.max(3, Math.floor(canvas.width / barCount)); // Thinner bars
|
||||
const step = Math.floor(bufferLength / barCount);
|
||||
|
||||
let x = 0;
|
||||
|
||||
for (let i = 0; i < barCount; i++) {
|
||||
const dataIndex = i * step;
|
||||
const barHeight = Math.max(5, (dataArray[dataIndex] / 255) * HEIGHT * 0.25); // Smaller bars like original
|
||||
const barHeight = Math.max(20, (dataArray[dataIndex] / 255) * HEIGHT * 0.4); // Original height like original code
|
||||
const blueShade = Math.min(3, Math.floor((dataArray[dataIndex] / 255) * 4));
|
||||
|
||||
// Create gradient for better visibility (bottom to top)
|
||||
@@ -87,7 +43,6 @@ const animateBars = (analyser, canvas, ctx, dataArray, bufferLength) => {
|
||||
x += barWidth;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error in Web Audio API animation:', error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -95,8 +50,6 @@ const animateBars = (analyser, canvas, ctx, dataArray, bufferLength) => {
|
||||
|
||||
const WaveForm = ({ analyzerData }) => {
|
||||
const canvasRef = useRef(null);
|
||||
const [width, height] = useSize();
|
||||
const [useFallback, setUseFallback] = useState(false);
|
||||
const animationRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -106,69 +59,41 @@ const WaveForm = ({ analyzerData }) => {
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) return;
|
||||
|
||||
let webAudioWorking = true;
|
||||
|
||||
// Check if we have valid analyzer data
|
||||
const hasValidAnalyzer = analyzerData &&
|
||||
analyzerData.analyzer &&
|
||||
analyzerData.dataArray &&
|
||||
analyzerData.bufferLength;
|
||||
|
||||
console.log('Audio analyzer status:', {
|
||||
hasAnalyzerData: !!analyzerData,
|
||||
hasAnalyzer: !!(analyzerData && analyzerData.analyzer),
|
||||
useFallback,
|
||||
webAudioWorking
|
||||
});
|
||||
|
||||
const render = () => {
|
||||
try {
|
||||
const currentTime = Date.now();
|
||||
|
||||
// Set canvas dimensions like SimpleWaveForm
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
// Set canvas dimensions
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
// Clear canvas
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Add subtle background
|
||||
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.save();
|
||||
// Clear canvas
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Add subtle background
|
||||
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.save();
|
||||
|
||||
if (hasValidAnalyzer && webAudioWorking && !useFallback) {
|
||||
const success = animateBars(
|
||||
analyzerData.analyzer,
|
||||
canvas,
|
||||
ctx,
|
||||
analyzerData.dataArray,
|
||||
analyzerData.bufferLength
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
webAudioWorking = false;
|
||||
setUseFallback(true);
|
||||
console.log('Web Audio failed, switching to fallback');
|
||||
}
|
||||
} else {
|
||||
// Use fallback animation with current time
|
||||
animateFallbackBars(canvas, ctx, currentTime);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
|
||||
animationRef.current = requestAnimationFrame(render);
|
||||
} catch (error) {
|
||||
console.warn('Canvas rendering error:', error);
|
||||
setUseFallback(true);
|
||||
animationRef.current = requestAnimationFrame(render);
|
||||
if (hasValidAnalyzer) {
|
||||
animateBars(
|
||||
analyzerData.analyzer,
|
||||
canvas,
|
||||
ctx,
|
||||
analyzerData.dataArray,
|
||||
analyzerData.bufferLength
|
||||
);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
|
||||
animationRef.current = requestAnimationFrame(render);
|
||||
};
|
||||
|
||||
// Start animation
|
||||
console.log('Starting animation');
|
||||
render();
|
||||
|
||||
return () => {
|
||||
@@ -176,7 +101,7 @@ const WaveForm = ({ analyzerData }) => {
|
||||
cancelAnimationFrame(animationRef.current);
|
||||
}
|
||||
};
|
||||
}, [analyzerData]); // Simplified dependencies
|
||||
}, [analyzerData]);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
@@ -185,7 +110,7 @@ const WaveForm = ({ analyzerData }) => {
|
||||
left: 0,
|
||||
width: '100vw',
|
||||
height: '100vh',
|
||||
zIndex: -1, // Behind content, not 1000
|
||||
zIndex: -1,
|
||||
pointerEvents: 'none'
|
||||
}}>
|
||||
<canvas
|
||||
@@ -195,14 +120,11 @@ const WaveForm = ({ analyzerData }) => {
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
willChange: "contents",
|
||||
backgroundColor: "transparent",
|
||||
pointerEvents: "none",
|
||||
display: "block"
|
||||
}}
|
||||
ref={canvasRef}
|
||||
role="img"
|
||||
aria-label={useFallback ? "Audio visualization (compatibility mode)" : "Real-time audio visualization"}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Referencia en una nueva incidencia
Block a user