Usar rutas SVG en el lienzo para mover objetos

Si para animar un objeto en el lienzo (y no solo), necesita moverlo a lo largo de una ruta deseada, tal vez incluso varias que pueden seleccionarse aleatoria o secuencialmente, entonces esto puede hacerse usando rutas svg. Comencemos por comenzar un cuadrado simple pero verde a lo largo del camino.

imagen


Para hacer esto, haremos o tomaremos prestado svg, con uno o más caminos.

Cree un elemento utilizando la función document.createElementNS . MDN nos dice que el método tiene soporte básico en todos los navegadores modernos. Luego agregue la ruta al elemento creado.

let path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute('d', 'M148.185,118.975c0,0-92.592,39.507-80.247,79.013,s79.012,143.21,129.629,124.691s64.198-113.856,120.988-100.755s118.518,30.384,116.049,109.397s-82.715,118.519-97.53,201.235,s-92.593,139.505,0,159.259'); 

Aquí, en los atributos, se presenta la primera ruta llamativa de algún archivo svg, método copiar y pegar. Por supuesto, esta no es la única y, además, no es la forma más conveniente, pero lo suficientemente clara como para usarla en el primer ejemplo.

Ahora en el bucle, obtendremos las coordenadas de los waypoints y las asignaremos a nuestro objeto. Dos métodos SVGGeometryElement son suficientes para esto :

 path.getTotalLength() 

devuelve el valor calculado de la longitud total de la ruta y

  path.getPointAtLength(index) 

Toma un argumento flotante y devuelve un objeto SVGPoint que tiene las coordenadas x e y de interés para nosotros. Si los valores del argumento son menores que cero o mayores que la longitud de la ruta, el primer o el último punto, respectivamente, se devolverán como resultado.

Al actualizar el marco, obtenemos el punto y usamos sus coordenadas para el movimiento.

→ Código de ejemplo completo en codepen

Pero, puede usar una opción más interesante para mover el objeto a lo largo de las coordenadas de varios caminos, por ejemplo esto:

imagen


Nuevamente, tome un archivo svg con varias rutas. El que se utilizó en el ejemplo se realiza en el editor de Inscape. Ahora necesita obtener estas rutas, esto es posible analizando el objeto o, si se recibió svg como un archivo de texto, entonces la siguiente función, usando expresiones regulares, puede obtenerlas como cadenas.

 extractPathsfromSvg: function(svg){ let results = svg.match(/<path\b([\s\S]*?)><\/path>/g); let paths = []; let len = results.length; for(let i = 0; i < len; i++){ let str = results[i]; let data = str.match(/[^\w]d="([\s\S]*?)"/); paths.push(data[1]); } return paths; } 

Después de crear una serie de rutas, queda extraerlas a su vez y procesarlas de la misma manera que la única ruta para el movimiento del cuadrado. obteniendo efectos interesantes.
Vea el código completo para el ejemplo a continuación.

Para agregar más control al mover un objeto a lo largo de las coordenadas de la ruta, puede usar gemelos. Para los casos de prueba, tomé la primera biblioteca GreenSock que me llamó la atención, pero podría haber resultado ser cualquier otra.

En el primer caso, cuando el cuadrado se mueve a lo largo del único camino, cree un objeto auxiliar intermedio y páselo para crear la interpolación.

 var helper = {progress: 0} helper.update = function(value){ point = path.getPointAtLength(totalLength * helper.progress); x = point.x; y = point.y; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, x, y ); } var tw = new TweenLite.to(helper, 5, {progress: 0, }); tw.eventCallback("onUpdate", helper.update); 

Puede ver el movimiento del cuadrado a lo largo del camino usando interpolación, en el primer ejemplo en codepen, marcando usar interpolación.

Cuando nos movemos por varios caminos, procedemos de la siguiente manera. Como antes, cree un objeto auxiliar con la propiedad de progreso. Calculamos la longitud total de todas las rutas y le asignamos handler.progress. Creemos una variable recorrida en la que se resumirán las rutas ya cubiertas.

Para obtener un punto en la ruta actual, reste helper.progress, que cambia en la interpolación, se atraviesa la ruta ya recorrida. Usamos las coordenadas del punto como de costumbre.

 var traversed = 0; helper.progress = totalLenghtAllPath; helper.update = function() { var localPoint = helper.progress - traversed; if(localPoint > curPath.getTotalLength()){ traversed += curPath.getTotalLength(); curPath = paths[next()]; if(curPath){ return false; } localPoint = helper.progress - traversed; } /*       */ } var tw = TweenLite.to( helper, 25, {progress: totalLenghtAllPath, ease: Power2.easeOut } ); tw.eventCallback("onUpdate", helper.update); 

El código está simplificado, el código completo está aquí:

Source: https://habr.com/ru/post/es432114/


All Articles