【问题标题】:VueJs - Animate number changesVueJs - 动画数字变化
【发布时间】:2016-02-21 02:34:30
【问题描述】:

我正在寻找使用 VueJs 动画数字变化。

例如我有:

{{ number }}

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

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

【问题讨论】:

  • 开始回答,但我要出去过夜。这是我正在研究的内容:jsfiddle.net/5nobcLq0/1 基本上,这个想法是将数字与显示的数字分开,如果它们不同,则将显示数字增加到实数。我认为理想情况下这将是它自己的一个组件,或者像v-animate 这样的指令。我明天再看一下
  • 我查看了 v-animate 但找不到任何对我有帮助的东西

标签: javascript animation vue.js


【解决方案1】:

将此作为自定义组件工作: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 () {
    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',
});

【讨论】:

  • 谢谢,这正是我要找的!
  • 你能调整它以支持小数吗?当前,如果数字不完整,它会闪烁并上下跳跃
  • change = change &gt;= 0 ? Math.ceil(change) : Math.floor(change); 使用Math.floorMath.ceil 来舍入更改。只需删除该行,它应该可以工作。您可能想要四舍五入到一定数量的小数。
  • 我建议使用 requestAnimationFrame() 而不是 setInterval()
【解决方案2】:

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

我在下面的 sn-p 中重新创建了它。

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

希望对您有所帮助! 蒂姆

【讨论】:

  • 您可能需要考虑使用 this.$nextTick 而不是 requestAnimationFrame,因为它已集成到 VueJs dom 更新过程中。
  • 嗨 @BenjaminEllis,我刚刚从 vue.js 2.x 文档中复制了示例。所以也许使用 requestAnimationFrame 是有原因的,否则我会假设他们会在示例中使用它?
【解决方案3】:

如果你使用 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

【讨论】:

  • 如果没有输入,如果我们想在页面加载后制作动画呢?
  • @OutForCode 输入不是必须的,我把它放在那里作为例子。传入任何你想要的值,``,只要这个值改变,组件就会动画。如果这更清楚,我会更新答案。
  • 我可以得到它。但我正在寻找加载时间动画。一旦页面加载或进入视图,值不会改变,它应该从 0 动画到值。你能帮我解决这个问题吗?
  • 您可以执行类似 :value="inView ? myValue : 0" 的操作。 inView 在您准备好动画之前为 false,然后将其设置为 true。
【解决方案4】:

如果你想支持浮点数和负数的动画,这个 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>


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    相关资源
    最近更新 更多