0
votes

I'm trying to animate a smooth moving of an entity, when appending it to another parent in the scene.

There are a few plugins out there to animate a change of the position itself, but not when the position stays the same, but the parent is changing.

I need this, because I have different "spots" defined, where the entity can be. Now I want to put the entity into one of these spots, so I don't have to calculate the new position of the entity. Without animation, that concept works perfect.

My current resolution for the animation is the following:

  • iterate through all current parents of the entity and sum the position vectors of these elements
  • iterate through all the parents and the new parent itself and sum the position vectors of these elements
  • subtract the two calculated vectors
  • append the entity to the new parent and add an animation with from = the resulting offset vector and to="0 0 0"

Works, but in some frames the element flickers, because it is first appended to the new parent (position="0 0 0", so exatly on the new parent), it gets drawn, and then the animation starts with the from placing it at the old position and moving it back to "0 0 0".

I built a jsfiddle, which shows the problem: https://jsfiddle.net/fshqghxt/

Can someone help me out on fixing this? I'm also open for completely different concepts. Thank you in advance!

2

2 Answers

0
votes

Would this help? (component-based approach)

HTML:

<a-scene>
    <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
    <a-box position="-1 0.5 -3" width="1" height="1" depth="1" color="#4CC3D9" animation="property: position; dir: alternate; loop: true; dur: 1000; to: -1 3 -3; startEvents: moveBox"></a-box>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
    <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
    <a-sky color="#ECECEC"></a-sky>
</a-scene>

JS:

document.querySelector('a-box').emit('moveBox');

Fiddle

0
votes

I worked out two solutions today, what work well:


Staying at aframe.io

While staying at aframe.io, this new concept works ok: * cloning the element on its current position * hide the original element * append it to the new parent and set its position to the offset position to match the cloned element * show the original element * hide the cloned element * start the animation

This way, no flickering is possible with the help of the clone.

function animateParentChange(element, newParent) {
  var newParentParents = newParent.add(newParent.parentsUntil('a-scene'));
  var elementParents = element.parentsUntil('a-scene');

  var oldVector = sumVectors(elementParents);
  var newVector = sumVectors(newParentParents);

  var diff = oldVector.sub(newVector)

  var newPosition = vectorToPosition(diff);
  console.log("newPosition", newPosition);

  $(element).find('a-animate').remove();
  var tempElement = $(element).clone().appendTo(element.parent());
  $(element).attr('visible', 'false').appendTo(newParent).attr('position', diff.toArray().join(' '));
  $(element).append('<a-animation attribute="position" dur="1000" fill="forwards" from="' + diff.toArray().join(' ') + '" to="0 0 0"></a-animation>');
  $(element).attr('visible', true);
  tempElement.remove();
}

Fiddle: https://jsfiddle.net/5uc1hn63/


Switching to pure three.js

But what I really did in the end is switching to pure three.js, replacing all aframe.io things with javascript generated objects.

This way I have full control over when is what rendered. While working with aframe.io I found, that it is very very easy to use (in compare to three.js), but not as flexible as I needed it.

I accept having to write more lines of code, but for the price of flexibility I think thats ok.

At the end everyone should consider by himself, what is more important to him.