diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2019-09-15 17:52:30 -0400 | 
|---|---|---|
| committer | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2019-09-27 21:41:00 -0400 | 
| commit | 946e577e42db9df43169d8547d4536fe8edd6748 (patch) | |
| tree | 3ca1d83d1d5bedcd113d71235f507411a49239c2 | |
| parent | 9fc69395c5a3c66a9289c73d412f8b92d9bc4b31 (diff) | |
Implement custom window scroll
| -rw-r--r-- | ext/bg/search.html | 1 | ||||
| -rw-r--r-- | ext/fg/float.html | 1 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 14 | ||||
| -rw-r--r-- | ext/mixed/js/scroll.js | 100 | 
4 files changed, 111 insertions, 5 deletions
| diff --git a/ext/bg/search.html b/ext/bg/search.html index 3c78122d..ab208c26 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -47,6 +47,7 @@          <script src="/fg/js/source.js"></script>          <script src="/mixed/js/display.js"></script>          <script src="/mixed/js/japanese.js"></script> +        <script src="/mixed/js/scroll.js"></script>          <script src="/bg/js/search.js"></script>          <script src="/bg/js/search-frontend.js"></script> diff --git a/ext/fg/float.html b/ext/fg/float.html index 465db589..e86c2caa 100644 --- a/ext/fg/float.html +++ b/ext/fg/float.html @@ -41,6 +41,7 @@          <script src="/fg/js/document.js"></script>          <script src="/fg/js/source.js"></script>          <script src="/mixed/js/display.js"></script> +        <script src="/mixed/js/scroll.js"></script>          <script src="/fg/js/float.js"></script> diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index a3d618e5..e3c44507 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -31,6 +31,8 @@ class Display {          this.dependencies = {}; +        this.windowScroll = new WindowScroll(); +          document.addEventListener('keydown', this.onKeyDown.bind(this));          document.addEventListener('wheel', this.onWheel.bind(this), {passive: false});      } @@ -53,11 +55,12 @@ class Display {              e.preventDefault();              const link = e.target; +            this.windowScroll.toY(0);              const context = {                  source: {                      definitions: this.definitions,                      index: this.entryIndexFind(link), -                    scroll: $('html,body').scrollTop() +                    scroll: this.windowScroll.y                  }              }; @@ -102,11 +105,12 @@ class Display {                  textSource.cleanup();              } +            this.windowScroll.toY(0);              const context = {                  source: {                      definitions: this.definitions,                      index: this.entryIndexFind(clickedElement), -                    scroll: $('html,body').scrollTop() +                    scroll: this.windowScroll.y                  }              }; @@ -410,7 +414,7 @@ class Display {          $('.current').hide().eq(index).show(); -        const container = $('html,body').stop(); +        this.windowScroll.stop();          const entry = $('.entry').eq(index);          let target; @@ -421,9 +425,9 @@ class Display {          }          if (smooth) { -            container.animate({scrollTop: target}, 200); +            this.windowScroll.animate(this.windowScroll.x, target, 200);          } else { -            container.scrollTop(target); +            this.windowScroll.toY(target);          }          this.index = index; diff --git a/ext/mixed/js/scroll.js b/ext/mixed/js/scroll.js new file mode 100644 index 00000000..824fd92b --- /dev/null +++ b/ext/mixed/js/scroll.js @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2019  Alex Yatskov <alex@foosoft.net> + * Author: Alex Yatskov <alex@foosoft.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + + +class WindowScroll { +    constructor() { +        this.animationRequestId = null; +        this.animationStartTime = 0; +        this.animationStartX = 0; +        this.animationStartY = 0; +        this.animationEndTime = 0; +        this.animationEndX = 0; +        this.animationEndY = 0; +        this.requestAnimationFrameCallback = (t) => this.onAnimationFrame(t); +    } + +    toY(y) { +        this.to(this.x, y); +    } + +    toX(x) { +        this.to(x, this.y); +    } + +    to(x, y) { +        this.stop(); +        window.scroll(x, y); +    } + +    animate(x, y, time) { +        this.animationStartX = this.x; +        this.animationStartY = this.y; +        this.animationStartTime = window.performance.now(); +        this.animationEndX = x; +        this.animationEndY = y; +        this.animationEndTime = this.animationStartTime + time; +        this.animationRequestId = window.requestAnimationFrame(this.requestAnimationFrameCallback); +    } + +    stop() { +        if (this.animationRequestId === null) { +            return; +        } + +        window.cancelAnimationFrame(this.animationRequestId); +        this.animationRequestId = null; +    } + +    onAnimationFrame(time) { +        if (time >= this.animationEndTime) { +            window.scroll(this.animationEndX, this.animationEndY); +            this.animationRequestId = null; +            return; +        } + +        const t = WindowScroll.easeInOutCubic((time - this.animationStartTime) / (this.animationEndTime - this.animationStartTime)); +        window.scroll( +            WindowScroll.lerp(this.animationStartX, this.animationEndX, t), +            WindowScroll.lerp(this.animationStartY, this.animationEndY, t) +        ); + +        this.animationRequestId = window.requestAnimationFrame(this.requestAnimationFrameCallback); +    } + +    get x() { +        return window.scrollX || window.pageXOffset; +    } + +    get y() { +        return window.scrollY || window.pageYOffset; +    } + +    static easeInOutCubic(t) { +        if (t < 0.5) { +            return (4.0 * t * t * t); +        } else { +            t = 1.0 - t; +            return 1.0 - (4.0 * t * t * t); +        } +    } + +    static lerp(start, end, percent) { +        return (end - start) * percent + start; +    } +} |