Skip to content
Browse files

added animateTo method. fixes #26

  • Loading branch information...
1 parent 75584dc commit f6a1c1046e942466877d3dcff82005211623a0b6 @Prinzhorn committed Jun 7, 2012
Showing with 78 additions and 6 deletions.
  1. +18 −2 README.md
  2. +0 −1 skrollr-0.3.8.js
  3. +1 −0 skrollr-0.3.9.js
  4. +59 −3 skrollr.js
View
20 README.md
@@ -1,7 +1,7 @@
-skrollr (v 0.3.8)
+skrollr (v 0.3.9)
======
-**Parallax\* scrolling** lib with **zero dependencies** (seriously, you **don't** need jQuery) in just over **4.8k minified** (2.3k gzipped). No JavaScript skills needed.
+**Parallax\* scrolling** lib with **zero dependencies** (seriously, you **don't** need jQuery) in just over **5.3k minified** (2.5k gzipped). No JavaScript skills needed.
\**Actually, skrollr is much more. It's a full-fledged scrolling animation library. In fact, you can use it and still have no parallax scrolling at all. But calling it "parallax" is part of my ongoing effort to play buzzword bingo as often as possible. By the way, skrollr leverages HTML5 and CSS3 ;-)*
@@ -212,6 +212,22 @@ Calling ```init()``` returns an instance of skrollr which exposes a public api.
Sets the top offset using window.scroll(0, top)
+#### animateTo(top[, options])
+
+Animates the scroll position from current position to ```top```. Possible Options include
+
+##### duration
+
+How long the animation should run in milliseconds. The default is ```1000``` or one second.
+
+##### easing
+
+The name of an easing function. The same functions can be used as for property animations. Default is ```linear``` .
+
+##### done
+
+A function to be called after the animation finished. When you pass a ```top``` value, which is the same as the current, then the function will be called immediately.
+
#### on(name, fn)
Set a listener function for one of the events described in the options section (beforerender, render). Only one listener can be attachet at a given time. This method overwrites the current listener, if any.
View
1 skrollr-0.3.8.js
@@ -1 +0,0 @@
-/*! skrollr v0.3.8 https://github.com/Prinzhorn/skrollr | free to use under terms of MIT license */(function(a,b,c){function A(e){O=this,e=e||{};if(e.easing)for(var h in e.easing)z[h]=e.easing[h];Q={beforerender:e.beforerender||d,render:e.render||d},R=[],S=e.maxKeyFrame||0,T="down",U=-1,V=0;var j=b.getElementsByTagName("*"),k=[];for(var l=0;l<j.length;l++){var m=j[l],o=[];if(!m.attributes)continue;for(var p=0;p<m.attributes.length;p++){var q=m.attributes[p],r=q.name.match(n);if(r!==null){var s,t;s=(r[2]|0)*(e.scale||1),t={frame:s,props:q.value},o.push(t),r[1]==="-end"&&k.push(t),s>S&&(S=s)}}o.length&&(R.push({element:m,keyFrames:o}),K(m,i))}for(var l=0;l<k.length;l++){var t=k[l];t.frame=S-t.frame}for(var l=0;l<R.length;l++){var u=R[l];u.keyFrames.sort(function(a,b){return a.frame-b.frame}),D(u),F(u)}var v=b.createElement("div"),w=v.style;w.width="1px",w.position="absolute",w.right=w.top=w.zIndex="0",g.appendChild(v);var x=function(){w.height=S+f.clientHeight+"px"};return a.addEventListener?a.addEventListener("resize",x,!1):a.attachEvent("onresize",x),x(),C(),v=k=e=c,O}"use strict";var d=function(){},e=Object.prototype.hasOwnProperty,f=b.documentElement,g=b.body,h="hidden",i="skrollable",j="linear",k=500,l=a.requestAnimationFrame||a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame||a.msRequestAnimationFrame||function(a){setTimeout(a,1e3/30)},m=/^\s*(.*)\s$/,n=/^data(-end)?-?(\d+)?$/,o=/:|;/g,p=/^([a-z-]+)\[(\w+)\]$/,q=/-([a-z])/g,r=/(:?\+|-)?[\d.]+/g,s=/rgba?\(\s*-?\d+\s*,\s*-?\d+\s*,\s*-?\d+/g,t=/[a-z-]+-gradient/g,u=/^O|Moz|webkit|ms/,v,w;if(a.getComputedStyle){var x=a.getComputedStyle(g,null);for(var y in x)if(v=y.match(u)||+y==y&&x[y].match(u))break}v=(v||[""])[0],w="-"+v.toLowerCase()+"-",u=c;var z={begin:function(){return 0},end:function(){return 1},linear:function(a){return a},quadratic:function(a){return a*a},cubic:function(a){return a*a*a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5},bounce:function(a){var b;switch(!0){case a<=.5083:b=3;break;case a<=.8489:b=9;break;case a<=.96208:b=27;break;case a<=.99981:b=91;break;default:return 1}return 1-Math.abs(3*Math.cos(a*b*1.028)/b)}};A.prototype.setScrollTop=function(b){a.scroll(0,b)},A.prototype.getScrollTop=function(b){return a.pageYOffset||f.scrollTop||g.scrollTop||0},A.prototype.on=function(a,b){Q[a]=b||d},A.prototype.off=function(a){Q[a]=d};var B=function(a,b){var c=a.keyFrames;if(b<c[0].frame)K(a.element,h);else if(b>=c[c.length-1].frame){L(a.element,h);var d=c[c.length-1],f;for(var g in d.props)e.call(d.props,g)&&(f=I(d.props[g].value),J(a.element,g,f))}else{L(a.element,h);for(var i=0;i<c.length-1;i++)if(b>=c[i].frame&&b<=c[i+1].frame){var j=c[i],k=c[i+1];for(var g in j.props)if(e.call(j.props,g)){var l=(b-j.frame)/(k.frame-j.frame);l=j.props[g].easing(l);var f=H(j.props[g].value,k.props[g].value,l);f=I(f),J(a.element,g,f)}break}}},C=function(){V=O.getScrollTop(),V<0&&(V=0);if(U!==V){T=V>=U?"down":"up";var a={curTop:V,lastTop:U,maxTop:S,direction:T},b=Q.beforerender.call(O,a);if(b!==!1){for(var c=0;c<R.length;c++)B(R[c],V);U=V,Q.render.call(O,a)}}l(function(){C()})},D=function(a){for(var b=0;b<a.keyFrames.length;b++){var c=a.keyFrames[b],d=c.props.split(o),e,f,g;c.props={};for(var h=0;h<d.length-1;h+=2)e=d[h],f=d[h+1],g=e.match(p),g!==null?(e=g[1],g=g[2]):g=j,f.indexOf("!")||console.log(f.slice(1)),f=f.indexOf("!")?E(f):[f.slice(1)],c.props[e]={value:f,easing:z[g]}}},E=function(a){var b=[];return s.lastIndex=0,a=a.replace(s,function(a){return a.replace(r,function(a){return a/255*100+"%"})}),t.lastIndex=0,a=a.replace(t,function(a){return w+a}),a=a.replace(r,function(a){return b.push(+a),"?"}),b.unshift(a),b},F=function(a){var b={};for(var c=0;c<a.keyFrames.length;c++)G(a.keyFrames[c],b);b={};for(var c=a.keyFrames.length-1;c>=0;c--)G(a.keyFrames[c],b)},G=function(a,b){for(var c in b)e.call(a.props,c)||(a.props[c]=b[c]);for(var c in a.props)b[c]=a.props[c]},H=function(a,b,c){if(a.length!==b.length)throw"Can't interpolate between \""+a[0]+'" and "'+b[0]+'"';var d=[a[0]];for(var e=1;e<a.length;e++)d[e]=a[e]+(b[e]-a[e])*c;return d},I=function(a){var b=1;return a[0].replace(/\?/g,function(){return a[b++]})},J=function(a,b,c){var d=a.style;b=b.replace(q,function(a,b){return b.toUpperCase()}).replace("-","");if(b==="zIndex")d[b]=""+(c|0);else try{d[v+b.slice(0,1).toUpperCase()+b.slice(1)]=c,d[b]=c}catch(e){}if(P.setStyle)for(var f=0;f<plugins.setStyle.length;f++)P.setStyle[0].call(this,a,b,c)},K=function(a,b){N(a.className).indexOf(N(b))===-1&&(a.className=M(a.className+" "+b))},L=function(a,b){a.className=M(N(a.className).replace(N(b)," "))},M=function(a){return a.replace(m,"$1")},N=function(a){return" "+a+" "},O,P={},Q,R,S,T,U,V;a.skrollr={init:function(a){return O||new A(a)},plugin:function(a,b){P[a]?P[a].push(b):P[a]=[b]},VERSION:"0.3.8"}})(window,document);
View
1 skrollr-0.3.9.js
@@ -0,0 +1 @@
+/*! skrollr v0.3.9 https://github.com/Prinzhorn/skrollr | free to use under terms of MIT license */(function(a,b,c){function A(e){P=this,e=e||{};if(e.easing)for(var h in e.easing)z[h]=e.easing[h];R={beforerender:e.beforerender||d,render:e.render||d},S=[],T=e.maxKeyFrame||0,U="down",V=-1,W=0;var j=b.getElementsByTagName("*"),k=[];for(var l=0;l<j.length;l++){var m=j[l],o=[];if(!m.attributes)continue;for(var p=0;p<m.attributes.length;p++){var q=m.attributes[p],r=q.name.match(n);if(r!==null){var s,t;s=(r[2]|0)*(e.scale||1),t={frame:s,props:q.value},o.push(t),r[1]==="-end"&&k.push(t),s>T&&(T=s)}}o.length&&(S.push({element:m,keyFrames:o}),K(m,i))}for(var l=0;l<k.length;l++){var t=k[l];t.frame=T-t.frame}for(var l=0;l<S.length;l++){var u=S[l];u.keyFrames.sort(function(a,b){return a.frame-b.frame}),D(u),F(u)}var v=b.createElement("div"),w=v.style;w.width="1px",w.position="absolute",w.right=w.top=w.zIndex="0",g.appendChild(v);var x=function(){w.height=T+f.clientHeight+"px"};return a.addEventListener?a.addEventListener("resize",x,!1):a.attachEvent("onresize",x),x(),C(),v=k=e=c,P}"use strict";var d=function(){},e=Object.prototype.hasOwnProperty,f=b.documentElement,g=b.body,h="hidden",i="skrollable",j="linear",k=1e3,l=a.requestAnimationFrame||a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame||a.msRequestAnimationFrame||function(a){setTimeout(a,1e3/30)},m=/^\s*(.*)\s$/,n=/^data(-end)?-?(\d+)?$/,o=/:|;/g,p=/^([a-z-]+)\[(\w+)\]$/,q=/-([a-z])/g,r=/(:?\+|-)?[\d.]+/g,s=/rgba?\(\s*-?\d+\s*,\s*-?\d+\s*,\s*-?\d+/g,t=/[a-z-]+-gradient/g,u=/^O|Moz|webkit|ms/,v,w;if(a.getComputedStyle){var x=a.getComputedStyle(g,null);for(var y in x)if(v=y.match(u)||+y==y&&x[y].match(u))break}v=(v||[""])[0],w="-"+v.toLowerCase()+"-",u=c;var z={begin:function(){return 0},end:function(){return 1},linear:function(a){return a},quadratic:function(a){return a*a},cubic:function(a){return a*a*a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5},bounce:function(a){var b;switch(!0){case a<=.5083:b=3;break;case a<=.8489:b=9;break;case a<=.96208:b=27;break;case a<=.99981:b=91;break;default:return 1}return 1-Math.abs(3*Math.cos(a*b*1.028)/b)}};A.prototype.animateTo=function(a,b){b=b||{};var e=O();X={startTop:P.getScrollTop(),topDiff:a-P.getScrollTop(),targetTop:a,duration:b.duration||k,startTime:e,endTime:e+(b.duration||k),easing:z[b.easing||j],done:b.done||d},X.topDiff||(X.done.call(P),X=c)},A.prototype.setScrollTop=function(b){a.scroll(0,b)},A.prototype.getScrollTop=function(b){return a.pageYOffset||f.scrollTop||g.scrollTop||0},A.prototype.on=function(a,b){R[a]=b||d},A.prototype.off=function(a){R[a]=d};var B=function(a,b){var c=a.keyFrames;if(b<c[0].frame)K(a.element,h);else if(b>=c[c.length-1].frame){L(a.element,h);var d=c[c.length-1],f;for(var g in d.props)e.call(d.props,g)&&(f=I(d.props[g].value),J(a.element,g,f))}else{L(a.element,h);for(var i=0;i<c.length-1;i++)if(b>=c[i].frame&&b<=c[i+1].frame){var j=c[i],k=c[i+1];for(var g in j.props)if(e.call(j.props,g)){var l=(b-j.frame)/(k.frame-j.frame);l=j.props[g].easing(l);var f=H(j.props[g].value,k.props[g].value,l);f=I(f),J(a.element,g,f)}break}}},C=function(){var a=d;if(X){var b=O();if(b>=X.endTime)P.setScrollTop(X.targetTop),a=X.done,X=c;else{var e=X.easing((b-X.startTime)/X.duration);P.setScrollTop(X.startTop+e*X.topDiff|0)}}W=P.getScrollTop(),W<0&&(W=0);if(V!==W){U=W>=V?"down":"up";var f={curTop:W,lastTop:V,maxTop:T,direction:U},g=R.beforerender.call(P,f);if(g!==!1){for(var h=0;h<S.length;h++)B(S[h],W);V=W,R.render.call(P,f)}a.call(P)}l(function(){C()})},D=function(a){for(var b=0;b<a.keyFrames.length;b++){var c=a.keyFrames[b],d=c.props.split(o),e,f,g;c.props={};for(var h=0;h<d.length-1;h+=2)e=d[h],f=d[h+1],g=e.match(p),g!==null?(e=g[1],g=g[2]):g=j,f.indexOf("!")||console.log(f.slice(1)),f=f.indexOf("!")?E(f):[f.slice(1)],c.props[e]={value:f,easing:z[g]}}},E=function(a){var b=[];return s.lastIndex=0,a=a.replace(s,function(a){return a.replace(r,function(a){return a/255*100+"%"})}),t.lastIndex=0,a=a.replace(t,function(a){return w+a}),a=a.replace(r,function(a){return b.push(+a),"?"}),b.unshift(a),b},F=function(a){var b={};for(var c=0;c<a.keyFrames.length;c++)G(a.keyFrames[c],b);b={};for(var c=a.keyFrames.length-1;c>=0;c--)G(a.keyFrames[c],b)},G=function(a,b){for(var c in b)e.call(a.props,c)||(a.props[c]=b[c]);for(var c in a.props)b[c]=a.props[c]},H=function(a,b,c){if(a.length!==b.length)throw"Can't interpolate between \""+a[0]+'" and "'+b[0]+'"';var d=[a[0]];for(var e=1;e<a.length;e++)d[e]=a[e]+(b[e]-a[e])*c;return d},I=function(a){var b=1;return a[0].replace(/\?/g,function(){return a[b++]})},J=function(a,b,c){var d=a.style;b=b.replace(q,function(a,b){return b.toUpperCase()}).replace("-","");if(b==="zIndex")d[b]=""+(c|0);else try{d[v+b.slice(0,1).toUpperCase()+b.slice(1)]=c,d[b]=c}catch(e){}if(Q.setStyle)for(var f=0;f<plugins.setStyle.length;f++)Q.setStyle[0].call(this,a,b,c)},K=function(a,b){N(a.className).indexOf(N(b))===-1&&(a.className=M(a.className+" "+b))},L=function(a,b){a.className=M(N(a.className).replace(N(b)," "))},M=function(a){return a.replace(m,"$1")},N=function(a){return" "+a+" "},O=function(){return+(new Date)},P,Q={},R,S,T,U,V,W,X;a.skrollr={init:function(a){return P||new A(a)},plugin:function(a,b){Q[a]?Q[a].push(b):Q[a]=[b]},VERSION:"0.3.9"}})(window,document);
View
62 skrollr.js
@@ -1,4 +1,4 @@
-/*! skrollr v0.3.8 https://github.com/Prinzhorn/skrollr | free to use under terms of MIT license */
+/*! skrollr v0.3.9 https://github.com/Prinzhorn/skrollr | free to use under terms of MIT license */
(function(window, document, undefined) {
"use strict";
@@ -13,7 +13,7 @@
var HIDDEN_CLASS = 'hidden';
var SKROLLABLE_CLASS = 'skrollable';
var DEFAULT_EASING = 'linear';
- var DEFAULT_DURATION = 500;
+ var DEFAULT_DURATION = 1000;
var requestAnimFrame =
window.requestAnimationFrame ||
@@ -290,6 +290,33 @@
return _instance;
}
+ /**
+ * Animates scroll top to new position.
+ */
+ Skrollr.prototype.animateTo = function(top, options) {
+ options = options || {};
+
+ var now = _now();
+
+ //Setting this to a new value will automatically prevent the current animation to stop, if any.
+ _scrollAnimation = {
+ startTop: _instance.getScrollTop(),
+ topDiff: top - _instance.getScrollTop(),
+ targetTop: top,
+ duration: options.duration || DEFAULT_DURATION,
+ startTime: now,
+ endTime: now + (options.duration || DEFAULT_DURATION),
+ easing: easings[options.easing || DEFAULT_EASING],
+ done: options.done || NOOP
+ };
+
+ //Don't queue the animation if there's nothing to animate.
+ if(!_scrollAnimation.topDiff) {
+ _scrollAnimation.done.call(_instance);
+ _scrollAnimation = undefined;
+ }
+ };
+
Skrollr.prototype.setScrollTop = function(top) {
window.scroll(0, top);
};
@@ -371,6 +398,26 @@
* Renders all elements
*/
var _render = function() {
+ //If there's an animation, which ends in current render call, call the callback after rendering;
+ var afterAnimationCallback = NOOP;
+
+ //Before actually rendering handle the scroll animation, if any.
+ if(_scrollAnimation) {
+ var now = _now();
+
+ //It's over
+ if(now >= _scrollAnimation.endTime) {
+ _instance.setScrollTop(_scrollAnimation.targetTop);
+ afterAnimationCallback = _scrollAnimation.done;
+ _scrollAnimation = undefined;
+ } else {
+ //Map the current progress to the new progress using given easing function.
+ var progress = _scrollAnimation.easing((now - _scrollAnimation.startTime) / _scrollAnimation.duration);
+
+ _instance.setScrollTop((_scrollAnimation.startTop + progress * _scrollAnimation.topDiff) | 0);
+ }
+ }
+
_curTop = _instance.getScrollTop();
//In OSX it's possible to have a negative scrolltop, so, we set it to zero.
@@ -404,6 +451,8 @@
_listeners.render.call(_instance, listenerParams);
}
+
+ afterAnimationCallback.call(_instance);
}
requestAnimFrame(function() {
@@ -636,6 +685,10 @@
return ' ' + a + ' ';
};
+ var _now = function() {
+ return +new Date();
+ };
+
/*
* Private variables.
*/
@@ -652,6 +705,9 @@
var _lastTop;
var _curTop;
+ //Will contain data about a running scrollbar animation, if any.
+ var _scrollAnimation;
+
/*
* Global api.
*/
@@ -669,6 +725,6 @@
_plugins[entryPoint] = [fn];
}
},
- VERSION: '0.3.8'
+ VERSION: '0.3.9'
};
}(window, document));

0 comments on commit f6a1c10

Please sign in to comment.
Something went wrong with that request. Please try again.