VueJs - Animate数字更改

时间:2016-02-21 02:34:30

标签: javascript animation vue.js

我希望使用VueJs为数字更改设置动画。

例如我有:

{{ number }}

然后number0更改为100,我希望该元素计数到100,而不是直接跳到它。

如果不使用除VueJs之外的任何第三方(纯Js / VueJs),我该如何做到这一点?

4 个答案:

答案 0 :(得分:24)

将此作为自定义组件:https://jsfiddle.net/5nobcLq0/5/

<强> HTML

<body>

  <input v-model="number">

  <animated-number :number="number"></animated-number>

</body>

<强> JS

Vue.component('animated-number',{
template:"{{displayNumber}}",
props:{'number':{default:0}},
data: function(){

    return {

      displayNumber:0,
      interval:false

    }

  },

  ready:function(){

    this.displayNumber = this.number ? this.number : 0;

  },

  watch:{

    number: function(){

      clearInterval(this.interval);

        if(this.number == this.displayNumber){
          return;
        }

        this.interval = window.setInterval(function(){

          if(this.displayNumber != this.number){

            var change = (this.number - this.displayNumber) / 10;

            change = change >= 0 ? Math.ceil(change) : Math.floor(change);

            this.displayNumber = this.displayNumber + change;

          }

        }.bind(this), 20);

    }

  }
})

new Vue({

  el:'body',

});

答案 1 :(得分:6)

我意识到这是一篇较旧的帖子,但我正在寻找类似的东西,我直接从vue.js 2.0文档中找到了一个例子。您可以在此处找到它:https://vuejs.org/v2/guide/transitioning-state.html#Organizing-Transitions-into-Components

我在下面的代码段中重新创建了它。

// This complex tweening logic can now be reused between
// any integers we may wish to animate in our application.
// Components also offer a clean interface for configuring
// more dynamic transitions and complex transition
// strategies.
Vue.component('animated-integer', {
  template: '<span>{{ tweeningValue }}</span>',
  props: {
    value: {
      type: Number,
      required: true
    }
  },
  data: function() {
    return {
      tweeningValue: 0
    }
  },
  watch: {
    value: function(newValue, oldValue) {
      this.tween(oldValue, newValue)
    }
  },
  mounted: function() {
    this.tween(0, this.value)
  },
  methods: {
    tween: function(startValue, endValue) {
      var vm = this

      function animate() {
        if (TWEEN.update()) {
          requestAnimationFrame(animate)
        }
      }
      new TWEEN.Tween({
          tweeningValue: startValue
        })
        .to({
          tweeningValue: endValue
        }, 500)
        .onUpdate(function() {
          vm.tweeningValue = this.tweeningValue.toFixed(0)
        })
        .start()
      animate()
    }
  }
})
// All complexity has now been removed from the main Vue instance!
new Vue({
  el: '#example-8',
  data: {
    firstNumber: 20,
    secondNumber: 40
  },
  computed: {
    result: function() {
      return this.firstNumber + this.secondNumber
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.4.3/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tween.js"></script>
<div id="example-8">
  <input v-model.number="firstNumber" type="number" step="20"> +
  <input v-model.number="secondNumber" type="number" step="20"> = {{ result }}
  <p>
    <animated-integer v-bind:value="firstNumber"></animated-integer> +
    <animated-integer v-bind:value="secondNumber"></animated-integer> =
    <animated-integer v-bind:value="result"></animated-integer>
  </p>
</div>

我希望有所帮助! 添

答案 2 :(得分:0)

如果您使用GSAP

我接受了杰夫的回答,并使用GSAP对其进行了简化。

import gsap from 'gsap';

Vue.component('animate-integer', {
  template: '<span>{{displayValue}}</span>',
  props: { value: { default: 0 } },

  data() {
    return {
      displayValue: this.value,
      tweenValue: this.value
    };
  },

  watch: {
    value() {
      gsap.to(this, {
        tweenValue: this.value,
        onUpdate: () => {
          this.displayValue = Math.ceil(this.tweenValue);
        }
      });
    }
  }
});

用法:

<input v-model="value">
<animate-integer :value="value"></animated-integer>

答案 3 :(得分:0)

如果要支持浮点数和负数的动画,此vue组件也将起作用。它基于@jeff's答案。更改数字5或使其成为控制动画发生的快慢的道具。

<template>
  <span>{{displayNumber}}</span>
</template>

<script>

export default {
  data () {
    return {
      displayNumber: 0,
      counter: false
    };
  },
  props: {
    number: {
      type: Number,
      default: 0
    }
  },
  watch: {
    number () {
      clearInterval(this.counter);
      if (this.number === this.displayNumber) {
        return;
      }
      this.counter = setInterval(function () {
        if (Math.floor(this.displayNumber) !== Math.floor(this.number)) {
          var change = (this.number - this.displayNumber) / 5;
          change = change >= 0 ? Math.ceil(change) : Math.floor(change);
          this.displayNumber = this.displayNumber + change;
        } else {
          this.displayNumber = this.number;
          clearInterval(this.counter);
        }
      }.bind(this), 20);
    }
  }
};
</script>