Se para animar um objeto na tela (e não apenas), é necessário movê-lo ao longo de algum caminho desejado, talvez até vários que possam ser selecionados aleatoriamente ou sequencialmente, e isso pode ser feito usando caminhos svg. Vamos começar iniciando um quadrado simples, mas verde, ao longo do caminho.
Para fazer isso, criaremos ou emprestaremos svg, com um ou mais caminhos.
Crie um elemento usando a função
document.createElementNS . O MDN nos diz que o método possui suporte básico em todos os navegadores modernos. Em seguida, adicione o caminho ao elemento criado.
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');
Aqui, nos atributos, é apresentado o primeiro caminho atraente de algum arquivo svg, método copiar e colar. Obviamente, essa não é a única e, além disso, não é a maneira mais conveniente, mas suficientemente clara para ser usada no primeiro exemplo.
Agora, no loop, obteremos as coordenadas dos waypoints e as atribuiremos ao nosso objeto. Dois métodos
SVGGeometryElement são suficientes para
isso :
path.getTotalLength()
retorna o valor calculado do comprimento total do caminho e
path.getPointAtLength(index)
Ele pega um argumento de flutuação e retorna um objeto SVGPoint que possui as coordenadas xey de seu interesse. Se os valores do argumento forem menores que zero ou maiores que o comprimento do caminho, o primeiro ou o último ponto, respectivamente, serão retornados como resultado.
Ao atualizar o quadro, obtemos o ponto e usamos suas coordenadas para o movimento.
→ Código de exemplo completo no
codepenMas você pode usar uma opção mais interessante para mover o objeto ao longo das coordenadas de vários caminhos, por exemplo:
Mais uma vez, pegue um arquivo svg com vários caminhos. O que foi usado no exemplo é feito no editor Inscape. Agora você precisa obter esses caminhos, isso é possível através da análise do objeto ou, se svg foi recebido como um arquivo de texto, a próxima função, usando expressões regulares, pode ser obtida como strings.
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; }
Depois de criar uma matriz de caminhos, resta extraí-los e processá-los da mesma maneira que o único caminho para o movimento do quadrado. obtendo efeitos interessantes.
Veja o código completo para o exemplo abaixo.
Para adicionar mais controle ao mover um objeto ao longo das coordenadas do caminho, você pode usar gêmeos. Para casos de teste, peguei a primeira biblioteca GreenSock que chamou minha atenção, mas poderia ter sido outra.
No primeiro caso, quando o quadrado se mover ao longo do único caminho, crie um auxiliar de objeto intermediário e passe-o para criar a interpolação.
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);
Você pode ver o movimento do quadrado ao longo do caminho usando interpolação, no primeiro exemplo no codepen, marcando usar interpolação.
Ao percorrer vários caminhos, procedemos da seguinte maneira. Como antes, crie um objeto auxiliar com a propriedade progress. Calculamos o comprimento total de todos os caminhos e atribuímos a ele handler.progress. Vamos criar uma variável atravessada na qual os caminhos já abordados serão resumidos.
Para obter um ponto no caminho atual, subtraia de helper.progress, que muda na interpolação, o caminho já percorrido é percorrido. Usamos as coordenadas do ponto como de costume.
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);
O código é simplificado, o código completo está aqui: