diff options
author | Ruslan Kiianchuk | 2014-08-31 01:20:21 -0700 |
---|---|---|
committer | Ruslan Kiianchuk | 2014-08-31 01:20:21 -0700 |
commit | c2ede41a905425bfc0348b248dbb370f40e0937f (patch) | |
tree | 65bac203b0b366fa7badf285aa006791becaa057 /_smooziee.js | |
parent | 3765fe33575088dad4d4f9a51e907f695546e5b3 (diff) | |
download | vimperator-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.js | 120 |
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: |