VueJs -动画数字更改

bqf10yzr  于 2023-06-24  发布在  Vue.js
关注(0)|答案(5)|浏览(147)

我希望使用VueJs动画数字变化。
例如,我有:

{{ number }}

然后number0变为100,我希望元素计数到100,而不是直接跳到它。
我如何在不使用任何第三方(纯Js/VueJs)(不包括VueJs)的情况下做到这一点?

edqdpe6u

edqdpe6u1#

得到了这个工作作为一个自定义组件:https://jsfiddle.net/5nobcLq0/5/
联系我们

<body>
  <input v-model="number">
  <animated-number :number="number"></animated-number>
</body>

js

Vue.component('animated-number', {

  template:"{{ displayNumber }}",
  props: {'number': { default:0 }},

  data () {
    return {
      displayNumber:0,
      interval:false
    }
  },

  ready () {
    this.displayNumber = this.number ? this.number : 0;
  },

  watch: {
    number () {
      clearInterval(this.interval);

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

      this.interval = window.setInterval(() => {
        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;
        }
      }, 20);
    }
  }
})

new Vue({
  el:'body',
});
c9qzyr3d

c9qzyr3d2#

我意识到这是一个较旧的帖子,但我正在寻找类似的东西,我发现了一个直接来自vue.js 2.0文档的示例。你可以在这里找到它:https://v2.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>

我希望这有帮助!蒂姆

rks48beu

rks48beu3#

如果使用GSAP

我采用了Jeff的答案,并使用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>

更新

当我使用这个组件时,它已经发展到接受持续时间和格式,here is a gist

7cwmlq89

7cwmlq894#

如果你想支持浮点数和负数的动画,这个vue组件也可以工作。它建立在@jeff的答案之上。更改数字5或使其成为一个 prop ,以控制动画发生的快慢。

<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>
cnwbcb6i

cnwbcb6i5#

如果你想要一个vue 3组合API组件,基于@jeff和@AnandShiva的答案。这就是:

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

<script setup>
const props = defineProps({
  value: {
    type: Number,
    default: 0,
  },
  speed: {
    // smaller is faster
    type: Number,
    default: 5,
  },
});

const displayNumber = ref(props.value);
let interval = null;

watch(
  () => props.value,
  (newVal) => {
    clearInterval(interval);

    if (newVal === displayNumber.value) {
      return;
    }

    interval = setInterval(() => {
      if (Math.floor(displayNumber.value) !== Math.floor(newVal)) {
        var change = (newVal - displayNumber.value) / props.speed;
        change = change >= 0 ? Math.ceil(change) : Math.floor(change);
        displayNumber.value = displayNumber.value + change;
      } else {
        displayNumber.value = newVal;
        clearInterval(interval);
      }
    }, 20);
  }
);
</script>

相关问题