aboutsummaryrefslogtreecommitdiffstats
path: root/_smooziee.js
diff options
context:
space:
mode:
authorRuslan Kiianchuk2014-08-31 01:20:21 -0700
committerRuslan Kiianchuk2014-08-31 01:20:21 -0700
commitc2ede41a905425bfc0348b248dbb370f40e0937f (patch)
tree65bac203b0b366fa7badf285aa006791becaa057 /_smooziee.js
parent3765fe33575088dad4d4f9a51e907f695546e5b3 (diff)
downloadvimperator-plugins-c2ede41a905425bfc0348b248dbb370f40e0937f.tar.bz2
Use approximated Fibonacci sequence for scroll
Smooth scroll is never done by using linear functions (like `x/2` used in current implementation). It looks ugly — at the end scrolling is very flickering. Such processes are much better simulated by Fibonacci sequence. I've used optimized formulas (from Wikipedia, ofcourse :)
Diffstat (limited to '_smooziee.js')
-rw-r--r--_smooziee.js120
1 files changed, 66 insertions, 54 deletions
diff --git a/_smooziee.js b/_smooziee.js
index ae4915c..a545406 100644
--- a/_smooziee.js
+++ b/_smooziee.js
@@ -80,68 +80,80 @@ var INFO = xml`
let self = liberator.plugins.smooziee = (function(){
- // Mappings {{{
- mappings.addUserMap(
- [modes.NORMAL],
- ["j"],
- "Smooth scroll down",
- function(count){
- self.smoothScrollBy(getScrollAmount() * (count || 1));
- },
- {
- count: true
- }
- );
- mappings.addUserMap(
- [modes.NORMAL],
- ["k"],
- "Smooth scroll up",
- function(count){
- self.smoothScrollBy(getScrollAmount() * -(count || 1));
- },
- {
- count: true
+ mappings.addUserMap(
+ [modes.NORMAL],
+ ["j"],
+ "Smooth scroll down",
+ function(count){
+ self.smoothScrollBy(getScrollAmount());
+ },
+ {
+ count: true
+ }
+ );
+ mappings.addUserMap(
+ [modes.NORMAL],
+ ["k"],
+ "Smooth scroll up",
+ function(count){
+ self.smoothScrollBy(getScrollAmount() * -1);
+ },
+ {
+ count: true
+ }
+ );
+
+ var next;
+ var win;
+ var interval;
+
+ var PUBLICS = {
+ smoothScrollBy: function(moment) {
+ win = Buffer.findScrollableWindow();
+ interval = window.eval(liberator.globalVariables.smooth_scroll_interval || '30');
+ clearTimeout(next);
+ smoothScroll(moment);
+ }
}
- );
- // }}}
- // PUBLIC {{{
- var PUBLICS = {
- smoothScrollBy: function(moment) {
- win = Buffer.findScrollableWindow();
- interval = window.eval(liberator.globalVariables.smooziee_scroll_interval || '20');
- destY = win.scrollY + moment;
- clearTimeout(next);
- smoothScroll(moment);
+
+ function logBase(x, y) {
+ // Logarithm of arbitrary base `x`
+ return Math.log(y) / Math.log(x);
}
- }
- // }}}
- // PRIVATE {{{
- var next;
- var destY;
- var win;
- var interval;
+ function getScrollAmount() {
+ // see recognition of Fibonacci Numbers (here approximation is used)
+ // http://en.wikipedia.org/wiki/Fibonacci_number#Recognizing_Fibonacci_numbers
+ phi = 1.618033;
+ sqrt5 = 2.236067;
+ fn = liberator.globalVariables.smooth_scroll_amount || '150'
+ n = Math.ceil(logBase(phi, (fn * sqrt5 + Math.sqrt(5 * Math.pow(fn, 2) + 4)) / 2))
+ return window.eval(n);
+ }
- function getScrollAmount() window.eval(liberator.globalVariables.smooziee_scroll_amount || '400');
+ function fib(n){
+ // see optimized Binet's formula for Fibonacci sequence
+ // http://en.wikipedia.org/wiki/Fibonacci_number#Closed_form_expression
+ phi = 1.618033;
+ sqrt5 = 2.236067;
+ return Math.floor((Math.pow(phi, n) / sqrt5) + 0.5)
+ }
- function smoothScroll(moment) {
- if (moment > 0)
- moment = Math.floor(moment / 2);
- else
- moment = Math.ceil(moment / 2);
+ function smoothScroll(moment) {
+ if (moment > 0) {
+ moment = moment - 1;
+ win.scrollBy(0, fib(Math.abs(moment)));
+ } else {
+ moment = moment + 1;
+ win.scrollBy(0, -fib(Math.abs(moment)));
+ }
- win.scrollBy(0, moment);
+ if (moment == 0)
+ return;
- if (Math.abs(moment) < 1) {
- setTimeout(makeScrollTo(win.scrollX, destY), interval);
- destY = null;
- return;
+ next = setTimeout(function() smoothScroll(moment), interval);
}
- next = setTimeout(function() smoothScroll(moment), interval);
- }
- function makeScrollTo(x, y) function() win.scrollTo(x, y);
- // }}}
- return PUBLICS;
+ return PUBLICS;
})();
// vim: sw=2 ts=2 et si fdm=marker: