Psychonaut007
Psychonaut007

Reputation: 197

How to sync the position of entity with respect to two animations present inside same entity tag in aframe?

I have two animations present in my project: 'animation' and 'animation__mouseenter'. I am trying to control the animation by using properties like: startEvents, resumeEvents and pauseEvents. Everything is working fine until entity switches from 'animation__mouseenter' to 'animation'. After the completion of animation__mouseenter'. The entity starts from the last position where 'animation' left the entity, whereas what I am looking for is that it should continue from new location assigned by 'animation__mouseenter'.

I have also tried to use .setAttribute from JavaScript and tried to adjust the from property for 'animation' with the help of tick function which will continuously update the new location of the entity.

<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
  <script>
  AFRAME.registerComponent('eventhandling', {
            tick: function () {
                var el = this.el;
              var entity = document.querySelector('#duck1');
                el.addEventListener('animationcomplete', function(){
                   entity.emit('starteventforAnimation'); 
                });
          }
        });
    
  </script>
</head>

<body>
    <a-scene>
<a-entity class="rota" id="duck1" color="#FF0000" scale="0.1 0.1 .1" position="2 0 -7" animation="property: rotation;from: ; to:0 -360 0; loop:true; easing:linear; dur:30000; pauseEvents: mouseenter; resumeEvents: starteventforAnimation " animation__mouseenter="property: rotation;from: ; to:0 360 0; easing:linear; dur:4000; startEvents: mouseenter ;pauseEvents: starteventforAnimation; resumeEvents: mouseenter" eventhandling>
            <a-box class="rota" color="#FF0000" gltf-model="spaceship.glb"  position="20 0 -10"  scale="2 3 3" collison-check="el: #otherduck; radius: 0.15; other-radius: 0.15;"> </a-box>
        </a-entity>
<a-camera position="0 1.2 1.3"><a-cursor objects=".rota" ></a-cursor></a-camera>        <

    </a-scene>
</body>
</html>

Upvotes: 0

Views: 115

Answers (1)

Piotr Adam Milewski
Piotr Adam Milewski

Reputation: 14645

From what I understand you want to change the direction of the rotation at any point (and slow it down, etc).

You're moving the object around by rotating the parent. Which means position doesn't play a major role here - rotation does.

Id use only one animation, and a component which would:

  • grab the current rotation, add or subtract 360
  • change the duration
  • update the existing animation with new values.

Here's an example with a couple of neat tricks:

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("animation-manager", {
    init: function() {
      // bind updateAnimation() so that we have new functions
      // doing exactly what we need
      this.rotateClockwise = this.updateAnimation.bind(this, 1);
      this.rotateCounterClockwise = this.updateAnimation.bind(this, -1);

      // bind the above functions to mouseenter/mouseleave
      this.el.addEventListener("mouseenter", this.rotateClockwise)
      this.el.addEventListener("mouseleave", this.rotateCounterClockwise)
    },
    updateAnimation: (function() {
      // this is an IIFE - there two vectors are created only once
      // even though the returned function is called multiple times
      const fromRotation = new THREE.Vector3();
      const toRotation = new THREE.Vector3();

      return function(dir) {
        // get current rotation, and move the target rotation by 360 or -360
        // depending on the direction
        fromRotation.copy(this.el.getAttribute("rotation"));
        toRotation.copy(this.el.getAttribute("rotation"));
        toRotation.y += dir * 360

        // update the animation
        this.el.setAttribute("animation", {
          "from": AFRAME.utils.coordinates.stringify(fromRotation),
          "to": AFRAME.utils.coordinates.stringify(toRotation),
          "dur": dir == -1 ? "8000" : "1000"
        })
      }
    })()
  })
</script>
<a-scene cursor="rayOrigin: mouse" raycaster="objects: a-box">
  <a-box position="0 1 -4" color="blue" animation-manager 
         animation="property: rotation; to:0 -360 0; loop:true; easing:linear; dur:8000">
    <a-sphere position="2 0 0" color="green" radius="0.25" foo></a-sphere>
  </a-box>
</a-scene>

The neat tricks being function binding, IIFEs, and AFRAME.Utils

Upvotes: 1

Related Questions