Skip to content

Commit

Permalink
Implement #925.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidjerleke committed Jun 30, 2024
1 parent 49ce3ce commit 3f06739
Show file tree
Hide file tree
Showing 14 changed files with 39 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,7 @@ export const setupInfiniteScroll = (emblaApi, loadMoreCallback) => {

emblaApi.reInit()
const newEngine = emblaApi.internalEngine()
const copyEngineModules = [
'scrollBody',
'location',
'offsetLocation',
'target'
]
const copyEngineModules = ['scrollBody', 'location', 'target']
copyEngineModules.forEach((engineModule) =>
Object.assign(newEngine[engineModule], oldEngine[engineModule])
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export const setupInfiniteScroll = (
const copyEngineModules: (keyof EngineType)[] = [
'scrollBody',
'location',
'offsetLocation',
'target'
]
copyEngineModules.forEach((engineModule) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export const setupInfiniteScroll = (
const copyEngineModules: (keyof EngineType)[] = [
'scrollBody',
'location',
'offsetLocation',
'target'
]
copyEngineModules.forEach((engineModule) =>
Expand Down
1 change: 0 additions & 1 deletion packages/embla-carousel/src/__tests__/loop-ltr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export const scrollToLocationInstant = (
engine.target.set(location)
engine.scrollBody.useDuration(0)
engine.animation.update()
engine.animation.render(1)
}

describe('➡️ Loop - Horizontal LTR', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const setLocationOutOfBounds = (
engine: EngineType,
outOfBoundsLocation: number
): void => {
engine.offsetLocation.set(outOfBoundsLocation)
engine.location.set(outOfBoundsLocation)
engine.target.set(outOfBoundsLocation)
}
Expand All @@ -22,7 +21,7 @@ describe('➡️ ScrollBounds - Horizontal LTR', () => {
emblaApi.on('settle', settleCallback)

setLocationOutOfBounds(engine, engine.limit.max + 1)
engine.animation.render(1)
engine.animation.update()

expect(settleCallback).toHaveBeenCalledTimes(0)
})
Expand All @@ -47,7 +46,7 @@ describe('➡️ ScrollBounds - Horizontal LTR', () => {
emblaApi.on('settle', settleCallback)

setLocationOutOfBounds(engine, engine.limit.min - 1)
engine.animation.render(1)
engine.animation.update()

expect(settleCallback).toHaveBeenCalledTimes(0)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const setLocationOutOfBounds = (
engine: EngineType,
outOfBoundsLocation: number
): void => {
engine.offsetLocation.set(outOfBoundsLocation)
engine.location.set(outOfBoundsLocation)
engine.target.set(outOfBoundsLocation)
}
Expand All @@ -24,7 +23,7 @@ describe('➡️ ScrollBounds - Horizontal RTL', () => {
emblaApi.on('settle', settleCallback)

setLocationOutOfBounds(engine, engine.limit.max + 1)
engine.animation.render(1)
engine.animation.update()

expect(settleCallback).toHaveBeenCalledTimes(0)
})
Expand Down Expand Up @@ -53,7 +52,7 @@ describe('➡️ ScrollBounds - Horizontal RTL', () => {
emblaApi.on('settle', settleCallback)

setLocationOutOfBounds(engine, engine.limit.min - 1)
engine.animation.render(1)
engine.animation.update()

expect(settleCallback).toHaveBeenCalledTimes(0)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const setLocationOutOfBounds = (
engine: EngineType,
outOfBoundsLocation: number
): void => {
engine.offsetLocation.set(outOfBoundsLocation)
engine.location.set(outOfBoundsLocation)
engine.target.set(outOfBoundsLocation)
}
Expand All @@ -24,7 +23,7 @@ describe('➡️ ScrollBounds - Vertical', () => {
emblaApi.on('settle', settleCallback)

setLocationOutOfBounds(engine, engine.limit.max + 1)
engine.animation.render(1)
engine.animation.update()

expect(settleCallback).toHaveBeenCalledTimes(0)
})
Expand Down Expand Up @@ -53,7 +52,7 @@ describe('➡️ ScrollBounds - Vertical', () => {
emblaApi.on('settle', settleCallback)

setLocationOutOfBounds(engine, engine.limit.min - 1)
engine.animation.render(1)
engine.animation.update()

expect(settleCallback).toHaveBeenCalledTimes(0)
})
Expand Down
22 changes: 6 additions & 16 deletions packages/embla-carousel/src/components/Animations.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
import { EngineType } from './Engine'
import { EventStore } from './EventStore'
import { mathAbs, WindowType } from './utils'
import { WindowType } from './utils'

export type AnimationsUpdateType = (engine: EngineType) => void
export type AnimationsRenderType = (
engine: EngineType,
lagOffset: number
) => void

export type AnimationsType = {
init: () => void
destroy: () => void
start: () => void
stop: () => void
update: () => void
render: (lagOffset: number) => void
}

export function Animations(
ownerDocument: Document,
ownerWindow: WindowType,
update: AnimationsType['update'],
render: AnimationsType['render']
update: AnimationsType['update']
): AnimationsType {
const documentVisibleHandler = EventStore()
const timeStep = 1000 / 60
let lastTimeStamp: number | null = null
let lag = 0
let animationFrame = 0
let lag = 0

function init(): void {
documentVisibleHandler.add(ownerDocument, 'visibilitychange', () => {
Expand All @@ -44,18 +38,15 @@ export function Animations(
if (!animationFrame) return
if (!lastTimeStamp) lastTimeStamp = timeStamp

const elapsed = timeStamp - lastTimeStamp
const timeElapsed = timeStamp - lastTimeStamp
lastTimeStamp = timeStamp
lag += elapsed
lag += timeElapsed

while (lag >= timeStep) {
update()
lag -= timeStep
}

const lagOffset = mathAbs(lag / timeStep)
render(lagOffset)

if (animationFrame) ownerWindow.requestAnimationFrame(animate)
}

Expand All @@ -82,8 +73,7 @@ export function Animations(
destroy,
start,
stop,
update,
render
update
}
return self
}
62 changes: 14 additions & 48 deletions packages/embla-carousel/src/components/Engine.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { Alignment } from './Alignment'
import {
Animations,
AnimationsType,
AnimationsUpdateType,
AnimationsRenderType
} from './Animations'
import { Animations, AnimationsType, AnimationsUpdateType } from './Animations'
import { Axis, AxisType } from './Axis'
import { Counter, CounterType } from './Counter'
import { DragHandler, DragHandlerType } from './DragHandler'
Expand Down Expand Up @@ -49,7 +44,6 @@ export type EngineType = {
indexPrevious: CounterType
limit: LimitType
location: Vector1DType
offsetLocation: Vector1DType
options: OptionsType
percentOfView: PercentOfViewType
scrollBody: ScrollBodyType
Expand Down Expand Up @@ -157,31 +151,19 @@ export function Engine(
// Animation
const update: AnimationsUpdateType = ({
dragHandler,
eventHandler,
scrollBody,
scrollBounds,
scrollLooper,
slideLooper,
translate,
location,
animation,
options: { loop }
}) => {
if (!loop) scrollBounds.constrain(dragHandler.pointerDown())
scrollBody.seek()
}

const render: AnimationsRenderType = (
{
scrollBody,
translate,
location,
offsetLocation,
scrollLooper,
slideLooper,
dragHandler,
animation,
eventHandler,
scrollBounds,
options: { loop }
},
lagOffset
) => {
const velocity = scrollBody.velocity()
const shouldSettle = scrollBody.settled()
const withinBounds = !scrollBounds.shouldConstrain()
const hasSettled = loop ? shouldSettle : shouldSettle && withinBounds
Expand All @@ -192,35 +174,22 @@ export function Engine(
}
if (!hasSettled) eventHandler.emit('scroll')

offsetLocation.set(location.get() - velocity + velocity * lagOffset)

if (loop) {
scrollLooper.loop(scrollBody.direction())
slideLooper.loop()
}

translate.to(offsetLocation.get())
translate.to(location.get())
}
const animation = Animations(
ownerDocument,
ownerWindow,
() => update(engine),
(lagOffset: number) => render(engine, lagOffset)
)

const animation = Animations(ownerDocument, ownerWindow, () => update(engine))

// Shared
const friction = 0.68
const startLocation = scrollSnaps[index.get()]
const location = Vector1D(startLocation)
const offsetLocation = Vector1D(startLocation)
const target = Vector1D(startLocation)
const scrollBody = ScrollBody(
location,
offsetLocation,
target,
duration,
friction
)
const scrollBody = ScrollBody(location, target, duration, friction)
const scrollTarget = ScrollTarget(
loop,
scrollSnaps,
Expand All @@ -232,7 +201,6 @@ export function Engine(
animation,
index,
indexPrevious,
scrollBody,
scrollTarget,
target,
eventHandler
Expand Down Expand Up @@ -299,7 +267,6 @@ export function Engine(
indexPrevious,
limit,
location,
offsetLocation,
options,
resizeHandler: ResizeHandler(
container,
Expand All @@ -313,14 +280,13 @@ export function Engine(
scrollBody,
scrollBounds: ScrollBounds(
limit,
offsetLocation,
location,
target,
scrollBody,
percentOfView
),
scrollLooper: ScrollLooper(contentSize, limit, offsetLocation, [
scrollLooper: ScrollLooper(contentSize, limit, location, [
location,
offsetLocation,
target
]),
scrollProgress,
Expand All @@ -336,7 +302,7 @@ export function Engine(
slideSizesWithGaps,
snaps,
scrollSnaps,
offsetLocation,
location,
slides
),
slideFocus,
Expand Down
3 changes: 1 addition & 2 deletions packages/embla-carousel/src/components/ScrollBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export type ScrollBodyType = {

export function ScrollBody(
location: Vector1DType,
offsetLocation: Vector1DType,
target: Vector1DType,
baseDuration: number,
baseFriction: number
Expand Down Expand Up @@ -52,7 +51,7 @@ export function ScrollBody(
}

function settled(): boolean {
const diff = target.get() - offsetLocation.get()
const diff = target.get() - location.get()
return mathAbs(diff) < 0.001
}

Expand Down
10 changes: 5 additions & 5 deletions packages/embla-carousel/src/components/ScrollBounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type ScrollBoundsType = {

export function ScrollBounds(
limit: LimitType,
offsetLocation: Vector1DType,
location: Vector1DType,
target: Vector1DType,
scrollBody: ScrollBodyType,
percentOfView: PercentOfViewType
Expand All @@ -25,15 +25,15 @@ export function ScrollBounds(
function shouldConstrain(): boolean {
if (disabled) return false
if (!limit.reachedAny(target.get())) return false
if (!limit.reachedAny(offsetLocation.get())) return false
if (!limit.reachedAny(location.get())) return false
return true
}

function constrain(pointerDown: boolean): void {
if (!shouldConstrain()) return
const edge = limit.reachedMin(offsetLocation.get()) ? 'min' : 'max'
const diffToEdge = mathAbs(limit[edge] - offsetLocation.get())
const diffToTarget = target.get() - offsetLocation.get()
const edge = limit.reachedMin(location.get()) ? 'min' : 'max'
const diffToEdge = mathAbs(limit[edge] - location.get())
const diffToTarget = target.get() - location.get()
const friction = frictionLimit.constrain(diffToEdge / edgeOffsetTolerance)

target.subtract(diffToTarget * friction)
Expand Down
6 changes: 3 additions & 3 deletions packages/embla-carousel/src/components/ScrollLooper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type ScrollLooperType = {
export function ScrollLooper(
contentSize: number,
limit: LimitType,
offsetLocation: Vector1DType,
location: Vector1DType,
vectors: Vector1DType[]
): ScrollLooperType {
const jointSafety = 0.1
Expand All @@ -17,8 +17,8 @@ export function ScrollLooper(
const { reachedMin, reachedMax } = Limit(min, max)

function shouldLoop(direction: number): boolean {
if (direction === 1) return reachedMax(offsetLocation.get())
if (direction === -1) return reachedMin(offsetLocation.get())
if (direction === 1) return reachedMax(location.get())
if (direction === -1) return reachedMin(location.get())
return false
}

Expand Down
Loading

0 comments on commit 3f06739

Please sign in to comment.