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
JavaScript
/**
* 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