Search code examples
javascriptaframewebvr

How to stop tick function executing code in a-frame once condition is met?


I am using the tick function in an a-frame component to animate. I do this by setting a true/false flag and then incrementing a number which updates a vertices. I have created a simplified version below that illustrates the process. I would like to understand how better to use the tick function.

Specifically, my question is in 2 parts.

  1. How can I stop the tick function running once my function within it is 'completed' (in this case when curr === to)?

  2. How to reset the flag that I set in order to trigger it in the first place so I can then retrigger it later on?

You will see below I have a patchy solution to stop it (I check that the curr value I am incrementing has not exceeded the to value && this.curr < 9 ) but this is just to stop it from running endlessly on the screen/console.

I have tried to set the 'change' attribute back to false at the end of the function but again it seems to do this over and over and it seems it will effect performance to have something constantly changing an attribute? Maybe I'm wrong. Please see my code below.

The component;

AFRAME.registerComponent('tickquery', {

    schema: {    
        change: {type: 'boolean', default: false},
    },

    init: function () { 
        this.curr = 0
        this.to = 10
        this.dur = 400
        this.parent = this.el
    },

    update: function () {

    },

    tick: function (t, td) {
        if ( this.data.change === true && this.curr < 9 ){
            if ( this.curr < this.to ) {
                var step = this.stepCalc(this.curr, this.to, this.dur, td)
                this.curr += step
                this.parent.setAttribute('value', this.curr)
                //console.log(this.curr)
            }        
        }
    },

    stepCalc: function (curr, to, dur, td) {
        var distance = Math.abs(curr - to)
        var speed = distance/dur
        var step = speed*td
        return step;
    },

});

The HTML;

<a-scene test>
    <a-text 
        id="ticker" 
        tickquery 
        value="0"
        color="#333"
        position="0 0 -5">
    </a-text>
</a-scene>

And a component to trigger the change;

AFRAME.registerComponent('test', {
  init: function () {
    setTimeout(function(){
          var ticker = document.getElementById('ticker');
          ticker.setAttribute('tickquery', {'change': true});
    }, 2000);           
  },      
});

And here is a fiddle (wait 2 seconds and see the text update with the tick)

I may be approaching this in the wrong way so please advise if there is a better way to handle this. Any more info needed, please let me know. Thank you.


Solution

  • If You want to use a flag, then you have to alter your code a bit:

    init: function() {
       this.animationRunning = true;
    },
    tick: function (t, td) {
      if(animationRunning) {
        if ( this.curr < 9 ) {
            if ( this.curr < this.to ) {
                var step = this.stepCalc(this.curr, this.to, this.dur, td)
                this.curr += step
                this.parent.setAttribute('value', this.curr)
                //console.log(this.curr)
            }        
        } else {
          this.animationRunning = false;
        }
      }
    }
    

    so i have a flag, it will be up until the conditions are met, then it will become false.


    Now, resetting the flag. It really depends, where you want to check the conditions for a reset. If You want to check something within your component, you can also do a check in the tick(), which will reset the flag if some conditions are met.

    If You want to do it from outside the component, You can add another function to Your component

    restart: function() {
       this.curr = 0;
       this.animationRunning = true;
    }
    

    and call it :yourElementReference.components.tickquery.restart(). Check it out in this fiddle.


    I'm not sure about using the update + schema mechanisms. You could reset the values in the update function, and set the change attrubute to its opposite to call the update like i did here.

    Still these are so simple operations, it should have no impact on the performance here.