UNPKG

vlibras-player-webjs

Version:

Biblioteca JavaScript moderna para integração do VLibras Player com React, Vue, Angular e vanilla JS

295 lines (279 loc) 9.06 kB
/** * Sistema de CSS Automático para VLibras Player * * Resolve o problema identificado no FUNCOES-UTILITARIAS-VLIBRAS.md * onde o canvas do Unity não ocupa o espaço corretamente e tem bordas pretas. */ /** * Classe responsável por otimizar automaticamente o CSS do canvas Unity */ export class VLibrasCSS { /** * Injeta CSS automático para otimizar o canvas */ static injectOptimizedCSS(containerSelector = '.vlibras-container', canvasConfig = {}, responsive) { if (typeof document === 'undefined') return; // Remove CSS anterior se existir VLibrasCSS.removeInjectedCSS(); const config = { fillContainer: true, aspectRatio: 'auto', scaleMode: 'cover', removeBlackBorders: true, backgroundColor: 'transparent', borderRadius: '8px', ...canvasConfig }; const css = VLibrasCSS.generateOptimizedCSS(containerSelector, config, responsive); const styleElement = document.createElement('style'); styleElement.id = VLibrasCSS.injectedStyleId; styleElement.textContent = css; document.head.appendChild(styleElement); VLibrasCSS.cssInjected = true; console.log('[VLibras CSS] CSS otimizado injetado automaticamente'); } /** * Gera o CSS otimizado com base na configuração */ static generateOptimizedCSS(containerSelector, config, responsive) { let css = ` /* VLibras Player - CSS Automático Otimizado */ ${containerSelector} { position: relative; overflow: hidden; ${config.borderRadius ? `border-radius: ${config.borderRadius};` : ''} ${config.backgroundColor ? `background-color: ${config.backgroundColor};` : ''} ${config.fillContainer ? 'width: 100%; height: 100%;' : ''} } ${containerSelector} canvas { display: block; ${config.fillContainer ? 'width: 100% !important; height: 100% !important;' : ''} ${config.customWidth ? `width: ${config.customWidth} !important;` : ''} ${config.customHeight ? `height: ${config.customHeight} !important;` : ''} ${config.backgroundColor ? `background-color: ${config.backgroundColor};` : ''} ${config.borderRadius ? `border-radius: ${config.borderRadius};` : ''} /* Remove bordas pretas do Unity */ ${config.removeBlackBorders ? 'transform: scale(1.05);' : ''} /* Modo de escala */ object-fit: ${config.scaleMode === 'stretch' ? 'fill' : config.scaleMode === 'cover' ? 'cover' : config.scaleMode === 'contain' ? 'contain' : 'none'}; } /* Proporção de aspecto */ ${VLibrasCSS.generateAspectRatioCSS(containerSelector, config.aspectRatio)} /* Container para centralizar o canvas */ ${containerSelector} .unity-container { position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; } /* Loading state styling */ ${containerSelector} .vlibras-loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; display: flex; flex-direction: column; align-items: center; gap: 12px; } /* Estados visuais */ ${containerSelector}[data-state="loading"] { background: linear-gradient(45deg, #f0f0f0 25%, transparent 25%), linear-gradient(-45deg, #f0f0f0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f0f0f0 75%), linear-gradient(-45deg, transparent 75%, #f0f0f0 75%); background-size: 20px 20px; background-position: 0 0, 0 10px, 10px -10px, -10px 0px; animation: vlibras-loading-bg 2s linear infinite; } ${containerSelector}[data-state="error"] { background-color: #fee; border: 2px solid #fcc; } ${containerSelector}[data-state="ready"] { background-color: #efe; border: 2px solid #cfc; } @keyframes vlibras-loading-bg { 0% { background-position: 0 0, 0 10px, 10px -10px, -10px 0px; } 100% { background-position: 20px 20px, 20px 30px, 30px 10px, 10px 20px; } } /* Animações suaves */ ${containerSelector} canvas { transition: transform 0.3s ease, opacity 0.3s ease; } ${containerSelector}[data-state="playing"] canvas { transform: scale(${config.removeBlackBorders ? '1.05' : '1'}); opacity: 1; } ${containerSelector}[data-state="loading"] canvas { opacity: 0.7; } `; // CSS responsivo if (responsive?.enabled) { css += VLibrasCSS.generateResponsiveCSS(containerSelector, responsive); } return css; } /** * Gera CSS para proporção de aspecto */ static generateAspectRatioCSS(containerSelector, aspectRatio) { if (!aspectRatio || aspectRatio === 'auto') return ''; const ratios = { '16:9': '56.25%', // (9/16) * 100 '4:3': '75%', // (3/4) * 100 '1:1': '100%' // (1/1) * 100 }; const paddingTop = ratios[aspectRatio]; if (!paddingTop) return ''; return ` ${containerSelector}::before { content: ''; display: block; padding-top: ${paddingTop}; } ${containerSelector} .unity-container { position: absolute; top: 0; left: 0; right: 0; bottom: 0; } `; } /** * Gera CSS responsivo */ static generateResponsiveCSS(containerSelector, responsive) { return ` /* Mobile */ @media (max-width: ${responsive.breakpoints.mobile.maxWidth}) { ${containerSelector} { ${VLibrasCSS.configToCSS(responsive.breakpoints.mobile.config)} } } /* Tablet */ @media (min-width: calc(${responsive.breakpoints.mobile.maxWidth} + 1px)) and (max-width: ${responsive.breakpoints.tablet.maxWidth}) { ${containerSelector} { ${VLibrasCSS.configToCSS(responsive.breakpoints.tablet.config)} } } /* Desktop */ @media (min-width: ${responsive.breakpoints.desktop.minWidth}) { ${containerSelector} { ${VLibrasCSS.configToCSS(responsive.breakpoints.desktop.config)} } } `; } /** * Converte config para propriedades CSS */ static configToCSS(config) { let css = ''; if (config.customWidth) css += `width: ${config.customWidth} !important; `; if (config.customHeight) css += `height: ${config.customHeight} !important; `; if (config.backgroundColor) css += `background-color: ${config.backgroundColor}; `; if (config.borderRadius) css += `border-radius: ${config.borderRadius}; `; return css; } /** * Remove o CSS injetado */ static removeInjectedCSS() { if (typeof document === 'undefined') return; const existingStyle = document.getElementById(VLibrasCSS.injectedStyleId); if (existingStyle) { existingStyle.remove(); VLibrasCSS.cssInjected = false; } } /** * Verifica se o CSS foi injetado */ static isCSSInjected() { return VLibrasCSS.cssInjected; } /** * Aplica classe de estado ao container */ static setContainerState(containerElement, state) { if (!containerElement) return; containerElement.setAttribute('data-state', state); } /** * Configurações responsivas padrão */ static getDefaultResponsiveConfig() { return { enabled: true, breakpoints: { mobile: { maxWidth: '768px', config: { customHeight: '200px', removeBlackBorders: true, borderRadius: '4px' } }, tablet: { maxWidth: '1024px', config: { customHeight: '300px', removeBlackBorders: true, borderRadius: '6px' } }, desktop: { minWidth: '1025px', config: { fillContainer: true, removeBlackBorders: true, borderRadius: '8px' } } } }; } } VLibrasCSS.injectedStyleId = 'vlibras-auto-css'; VLibrasCSS.cssInjected = false; /** * Função de conveniência para setup automático de CSS */ export function setupOptimizedCSS(containerSelector, config, responsive) { const responsiveConfig = responsive ? VLibrasCSS.getDefaultResponsiveConfig() : undefined; VLibrasCSS.injectOptimizedCSS(containerSelector, config, responsiveConfig); } /** * Exemplo de uso: * * // Setup básico * setupOptimizedCSS(); * * // Setup customizado * setupOptimizedCSS('.meu-container', { * fillContainer: true, * removeBlackBorders: true, * backgroundColor: '#f5f5f5', * aspectRatio: '16:9' * }, true); */ //# sourceMappingURL=VLibrasCSS.js.map