Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add lazy option to allow recalculating targets #388

Merged
merged 4 commits into from
Oct 28, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ In case you are using the browser version (directly including the script on your
VueScrollTo.setDefaults({
container: "body",
duration: 500,
lazy: false,
easing: "ease",
offset: 0,
force: true,
Expand Down Expand Up @@ -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,
lazy: false
easing: 'linear',
offset: -200,
force: true,
Expand All @@ -151,6 +153,7 @@ var VueScrollTo = require('vue-scrollto');
var options = {
container: '#container',
easing: 'ease-in',
lazy: false,
offset: -60,
force: true,
cancelable: true,
Expand Down Expand Up @@ -196,6 +199,11 @@ 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.

*Default:* `true`

#### offset
The offset that should be applied when scrolling. This option accepts a callback function since `v2.8.0`.

Expand Down
43 changes: 34 additions & 9 deletions src/scrollTo.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const abortEvents = [
let defaults = {
container: 'body',
duration: 500,
lazy: true,
easing: 'ease',
offset: 0,
force: true,
Expand All @@ -34,6 +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 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.
Expand All @@ -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
Expand Down Expand Up @@ -91,10 +96,33 @@ 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

// 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 (!lazy) {
recalculateTargets()
}

timeElapsed = timestamp - timeStart

progress = Math.min(timeElapsed / duration, 1)
Expand Down Expand Up @@ -143,7 +171,10 @@ export const scroller = () => {
}

container = _.$(options.container || defaults.container)
duration = options.hasOwnProperty('duration') ? options.duration : defaults.duration
duration = options.hasOwnProperty('duration')
? options.duration
: defaults.duration
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')
Expand All @@ -158,20 +189,14 @@ 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)

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

Expand Down