代码之家  ›  专栏  ›  技术社区  ›  Nick Bondarenko

数字动画行为是否可以在击倒时观察到?

  •  4
  • Nick Bondarenko  · 技术社区  · 8 年前

    例如,您有这样的简单模型:

    var ViewModel = function() {
        var timer,
            self = this;
            
        this.value = ko.observable(10);
        this.value2 = ko.observable(10);
    
        this.value.subscribe(function(newValue){
            clearInterval(timer)
            timer = setInterval(function(){
               if (self.value2() == newValue) {
                  clearInterval(timer);
                  return;
               }
               
               self.value2(self.value2() + 1);
            }, 100);
        });    
    
        
        this.update = function(){
            this.value(this.value() + 10);
        };
    };
     
    ko.applyBindings(new ViewModel());
    body { font-family: arial; font-size: 14px; }
    .liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
    .liveExample input { font-family: Arial; }
    .liveExample b { font-weight: bold; }
    .liveExample p { margin-top: 0.9em; margin-bottom: 0.9em; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <div class='liveExample'>   
        <p>Value: <input data-bind='value: value' /></p> 
        <p>Animated value: <input data-bind='value: value2' /></p> 
        <button data-bind="click: update">
        +10
        </button>
    </div>

    每次按下按钮 value 将递增,并且 value2 将使用数字动画制作动画(例如,在Qt QML中)。在这个示例中,这个函数抛出了新变量和自制计时器。

    问题

    这里有什么方法可以通过自定义绑定或自定义扩展器实现这种行为吗?

    1 回复  |  直到 8 年前
        1
  •  2
  •   TSV    8 年前

    我已经绘制了自定义“animatedValue”绑定的草图,希望能有所帮助:

    function createValueAccessor(val) {
      var displayValue = ko.observable(val());
      var timer;
      val.subscribe(function(newValue) {
        clearInterval(timer)
        timer = setInterval(function(){
          if(displayValue() == newValue) {
            clearInterval(timer);
          } else {
            displayValue(displayValue() + 1);
          }
        }, 100);
      });    
      return function() {
        return displayValue;
      }
    }
    
    // Binding handler
    
    ko.bindingHandlers.animatedValue = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var value = valueAccessor();
            ko.bindingHandlers.value.init(element, createValueAccessor(value), allBindingsAccessor, viewModel);
        }
    };
    

    var ViewModel = function() {
        var timer,
            self = this;
            
        this.value = ko.observable(10);
        this.value2 = ko.observable(10);
    
        this.value.subscribe(function(newValue){
            clearInterval(timer)
            timer = setInterval(function(){
               if (self.value2() == newValue) {
                  clearInterval(timer);
                  return;
               }
               
               self.value2(self.value2() + 1);
            }, 100);
        });    
    
        
        this.update = function(){
            this.value(this.value() + 10);
        };
    };
     
    function createValueAccessor(val) {
      var displayValue = ko.observable(val());
      var timer;
      val.subscribe(function(newValue) {
        clearInterval(timer)
        timer = setInterval(function(){
          if(displayValue() == newValue) {
            clearInterval(timer);
          } else {
            displayValue(displayValue() + 1);
          }
        }, 100);
      });    
      return function() {
        return displayValue;
      }
    }
    
    // Binding handler
    
    ko.bindingHandlers.animatedValue = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var value = valueAccessor();
            ko.bindingHandlers.value.init(element, createValueAccessor(value), allBindingsAccessor, viewModel);
        }
    };
    
    ko.bindingHandlers.animatedText = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var value = valueAccessor();
            var displayValue = ko.observable(value());
            var timer;
            value.subscribe(function(newValue) {
              clearInterval(timer)
                timer = setInterval(function() {
                  if(displayValue() == newValue) {
                    clearInterval(timer);
                  } else {
                    displayValue(displayValue() + 1);
                    ko.bindingHandlers.text.update(element, function() { return displayValue; });
                  }
                }, 100);
            });    
          ko.bindingHandlers.text.update(element, function() { return displayValue; });
        }
    };
    
    
    ko.applyBindings(new ViewModel());
    body { font-family: arial; font-size: 14px; }
    .liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
    .liveExample input { font-family: Arial; }
    .liveExample b { font-weight: bold; }
    .liveExample p { margin-top: 0.9em; margin-bottom: 0.9em; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <div class='liveExample'>   
        <p>Value: <input data-bind='value: value' /></p> 
        <p>Animated value: <input data-bind='value: value2' /></p> 
        <p>Animated value via animatedText binding: <span data-bind='animatedText: value'></span></p> 
        <p>Animated value via binding: <input data-bind='animatedValue: value' /></p>
        <button data-bind="click: update">
        +10
        </button>
    </div>

    更新1

    我添加了“animatedText”自定义绑定处理程序。

    ko.bindingHandlers.animatedText = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var value = valueAccessor();
            var displayValue = ko.observable(value());
            var timer;
            value.subscribe(function(newValue) {
              clearInterval(timer)
                timer = setInterval(function() {
                  if(displayValue() == newValue) {
                    clearInterval(timer);
                  } else {
                    displayValue(displayValue() + 1);
                    ko.bindingHandlers.text.update(element, function() { return displayValue; });
                  }
                }, 100);
            });    
          ko.bindingHandlers.text.update(element, function() { return displayValue; });
        }
    };