From eb11b5feaad76965b13dc2ba5c8b6471b2210ef0 Mon Sep 17 00:00:00 2001 From: Mikhail Efimov Date: Fri, 16 Oct 2020 16:56:33 +0300 Subject: [PATCH 1/4] feat: add dynamicPosition parameter (for dynamic container height) --- README.md | 8 ++++++++ src/scrollTo.js | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0f4e14d4..720d8031 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ In case you are using the browser version (directly including the script on your VueScrollTo.setDefaults({ container: "body", duration: 500, + dynamicPosition: true, easing: "ease", offset: 0, force: true, @@ -125,6 +126,7 @@ If you need to customize the scrolling options, you can pass in an object litera el: '#element', container: '#container', duration: 500, + dynamicPosition: true easing: 'linear', offset: -200, force: true, @@ -151,6 +153,7 @@ var VueScrollTo = require('vue-scrollto'); var options = { container: '#container', easing: 'ease-in', + dynamicPosition: true, offset: -60, force: true, cancelable: true, @@ -191,6 +194,11 @@ The duration (in milliseconds) of the scrolling animation. *Default:* `500` +#### dynamicPosition +Recalculating targetY/targetX at each scroll step. Useful when you don't know the final height of the container, and it grows as it scrolls. + +*Default:* `false` + #### easing The easing to be used when animating. Read more in the [Easing section](#easing-detailed). diff --git a/src/scrollTo.js b/src/scrollTo.js index 050eef7d..d77f219d 100644 --- a/src/scrollTo.js +++ b/src/scrollTo.js @@ -14,6 +14,7 @@ const abortEvents = [ let defaults = { container: 'body', duration: 500, + dynamicPosition: false, easing: 'ease', offset: 0, force: true, @@ -33,6 +34,7 @@ export const scroller = () => { let element // element to scroll to let container // container to scroll let duration // duration of the scrolling + let dynamicPosition //checks the target position at each step let easing // easing to be used when scrolling let offset // offset to be added (subtracted) let force // force scroll, even if element is visible @@ -52,6 +54,9 @@ export const scroller = () => { let abort // is scrolling aborted + let cumulativeOffsetContainer + let cumulativeOffsetElement + let abortEv // event that aborted scrolling let abortFn = e => { if (!cancelable) return @@ -95,6 +100,24 @@ export const scroller = () => { if (abort) return done() if (!timeStart) timeStart = timestamp + // When a site has a lot of media that can be loaded asynchronously, + // the targetY/targetX may end up in the wrong place during scrolling. + // So we will check this at each step + if (dynamicPosition) { + cumulativeOffsetContainer = _.cumulativeOffset(container) + cumulativeOffsetElement = _.cumulativeOffset(element) + if (x) { + targetX = + cumulativeOffsetElement.left - cumulativeOffsetContainer.left + offset + diffX = targetX - initialX + } + if (y) { + targetY = + cumulativeOffsetElement.top - cumulativeOffsetContainer.top + offset + diffY = targetY - initialY + } + } + timeElapsed = timestamp - timeStart progress = Math.min(timeElapsed / duration, 1) @@ -143,7 +166,12 @@ export const scroller = () => { } container = _.$(options.container || defaults.container) - duration = options.hasOwnProperty('duration') ? options.duration : defaults.duration + duration = options.hasOwnProperty('duration') + ? options.duration + : defaults.duration + dynamicPosition = options.hasOwnProperty('dynamicPosition') + ? options.dynamicPosition + : defaults.dynamicPosition easing = options.easing || defaults.easing offset = options.hasOwnProperty('offset') ? options.offset : defaults.offset force = options.hasOwnProperty('force') @@ -158,8 +186,8 @@ export const scroller = () => { x = options.x === undefined ? defaults.x : options.x y = options.y === undefined ? defaults.y : options.y - let cumulativeOffsetContainer = _.cumulativeOffset(container) - let cumulativeOffsetElement = _.cumulativeOffset(element) + cumulativeOffsetContainer = _.cumulativeOffset(container) + cumulativeOffsetElement = _.cumulativeOffset(element) if (typeof offset === 'function') { offset = offset(element, container) From 2bb2cbb1a6b025848f1766e687f7c18c4398909b Mon Sep 17 00:00:00 2001 From: Mikhail Efimov Date: Tue, 27 Oct 2020 19:06:45 +0300 Subject: [PATCH 2/4] fix: rename option and small refactoring --- README.md | 16 ++++++++-------- src/scrollTo.js | 49 +++++++++++++++++++++++-------------------------- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 720d8031..949e2780 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ In case you are using the browser version (directly including the script on your VueScrollTo.setDefaults({ container: "body", duration: 500, - dynamicPosition: true, + lazy: false, easing: "ease", offset: 0, force: true, @@ -126,7 +126,7 @@ If you need to customize the scrolling options, you can pass in an object litera el: '#element', container: '#container', duration: 500, - dynamicPosition: true + lazy: false easing: 'linear', offset: -200, force: true, @@ -153,7 +153,7 @@ var VueScrollTo = require('vue-scrollto'); var options = { container: '#container', easing: 'ease-in', - dynamicPosition: true, + lazy: false, offset: -60, force: true, cancelable: true, @@ -194,16 +194,16 @@ The duration (in milliseconds) of the scrolling animation. *Default:* `500` -#### dynamicPosition -Recalculating targetY/targetX at each scroll step. Useful when you don't know the final height of the container, and it grows as it scrolls. - -*Default:* `false` - #### easing The easing to be used when animating. Read more in the [Easing section](#easing-detailed). *Default:* `ease` +#### lazy +Recalculating targetY/targetX at each scroll step. Useful when you don't know the final height of the container, and it grows as it scrolls. + +*Default:* `true` + #### offset The offset that should be applied when scrolling. This option accepts a callback function since `v2.8.0`. diff --git a/src/scrollTo.js b/src/scrollTo.js index d77f219d..f6e86120 100644 --- a/src/scrollTo.js +++ b/src/scrollTo.js @@ -14,7 +14,7 @@ const abortEvents = [ let defaults = { container: 'body', duration: 500, - dynamicPosition: false, + lazy: true, easing: 'ease', offset: 0, force: true, @@ -34,8 +34,8 @@ export const scroller = () => { let element // element to scroll to let container // container to scroll let duration // duration of the scrolling - let dynamicPosition //checks the target position at each step let easing // easing to be used when scrolling + let lazy //checks the target position at each step let offset // offset to be added (subtracted) let force // force scroll, even if element is visible let cancelable // indicates if user can cancel the scroll or not. @@ -96,6 +96,22 @@ export const scroller = () => { return scrollLeft } + function recalculateTargets() { + cumulativeOffsetContainer = _.cumulativeOffset(container) + cumulativeOffsetElement = _.cumulativeOffset(element) + + if (x) { + targetX = + cumulativeOffsetElement.left - cumulativeOffsetContainer.left + offset + diffX = targetX - initialX + } + if (y) { + targetY = + cumulativeOffsetElement.top - cumulativeOffsetContainer.top + offset + diffY = targetY - initialY + } + } + function step(timestamp) { if (abort) return done() if (!timeStart) timeStart = timestamp @@ -103,19 +119,8 @@ export const scroller = () => { // When a site has a lot of media that can be loaded asynchronously, // the targetY/targetX may end up in the wrong place during scrolling. // So we will check this at each step - if (dynamicPosition) { - cumulativeOffsetContainer = _.cumulativeOffset(container) - cumulativeOffsetElement = _.cumulativeOffset(element) - if (x) { - targetX = - cumulativeOffsetElement.left - cumulativeOffsetContainer.left + offset - diffX = targetX - initialX - } - if (y) { - targetY = - cumulativeOffsetElement.top - cumulativeOffsetContainer.top + offset - diffY = targetY - initialY - } + if (!lazy) { + recalculateTargets() } timeElapsed = timestamp - timeStart @@ -169,9 +174,7 @@ export const scroller = () => { duration = options.hasOwnProperty('duration') ? options.duration : defaults.duration - dynamicPosition = options.hasOwnProperty('dynamicPosition') - ? options.dynamicPosition - : defaults.dynamicPosition + lazy = options.hasOwnProperty('lazy') ? options.lazy : defaults.lazy easing = options.easing || defaults.easing offset = options.hasOwnProperty('offset') ? options.offset : defaults.offset force = options.hasOwnProperty('force') @@ -186,20 +189,14 @@ export const scroller = () => { x = options.x === undefined ? defaults.x : options.x y = options.y === undefined ? defaults.y : options.y - cumulativeOffsetContainer = _.cumulativeOffset(container) - cumulativeOffsetElement = _.cumulativeOffset(element) - if (typeof offset === 'function') { offset = offset(element, container) } initialY = scrollTop(container) - targetY = - cumulativeOffsetElement.top - cumulativeOffsetContainer.top + offset - initialX = scrollLeft(container) - targetX = - cumulativeOffsetElement.left - cumulativeOffsetContainer.left + offset + + recalculateTargets() abort = false From eaecf9227049acf2acf9993598c0bdb27d608a64 Mon Sep 17 00:00:00 2001 From: Igor Randjelovic Date: Wed, 28 Oct 2020 15:40:02 +0100 Subject: [PATCH 3/4] chore: apply suggestions from code review --- README.md | 2 +- src/scrollTo.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 949e2780..e19c84cb 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,7 @@ The easing to be used when animating. Read more in the [Easing section](#easing- *Default:* `ease` #### lazy -Recalculating targetY/targetX at each scroll step. Useful when you don't know the final height of the container, and it grows as it scrolls. +By default targetX/targetY are calculated once at the start of a scroll, however if the target may shift around during the scroll - setting `lazy` to `false` will force recalculation of targetX/targetY at each scroll step. *Default:* `true` diff --git a/src/scrollTo.js b/src/scrollTo.js index f6e86120..e23f4950 100644 --- a/src/scrollTo.js +++ b/src/scrollTo.js @@ -35,7 +35,7 @@ export const scroller = () => { let container // container to scroll let duration // duration of the scrolling let easing // easing to be used when scrolling - let lazy //checks the target position at each step + let lazy // checks the target position at each step let offset // offset to be added (subtracted) let force // force scroll, even if element is visible let cancelable // indicates if user can cancel the scroll or not. From 70254d21c54cf315dcf7a497249a9d5f12645a95 Mon Sep 17 00:00:00 2001 From: Igor Randjelovic Date: Wed, 28 Oct 2020 15:48:42 +0100 Subject: [PATCH 4/4] perf: remove redundant calculation --- src/scrollTo.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/scrollTo.js b/src/scrollTo.js index e23f4950..fe4950c1 100644 --- a/src/scrollTo.js +++ b/src/scrollTo.js @@ -193,16 +193,14 @@ export const scroller = () => { offset = offset(element, container) } - initialY = scrollTop(container) initialX = scrollLeft(container) + initialY = scrollTop(container) + // calculates cumulative offsets and targetX/Y + diffX/Y recalculateTargets() abort = false - diffY = targetY - initialY - diffX = targetX - initialX - if (!force) { // When the container is the default (body) we need to use the viewport // height, not the entire body height