En svg, agrego transition: all 3s linear
a <rect>
y <path>
, y luego hago clic en un botón para hacer que <rect>
y <path>
se muevan repetidamente y simultáneamente la misma distancia entre dos posiciones, pero durante el movimiento , ¿por qué la distancia relativa entre <rect>
y <path>
no permanece igual?
Navegador: cromo
Demostración ejecutándose con Chrome:
const svg = document.querySelector("#svg"); const path = svg.querySelector("path"); const rect = svg.querySelector("g"); const btn = document.querySelector("#btn"); const paths = [ 'M 29 12.6 h 30', 'M 29 32.6 h 30', ] const hs = [2, 22]; let i = 0; btn.onclick = () => { path.setAttribute("d", paths[i]); rect.setAttribute("transform", `translate(0,${hs[i]})`); i ^= 1; }
svg * { transition: all 3s linear; }
<svg id="svg" width="200" height="200" viewbox="0 -10 50 50"> <path fill="none" stroke="#ff6699" d="M 29 12.6 h 30"></path> <g transform="translate(0,2)"> <rect x="29" y="0" width="30" height="10"></rect> </g> </svg> <br> <button id="btn">Click quickly and repeatedly</button>
Editar: la siguiente respuesta solo se aplica al comportamiento de Firefox, donde la transform
no está animada. Chrome muestra un problema diferente, y parece que eso fue lo que preguntaste.
transition
es una propiedad de CSS, pero intenta animar los atributos de presentación. Eso parece funcionar para d
(sorprendentemente, en mi opinión), pero no para transform
, donde no hay transición y el valor cambia instantáneamente.
Si bien la especificación trata de dar la impresión de que los atributos de presentación y las propiedades CSS se pueden intercambiar libremente, en la práctica se obtienen algunas asperezas una y otra vez. No voy a tratar de averiguar si se supone que lo que intentaste hacer funciona de acuerdo con las especificaciones. Según mi experiencia, lo sensato es quedarse a un lado de la valla. Entonces, si intenta animar algo con la propiedad de transition
CSS , ese algo también debe escribirse como una propiedad CSS .
En lugar de transform="translate(0,2)"
, use style="transform:translate(0,2px)"
- tenga cuidado de agregar la unidad px
.
const svg = document.querySelector("#svg"); const path = svg.querySelector("path"); const rect = svg.querySelector("g"); const btn = document.querySelector("#btn"); const paths = [ 'M 29 12.6 h 30', 'M 29 32.6 h 30', ] const hs = [2, 22]; let i = 0; btn.onclick = () => { path.setAttribute("d", paths[i]); rect.style.transform = `translate(0,${hs[i]}px)`; i ^= 1; }
svg * { transition: all 3s linear; }
<svg id="svg" width="200" height="200" viewbox="0 -10 50 50"> <path fill="none" stroke="#ff6699" d="M 29 12.6 h 30"></path> <g style="transform:translate(0,2px)"> <rect x="29" y="0" width="30" height="10"></rect> </g> </svg> <br> <button id="btn">Click quickly and repeatedly</button>