@@ -10,16 +10,26 @@ const BLUE_SHADES = [
|
||||
|
||||
// Fallback animation for Tizen browsers without Web Audio API
|
||||
const animateFallbackBars = (canvas, ctx, fallbackData) => {
|
||||
const HEIGHT = canvas.height / 2;
|
||||
const barCount = 64; // Reduced for better performance on TV
|
||||
const barWidth = Math.max(2, Math.floor(canvas.width / barCount));
|
||||
const HEIGHT = canvas.height;
|
||||
const barCount = 32; // Further reduced for Tizen TV performance
|
||||
const barWidth = Math.max(4, Math.floor(canvas.width / barCount)); // Minimum 4px width
|
||||
let x = 0;
|
||||
|
||||
// Set line width for better visibility on TV
|
||||
ctx.lineWidth = 2;
|
||||
|
||||
for (let i = 0; i < barCount; i++) {
|
||||
const barHeight = fallbackData[i] * HEIGHT;
|
||||
const blueShade = Math.floor(fallbackData[i] * 3);
|
||||
const barHeight = Math.max(2, fallbackData[i] * HEIGHT * 0.8); // Minimum 2px height
|
||||
const blueShade = Math.min(3, Math.floor(fallbackData[i] * 4));
|
||||
|
||||
// Fill the bar
|
||||
ctx.fillStyle = BLUE_SHADES[blueShade] || BLUE_SHADES[0];
|
||||
ctx.fillRect(x, HEIGHT - barHeight, barWidth - 1, barHeight);
|
||||
ctx.fillRect(x + 1, HEIGHT - barHeight, barWidth - 2, barHeight);
|
||||
|
||||
// Add border for better visibility on TV
|
||||
ctx.strokeStyle = "rgba(255,255,255,0.8)";
|
||||
ctx.strokeRect(x + 1, HEIGHT - barHeight, barWidth - 2, barHeight);
|
||||
|
||||
x += barWidth;
|
||||
}
|
||||
};
|
||||
@@ -28,15 +38,28 @@ const animateFallbackBars = (canvas, ctx, fallbackData) => {
|
||||
const animateBars = (analyser, canvas, ctx, dataArray, bufferLength) => {
|
||||
try {
|
||||
analyser.getByteFrequencyData(dataArray);
|
||||
const HEIGHT = canvas.height / 2;
|
||||
const barWidth = Math.ceil(canvas.width / bufferLength) * 2.5;
|
||||
const HEIGHT = canvas.height;
|
||||
const barCount = Math.min(128, bufferLength); // Limit bars for TV performance
|
||||
const barWidth = Math.max(3, Math.floor(canvas.width / barCount));
|
||||
const step = Math.floor(bufferLength / barCount);
|
||||
|
||||
let x = 0;
|
||||
for (let i = 0; i < bufferLength; i++) {
|
||||
const barHeight = (dataArray[i] / 255) * HEIGHT;
|
||||
const blueShade = Math.floor((dataArray[i] / 255) * 4);
|
||||
ctx.lineWidth = 1;
|
||||
|
||||
for (let i = 0; i < barCount; i++) {
|
||||
const dataIndex = i * step;
|
||||
const barHeight = Math.max(2, (dataArray[dataIndex] / 255) * HEIGHT * 0.8);
|
||||
const blueShade = Math.min(3, Math.floor((dataArray[dataIndex] / 255) * 4));
|
||||
|
||||
// Fill the bar
|
||||
ctx.fillStyle = BLUE_SHADES[blueShade] || BLUE_SHADES[0];
|
||||
ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight);
|
||||
x += barWidth + 1;
|
||||
ctx.fillRect(x + 1, HEIGHT - barHeight, barWidth - 2, barHeight);
|
||||
|
||||
// Add subtle border
|
||||
ctx.strokeStyle = "rgba(255,255,255,0.6)";
|
||||
ctx.strokeRect(x + 1, HEIGHT - barHeight, barWidth - 2, barHeight);
|
||||
|
||||
x += barWidth;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error in Web Audio API animation:', error);
|
||||
@@ -54,7 +77,7 @@ const WaveForm = ({ analyzerData }) => {
|
||||
|
||||
// Initialize fallback data
|
||||
useEffect(() => {
|
||||
const initialData = Array(64).fill(0).map(() => Math.random() * 0.3 + 0.1);
|
||||
const initialData = Array(32).fill(0).map(() => Math.random() * 0.5 + 0.3); // Higher initial values
|
||||
setFallbackData(initialData);
|
||||
}, []);
|
||||
|
||||
@@ -76,9 +99,12 @@ const WaveForm = ({ analyzerData }) => {
|
||||
|
||||
const render = () => {
|
||||
try {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
// Clear with black background for better visibility on TV
|
||||
ctx.fillStyle = "rgba(0,0,0,0.1)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Ensure we're drawing from bottom up
|
||||
ctx.save();
|
||||
ctx.translate(0, canvas.height / 2);
|
||||
|
||||
if (hasValidAnalyzer && webAudioWorking && !useFallback) {
|
||||
// Try Web Audio API first
|
||||
@@ -113,12 +139,12 @@ const WaveForm = ({ analyzerData }) => {
|
||||
fallbackIntervalRef.current = setInterval(() => {
|
||||
setFallbackData(prevData =>
|
||||
prevData.map(val => {
|
||||
const target = Math.random() * 0.8 + 0.2;
|
||||
const smoothing = 0.15;
|
||||
const target = Math.random() * 0.7 + 0.3; // Higher amplitude for visibility
|
||||
const smoothing = 0.2; // Faster transitions
|
||||
return val + (target - val) * smoothing;
|
||||
})
|
||||
);
|
||||
}, 100); // Update every 100ms for smooth animation
|
||||
}, 80); // Faster updates for more responsive animation
|
||||
}
|
||||
|
||||
render();
|
||||
@@ -136,18 +162,23 @@ const WaveForm = ({ analyzerData }) => {
|
||||
return (
|
||||
<canvas
|
||||
style={{
|
||||
position: "absolute",
|
||||
position: "fixed", // Changed from absolute to fixed for better TV compatibility
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100vw", // Explicit viewport width
|
||||
height: "100vh", // Explicit viewport height
|
||||
zIndex: 0,
|
||||
// Add hardware acceleration hint for Tizen
|
||||
willChange: "transform",
|
||||
// Ensure canvas doesn't cause layout issues on TV
|
||||
imageRendering: "pixelated"
|
||||
// Tizen TV optimizations
|
||||
willChange: "auto", // Changed from transform to auto
|
||||
imageRendering: "auto", // Better for TV displays
|
||||
// Ensure visibility on TV
|
||||
backgroundColor: "transparent",
|
||||
// Prevent touch/click interference
|
||||
pointerEvents: "none"
|
||||
}}
|
||||
ref={canvasRef}
|
||||
width={width}
|
||||
height={height}
|
||||
width={width || window.innerWidth} // Fallback dimensions
|
||||
height={height || window.innerHeight}
|
||||
// Add accessibility for Smart TV navigation
|
||||
role="img"
|
||||
aria-label={useFallback ? "Audio visualization (compatibility mode)" : "Real-time audio visualization"}
|
||||
|
||||
Referencia en una nueva incidencia
Block a user