Skip to content

Instantly share code, notes, and snippets.

@raiden-dev
Created September 18, 2012 11:25
Show Gist options
  • Save raiden-dev/3742672 to your computer and use it in GitHub Desktop.
Save raiden-dev/3742672 to your computer and use it in GitHub Desktop.
KnockoutJS Custom Binding: animation
<!doctype html>
<html>
<head>
<title>KnockoutJS Custom Binding: animation</title>
<style>
/* WARNING: Only webkit animation defined */
@-webkit-keyframes zigzag {
0% { top: 0px; left: 0px; }
25% { top: 200px; left: 200px; }
50% { top: 0px; left: 400px; }
75% { top: 200px; left: 600px; }
100% { top: 0px; left: 800px; }
}
.animation {
position: absolute;
width: 20px;
height: 20px;
top: 0;
left: 0;
background: purple;
border-radius: 10px;
}
.is-animation_start {
-webkit-animation: zigzag 2s ease 1s forwards;
}
.is-animation_end {
top: 0px;
left: 800px;
}
</style>
<script>
window.fallbacks = {
"animation": [
{
"properties": {
"top": "200px",
"left": "200px"
},
"delay": 1000,
"duration": 500
},
{
"properties": {
"top": "0px",
"left": "400px"
},
"duration": 500
},
{
"properties": {
"top": "200px",
"left": "600px"
},
"duration": 500
},
{
"properties": {
"top": "0px",
"left": "800px"
},
"duration": 500
}
]
}
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
</head>
<body>
<div class="animation" data-bind="animation: {
test: isRenderEnd,
startClass: 'is-animation_start',
endClass: 'is-animation_end',
fallback: fallbacks.animation
}"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.1.0/knockout-min.js"></script>
<script>
/**
* KO: CSS Animation w/ jQuery fallback.
* @param {object} Binding value.
* @config {object}
* {obBoolean} [test] Observable, triggers the animation.
* {string} [startClass] Animation start class.
* {string} [endClass] Animation end class.
* {array} [fallback] Animation jQuery fallback JSON.
* @requires jQuery, Modernizr.cssanimations
* @example
* // View
* <div class="animation" data-bind="animation: {
* test: isRenderEnd,
* startClass: 'is-animation_start',
* endClass: 'is-animation_end',
* fallback: fallbacks.animation
* }"></div>
*/
ko.bindingHandlers.animation = {
update: function(element, valueAccessor) {
var value = valueAccessor();
var $el = $(element);
if (ko.utils.unwrapObservable(value.test)) {
if (Modernizr.cssanimations) {
$el.addClass(value.startClass);
$el.on('animationend mozanimationend webkitAnimationEnd OAnimationEnd oanimationend oAnimationEnd', function() {
$el.addClass(value.endClass);
$el.removeClass(value.startClass);
});
}
else {
$.each(value.fallback, function(index) {
if (this.selector) {
$(this.selector)
.delay(this.delay)
.animate(this.properties, this.duration, function() {
if (index === value.fallback.length-1) {
$el.trigger('jqanimationend');
}
});
}
else {
$el
.delay(this.delay)
.animate(this.properties, this.duration, function() {
if (index === value.fallback.length-1) {
$el.trigger('jqanimationend');
}
});
}
});
$el.on('jqanimationend', function() {
$el.addClass(value.endClass);
$el.attr('style', '');
});
}
value.test(false);
}
}
}
$(function() {
var ViewModel = function() {
var self = this;
self.isRenderEnd = ko.observable(false);
/* Simulate "renderEnd" */
setTimeout(function() {
self.isRenderEnd(true);
}, 1000);
}
ko.applyBindings(new ViewModel());
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment