Skip to content

Commit

Permalink
Merge pull request #1057 from davidjerleke/feature/#1056
Browse files Browse the repository at this point in the history
[Feat]: Give animation variables more descriptive names and round rendered position
  • Loading branch information
davidjerleke authored Nov 9, 2024
2 parents e714441 + 9ce1023 commit cbf0e66
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 69 deletions.
10 changes: 5 additions & 5 deletions packages/embla-carousel/src/__tests__/loop-ltr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe('➡️ Loop - Horizontal LTR', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(0.09000000000000001px,0px,0px)'
'translate3d(0.09px,0px,0px)'
)
})
})
Expand Down Expand Up @@ -274,7 +274,7 @@ describe('➡️ Loop - Horizontal LTR', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(-1209.8899999999999px,0px,0px)'
'translate3d(-1209.89px,0px,0px)'
)
})

Expand All @@ -285,7 +285,7 @@ describe('➡️ Loop - Horizontal LTR', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(450.09000000000003px,0px,0px)'
'translate3d(450.09px,0px,0px)'
)
})
})
Expand Down Expand Up @@ -940,7 +940,7 @@ describe('➡️ Loop - Horizontal LTR', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(-1419.8899999999999px,0px,0px)'
'translate3d(-1419.89px,0px,0px)'
)
})

Expand All @@ -951,7 +951,7 @@ describe('➡️ Loop - Horizontal LTR', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(440.09000000000003px,0px,0px)'
'translate3d(440.09px,0px,0px)'
)
})
})
Expand Down
10 changes: 5 additions & 5 deletions packages/embla-carousel/src/__tests__/loop-rtl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('➡️ Loop - Horizontal RTL', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(-0.09000000000000001px,0px,0px)'
'translate3d(-0.09px,0px,0px)'
)
})
})
Expand Down Expand Up @@ -267,7 +267,7 @@ describe('➡️ Loop - Horizontal RTL', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(1209.8899999999999px,0px,0px)'
'translate3d(1209.89px,0px,0px)'
)
})

Expand All @@ -278,7 +278,7 @@ describe('➡️ Loop - Horizontal RTL', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(-450.09000000000003px,0px,0px)'
'translate3d(-450.09px,0px,0px)'
)
})
})
Expand Down Expand Up @@ -939,7 +939,7 @@ describe('➡️ Loop - Horizontal RTL', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(1419.8899999999999px,0px,0px)'
'translate3d(1419.89px,0px,0px)'
)
})

Expand All @@ -950,7 +950,7 @@ describe('➡️ Loop - Horizontal RTL', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(-440.09000000000003px,0px,0px)'
'translate3d(-440.09px,0px,0px)'
)
})
})
Expand Down
10 changes: 5 additions & 5 deletions packages/embla-carousel/src/__tests__/loop-vertical.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('➡️ Loop - Vertical', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(0px,0.09000000000000001px,0px)'
'translate3d(0px,0.09px,0px)'
)
})
})
Expand Down Expand Up @@ -267,7 +267,7 @@ describe('➡️ Loop - Vertical', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(0px,-1209.8899999999999px,0px)'
'translate3d(0px,-1209.89px,0px)'
)
})

Expand All @@ -278,7 +278,7 @@ describe('➡️ Loop - Vertical', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(0px,450.09000000000003px,0px)'
'translate3d(0px,450.09px,0px)'
)
})
})
Expand Down Expand Up @@ -939,7 +939,7 @@ describe('➡️ Loop - Vertical', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(0px,-1419.8899999999999px,0px)'
'translate3d(0px,-1419.89px,0px)'
)
})

Expand All @@ -950,7 +950,7 @@ describe('➡️ Loop - Vertical', () => {
)

expect(emblaApi.containerNode().style.transform).toBe(
'translate3d(0px,440.09000000000003px,0px)'
'translate3d(0px,440.09px,0px)'
)
})
})
Expand Down
69 changes: 41 additions & 28 deletions packages/embla-carousel/src/components/Animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import { EngineType } from './Engine'
import { EventStore } from './EventStore'
import { WindowType } from './utils'

export type AnimationsUpdateType = (
engine: EngineType,
timeStep: number
) => void
export type AnimationsUpdateType = (engine: EngineType) => void
export type AnimationsRenderType = (
engine: EngineType,
lagOffset: number
Expand All @@ -23,14 +20,14 @@ export type AnimationsType = {
export function Animations(
ownerDocument: Document,
ownerWindow: WindowType,
update: (timeStep: number) => void,
update: () => void,
render: (lagOffset: number) => void
): AnimationsType {
const documentVisibleHandler = EventStore()
const timeStep = 1000 / 60
const fixedTimeStep = 1000 / 60
let lastTimeStamp: number | null = null
let lag = 0
let animationFrame = 0
let accumulatedTime = 0
let animationId = 0

function init(): void {
documentVisibleHandler.add(ownerDocument, 'visibilitychange', () => {
Expand All @@ -43,49 +40,65 @@ export function Animations(
documentVisibleHandler.clear()
}

function animate(timeStamp: DOMHighResTimeStamp): void {
if (!animationFrame) return
if (!lastTimeStamp) lastTimeStamp = timeStamp
function shouldUpdate(): boolean {
return accumulatedTime >= fixedTimeStep
}

const elapsed = timeStamp - lastTimeStamp
lastTimeStamp = timeStamp
lag += elapsed
function updateAndRemoveAccumulatedTime(): void {
update()
accumulatedTime -= fixedTimeStep
if (shouldUpdate()) updateAndRemoveAccumulatedTime()
}

function renderWithAlpha(): void {
const alpha = accumulatedTime / fixedTimeStep
render(alpha)
}

function animate(timeStamp: DOMHighResTimeStamp): void {
if (!animationId) return

while (lag >= timeStep) {
update(timeStep)
lag -= timeStep
if (!lastTimeStamp) {
lastTimeStamp = timeStamp
update()
renderWithAlpha()
}

const lagOffset = lag / timeStep
render(lagOffset)
const timeElapsed = timeStamp - lastTimeStamp
lastTimeStamp = timeStamp
accumulatedTime += timeElapsed

if (animationFrame) ownerWindow.requestAnimationFrame(animate)
if (shouldUpdate()) updateAndRemoveAccumulatedTime()
renderWithAlpha()

if (animationId) {
animationId = ownerWindow.requestAnimationFrame(animate)
}
}

function start(): void {
if (animationFrame) return

animationFrame = ownerWindow.requestAnimationFrame(animate)
if (animationId) return
animationId = ownerWindow.requestAnimationFrame(animate)
}

function stop(): void {
ownerWindow.cancelAnimationFrame(animationFrame)
ownerWindow.cancelAnimationFrame(animationId)
lastTimeStamp = null
lag = 0
animationFrame = 0
accumulatedTime = 0
animationId = 0
}

function reset(): void {
lastTimeStamp = null
lag = 0
accumulatedTime = 0
}

const self: AnimationsType = {
init,
destroy,
start,
stop,
update: () => update(timeStep),
update,
render
}
return self
Expand Down
22 changes: 13 additions & 9 deletions packages/embla-carousel/src/components/Engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,14 @@ export function Engine(
const slideIndexes = arrayKeys(slides)

// Animation
const update: AnimationsUpdateType = (
{ dragHandler, scrollBody, scrollBounds, options: { loop } },
timeStep
) => {
const update: AnimationsUpdateType = ({
dragHandler,
scrollBody,
scrollBounds,
options: { loop }
}) => {
if (!loop) scrollBounds.constrain(dragHandler.pointerDown())
scrollBody.seek(timeStep)
scrollBody.seek()
}

const render: AnimationsRenderType = (
Expand All @@ -171,6 +173,7 @@ export function Engine(
translate,
location,
offsetLocation,
previousLocation,
scrollLooper,
slideLooper,
dragHandler,
Expand All @@ -179,7 +182,7 @@ export function Engine(
scrollBounds,
options: { loop }
},
lagOffset
alpha
) => {
const shouldSettle = scrollBody.settled()
const withinBounds = !scrollBounds.shouldConstrain()
Expand All @@ -192,7 +195,7 @@ export function Engine(
if (!hasSettled) eventHandler.emit('scroll')

const interpolatedLocation =
location.get() * lagOffset + previousLocation.get() * (1 - lagOffset)
location.get() * alpha + previousLocation.get() * (1 - alpha)

offsetLocation.set(interpolatedLocation)

Expand All @@ -203,11 +206,12 @@ export function Engine(

translate.to(offsetLocation.get())
}

const animation = Animations(
ownerDocument,
ownerWindow,
(timeStep) => update(engine, timeStep),
(lagOffset: number) => render(engine, lagOffset)
() => update(engine),
(alpha: number) => render(engine, alpha)
)

// Shared
Expand Down
30 changes: 14 additions & 16 deletions packages/embla-carousel/src/components/ScrollBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type ScrollBodyType = {
direction: () => number
duration: () => number
velocity: () => number
seek: (timeStep: number) => ScrollBodyType
seek: () => ScrollBodyType
settled: () => boolean
useBaseFriction: () => ScrollBodyType
useBaseDuration: () => ScrollBodyType
Expand All @@ -21,38 +21,36 @@ export function ScrollBody(
baseDuration: number,
baseFriction: number
): ScrollBodyType {
let bodyVelocity = 0
let scrollVelocity = 0
let scrollDirection = 0
let scrollDuration = baseDuration
let scrollFriction = baseFriction
let rawLocation = location.get()
let rawLocationPrevious = 0

function seek(timeStep: number): ScrollBodyType {
const fixedDeltaTimeSeconds = timeStep / 1000
const duration = scrollDuration * fixedDeltaTimeSeconds
const diff = target.get() - location.get()
function seek(): ScrollBodyType {
const displacement = target.get() - location.get()
const isInstant = !scrollDuration
let directionDiff = 0
let scrollDistance = 0

if (isInstant) {
bodyVelocity = 0
scrollVelocity = 0
previousLocation.set(target)
location.set(target)

directionDiff = diff
scrollDistance = displacement
} else {
previousLocation.set(location)

bodyVelocity += diff / duration
bodyVelocity *= scrollFriction
rawLocation += bodyVelocity
location.add(bodyVelocity * fixedDeltaTimeSeconds)
scrollVelocity += displacement / scrollDuration
scrollVelocity *= scrollFriction
rawLocation += scrollVelocity
location.add(scrollVelocity)

directionDiff = rawLocation - rawLocationPrevious
scrollDistance = rawLocation - rawLocationPrevious
}

scrollDirection = mathSign(directionDiff)
scrollDirection = mathSign(scrollDistance)
rawLocationPrevious = rawLocation
return self
}
Expand All @@ -71,7 +69,7 @@ export function ScrollBody(
}

function velocity(): number {
return bodyVelocity
return scrollVelocity
}

function useBaseDuration(): ScrollBodyType {
Expand Down
Loading

0 comments on commit cbf0e66

Please sign in to comment.