是否可以使用knockout observable进行数字动画行为?

时间:2016-06-17 08:08:28

标签: javascript animation knockout.js knockout-3.0

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



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>
&#13;
value
&#13;
&#13;
&#13;

每次按下按钮value2都会增加,-- file: myClass.lua local myClass = {} myClass.__index = myClass setmetatable(myClass, { __call = function (cls, ...) return cls.new(...) end, }) function myClass.new(init_size) local self = setmetatable({}, myClass) self.max_size = init_size return self end function myClass:set_max_size(x) self.max_size = x print(myClass:get_max_size()) -- <= [1] end function myClass:get_max_size() return self.max_size end return myClass 将被数字动画设置为动画(例如Qt QML)。在这个例子中,这个完成了新变量和自制定时器。

问题

使用自定义绑定或自定义扩展程序,是否有任何方法可以在淘汰赛中执行此类行为?

1 个答案:

答案 0 :(得分:2)

我已经勾勒出自定义“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; });
    }
};