Actualmente estoy trabajando en un proyecto de CMS para crear objetos en perspectiva utilizando las propiedades de transform de CSS (escala, rotación, traducción...) en 3d: XYZ. Cuando se crea un objeto, tiene estas características en su matrix3d (-16 valores-) devuelto por window.getComputedStyle(element) -> style['transform'] El siguiente paso es crear animaciones: a través de un conjunto de input[range] , el usuario puede modificar las características de estos objetos y obtener su estado final una vez finalizada la animación. Funciona muy bien. La cuestión ahora es crear el sistema CSS dinámico completo, objeto por objeto.
Tengo su matriz1 (matriz3d inicial) y su matriz2 (matriz3d final). al ejecutar
@keyframes anim { from { transform: matrix1 } to { transform: matrix2; } } document.getElementById('object').style.animation = 'anim 2s linear';debería funcionar por sí solo... El problema es crear la instrucción CSS. Usando:
document.styleSheets[0].insertRule(' @keyframes anim { from { transform: matrix1 } to { transform: matrix2; } }' );funciona bien, pero una vez que se crea en el archivo CSS principal, si el usuario modifica la matriz2, no puedo volver a escribir la misma instrucción dos veces...
Mi idea es crear un archivo CSS para cada objeto en el servidor y luego importarlo con JS: si el usuario está satisfecho, lo conservo, y si no, lo elimino y creo uno nuevo con su nueva matriz2.
la ventaja es que puedo mantener la palabra 'anim' sin correr el riesgo de conflicto entre los objetos, ya que cada uno llamará a su propio CSS (es decir, 'objeto1.css').
¿Es esta la mejor manera de proceder o me recomiendan otra?
Otra pregunta: a pesar de mi investigación, no puedo encontrar a qué corresponden los 16 valores de matrix3d. Traducir XYZ está en [12], [13], [14] pero no los tengo todos. Si conoce un recurso más explícito que https://developer.mozilla.org/fr/docs/Web/CSS/transform-function/matrix3d() , puede ser útil.
Finalmente encontré la solución... tal vez no sea la mejor pero funciona.
Creamos la primera matrix3D (objeto en su estado inicial):
getObjectValues('objID', 0); // 0 for matrix1La función
function getObjectValues(div, n){ // 0 for matrix1, 1 for matrix2 let element = document.getElementById(div); let myTransform = window.getComputedStyle(element,null) let matrix = myTransform.getPropertyValue("-webkit-transform"); if (matrix === 'none' || typeof matrix === 'undefined') { // native HTML objects (as divs) are not in a 3D dimension space // if necessary we create its 3D environment element.style.transform = 'translateZ(1px)'; getObjectValues(div, n); // then reload the function } else { matrixObj[n] = matrix; } } // Array matrixObj at this step: [0] -> matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1) Después de jugar con los diferentes input type="range" (para posición, rotación, ... en la dimensión XYZ), creamos la segunda matriz 3D (estado final) haciendo clic en el botón "PRUEBA", que llama
getObjectValues('objID', 1); // 1 for matrix2 // Array matrixObj at this step: [0] -> matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1) [1] -> matrix3d(0.945519, 0, -0.325568, 0, 0, 1, 0, 0, 0.325568, 0, 0.945519, 0, 0, 0, -48, 1)Ahora el truco: creamos una pseudo hoja CSS llamada "anim-update"
includeCSS("anim-update"); let styleSheet = document.getElementById("anim-update"); // the function function includeCSS(css) { let head = document.getElementsByTagName('head')[0]; let sheet = document.createElement('style'); sheet.setAttribute('id',css); sheet.setAttribute('rel', 'stylesheet'); sheet.setAttribute('type', 'text/css'); head.appendChild(sheet); }Una vez hecho esto, reproducimos estas 3 secuencias:
let delay = 2; // duration // 1. returns the object to its initial state setTimeout(function(){ document.getElementById(div).style.transform = matrixObj[0]; },100); // 2. play the scenario setTimeout(function(){ styleSheet.innerHTML = '@keyframes anim { from { transform: '+matrixObj[n][0]+' } to { transform: '+matrixObj[n][1]+' } }'; document.getElementById(div).style.animation = 'anim '+delay+'s linear'; },500); // 3. removes the temporary CSS at the end of the animation setTimeout(function(){ document.getElementById('anim-update').outerHTML = ""; delete document.getElementById('anim-update'); },500+2000); // +2 seconds -> delay*1000De esta forma el usuario puede cambiar el estado final del objeto tanto como quiera hasta obtener la animación deseada, la cual comprueba haciendo clic en el botón "PRUEBA". Un botón "GUARDAR" recupera los datos de matrixObj y guarda los 2 valores de matriz. Luego pasa al siguiente objeto.