Search code examples
animationthree.js3daframewebvr

A-frame random animation delay


I am creating a scene using A-frame (https://aframe.io) and I'm currently using an animation in my scene. I'm wondering how I can randomize the delay on my animation so the animation delays from a random amount from 0 to 2 seconds. How can this be done? My current code:

 <html>
  <head>
    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
  </head>
  <body>
    <a-scene>
      
      
      <!--Animte the box with a ranom delay from 0 - 2 seconds. -->
      <a-box position="-1 1.6 -5" animation="property: position; delay: 1000; to: 1 8 -10; dur: 2000; easing: linear; loop: true" color="tomato"></a-box>

      <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>
  </body>
</html>

I currently have the delay set to 1000 (1 second since the delay is in milliseconds). What should happen instead is the delay should be a random amount from 0 - 2000 since 2000 milliseconds is 2 seconds. How can this be done?


Solution

  • Random delay only at the start - first cycle

    Register the a-box component with a custom one that will do the math and apply it to the animation on the a-box <a-box position="-1 1.6 -5" random-delay animation color="tomato"></a-box>.

    1. Building the custom aframe component:
        AFRAME.registerComponent('random-delay', {
            init: function (el) {
             // this.el points to the element the component is placed on 
             var el = this.el;
    
            }
        });
    
    1. Set your min and max values
        AFRAME.registerComponent('random-delay', {
            init: function (el) {
                var el = this.el;
                var min = 0;
                var max = 2000;
    
            }
        });
    
    1. Math.floor(Math.random() * (max - min + 1)) + min returns an integer random number between min and max and than we build the string for the animation:
        AFRAME.registerComponent('random-delay', {
            init: function (el) {
                var el = this.el;
                var min = 0;
                var max = 2000;
    
                // generates a random number between the set min and max
                var delay = Math.floor(Math.random() * (max - min + 1)) + min;
                var animation = `property: position; delay: ${delay}; from: -1 1.6 -5; to: 1 8 -10; dur: 2000; easing: linear; loop: true`
    
            }
        });
    
    1. Apply the animation string with the delay generated with .setAttribue():
        AFRAME.registerComponent('random-delay', {
            init: function (el) {
                var el = this.el;
                var min = 0;
                var max = 2000;
    
                // generates a random number between the set min and max
                var delay = Math.floor(Math.random() * (max - min + 1)) + min;
                // builds the string for the animation
                var animation = `property: position; delay: ${delay}; to: 1 8 -10; dur: 2000; easing: linear; loop: true`
    
                // updating the animation component with the .setAttribute() function
                el.setAttribute('animation', animation)
    
            }
        });
    

    Random delay on every animation cycle

    1. place these lines of code into a new function:
    function setAnimation(min, max) {
        // generates a random number between the set min and max
        var delay = Math.floor(Math.random() * (max - min + 1)) + min;
        var animation = `property: position; delay: ${delay}; from: -1 1.6 -5; to: 1 8 -10; dur: 2000; easing: linear; `
        console.log(delay);
        // updating the animation component with the .setAttribute function
        el.setAttribute('animation', animation)
    }
    
    1. At every animationcomplete event set a new animation with the function we created
    function setAnimation(min, max) {
        // generates a random number between the set min and max
        var delay = Math.floor(Math.random() * (max - min + 1)) + min;
        var animation = `property: position; delay: ${delay}; from: -1 1.6 -5; to: 1 8 -10; dur: 2000; easing: linear; `
        console.log(delay);
        // updating the animation component with the .setAttribute function
        el.setAttribute('animation', animation)
    }
    

    The result should look something like this:

    <html>
    
    <head>
        <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    </head>
    
    <script>
        AFRAME.registerComponent('random-delay', {
            init: function (el) {
                // this.el points to the element the component is placed on 
                var el = this.el;
                let min = 0;
                let max = 2000;
                // initial animation
                setAnimation(min, max)
    
                function setAnimation(min, max) {
                    // generates a random number between the set min and max
                    let delay = Math.floor(Math.random() * (max - min + 1)) + min;
                    let animation = `property: position; delay: ${delay}; from: -1 1.6 -5; to: 1 8 -10; dur: 2000; easing: linear; `
                    console.log(delay);
                    // updating the animation component with the .setAttribute function
                    el.setAttribute('animation', animation)
                }
                el.addEventListener('animationcomplete', () => {
                    setAnimation(min, max)
                });
            }
        });
    </script>
    
    <body>
        <a-scene>
            <a-box position="-1 1.6 -5" random-delay animation autoplay color="tomato">
            </a-box>
    
            <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>
    </body>
    
    </html>