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

Bugfix #514 #520

Merged
merged 1 commit into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 8 additions & 19 deletions packages/embla-carousel/src/__tests__/ScrollBody.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,20 @@ describe('ScrollBody', () => {
})
})

describe('Direction is', () => {
test('1 when it seeks a positive target', () => {
target.set(targetPositive)
scrollBody.seek()
expect(scrollBody.direction()).toBe(directionPositive)
})

test('1 when it instantly goes to a positive target', () => {
target.set(targetPositive)
scrollBody.useDuration(0)
scrollBody.seek()
describe('Direction is ', () => {
test('1 when given distance is positive', () => {
scrollBody.useDirection(targetPositive)
expect(scrollBody.direction()).toBe(directionPositive)
})

test('-1 when it seeks a negative target', () => {
target.set(targetNegative)
scrollBody.seek()
test('-1 when given distance is negative', () => {
scrollBody.useDirection(targetNegative)
expect(scrollBody.direction()).toBe(directionNegative)
})

test('-1 when it instantly goes to a negative target', () => {
target.set(targetNegative)
scrollBody.useDuration(0)
scrollBody.seek()
expect(scrollBody.direction()).toBe(directionNegative)
test('0 when given distance is zero', () => {
scrollBody.useDirection(0)
expect(scrollBody.direction()).toBe(0)
})
})

Expand Down
10 changes: 1 addition & 9 deletions packages/embla-carousel/src/components/Animations.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { EngineType } from './Engine'
import { mathAbs, WindowType } from './utils'
import { WindowType } from './utils'

export type AnimationUpdateType = (engine: EngineType) => void
export type AnimationRenderType = (
engine: EngineType,
lagFactor: number,
) => void

export type AnimationType = {
start: () => void
stop: () => void
update: () => void
render: (lagFactor: number) => void
}

export type AnimationsType = {
Expand Down Expand Up @@ -40,9 +35,6 @@ export function Animations(ownerWindow: WindowType): AnimationsType {
lag -= timeStep
}

const lagOffset = mathAbs(lag / timeStep)
engines.forEach(({ animation }) => animation.render(lagOffset))

if (animationFrame) ownerWindow.requestAnimationFrame(animate)
}

Expand Down
4 changes: 3 additions & 1 deletion packages/embla-carousel/src/components/DragHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,13 @@ export function DragHandler(
if (!preventScroll) return up(evt)
}
const diff = dragTracker.pointerMove(evt)
const directionDiff = direction.apply(diff)
if (diffScroll > dragThreshold) preventClick = true

scrollBody.useFriction(0.3).useDuration(1)
if (directionDiff) scrollBody.useDirection(directionDiff)
animation.start()
target.add(direction.apply(diff))
target.add(directionDiff)
evt.preventDefault()
}

Expand Down
22 changes: 7 additions & 15 deletions packages/embla-carousel/src/components/Engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import { arrayKeys, arrayLast, arrayLastIndex, WindowType } from './utils'
import { Vector1D, Vector1DType } from './Vector1d'
import {
AnimationType,
AnimationRenderType,
AnimationUpdateType,
AnimationsType,
} from './Animations'
Expand Down Expand Up @@ -147,9 +146,10 @@ export function Engine(
scrollBody,
scrollBounds,
scrollLooper,
slideLooper,
eventHandler,
animation,
slideLooper,
translate,
options: { loop },
}) => {
const pointerDown = dragHandler.pointerDown()
Expand All @@ -162,29 +162,20 @@ export function Engine(
animation.stop()
eventHandler.emit('settle')
}
if (!hasSettled) {
eventHandler.emit('scroll')
}
if (!hasSettled) eventHandler.emit('scroll')

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

const render: AnimationRenderType = (
{ scrollBody, translate, location },
lagOffset,
) => {
const velocity = scrollBody.velocity()
const offsetLocation = location.get() - velocity + velocity * lagOffset
translate.to(offsetLocation)
translate.to(location.get())
}

const animation: AnimationType = {
update: () => update(engine),
render: (lagOffset: number) => render(engine, lagOffset),
start: () => animations.start(engine),
stop: () => animations.stop(engine),
update: () => update(engine),
}

// Shared
Expand All @@ -205,6 +196,7 @@ export function Engine(
index,
indexPrevious,
scrollTarget,
scrollBody,
target,
eventHandler,
)
Expand Down
31 changes: 18 additions & 13 deletions packages/embla-carousel/src/components/ScrollBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { Vector1DType } from './Vector1d'

export type ScrollBodyType = {
direction: () => number
duration: () => number
seek: () => ScrollBodyType
settled: () => boolean
useBaseFriction: () => ScrollBodyType
useBaseDuration: () => ScrollBodyType
useFriction: (n: number) => ScrollBodyType
useDuration: (n: number) => ScrollBodyType
velocity: () => number
useDirection: (n: number) => ScrollBodyType
}

export function ScrollBody(
Expand All @@ -21,34 +22,32 @@ export function ScrollBody(
let hasSettled = true
let bodyVelocity = 0
let scrollDirection = 0
let duration = baseDuration
let friction = baseFriction
let scrollDuration = baseDuration
let scrollFriction = baseFriction

function seek(): ScrollBodyType {
const diff = target.get() - location.get()
const isInstant = !friction || !duration
const isInstant = !scrollDuration

if (isInstant) {
bodyVelocity = 0
location.set(target)
} else {
bodyVelocity += diff / duration
bodyVelocity *= friction
bodyVelocity += diff / scrollDuration
bodyVelocity *= scrollFriction
location.add(bodyVelocity)
}

scrollDirection = mathSign(bodyVelocity || diff)
hasSettled = mathAbs(diff) < 0.001
return self
}

function settled(): boolean {
if (hasSettled) location.set(target)
return hasSettled
}

function velocity(): number {
return bodyVelocity
function duration(): number {
return scrollDuration
}

function direction(): number {
Expand All @@ -64,24 +63,30 @@ export function ScrollBody(
}

function useDuration(n: number): ScrollBodyType {
duration = n
scrollDuration = n
return self
}

function useFriction(n: number): ScrollBodyType {
friction = n
scrollFriction = n
return self
}

function useDirection(n: number): ScrollBodyType {
scrollDirection = mathSign(n)
return self
}

const self: ScrollBodyType = {
direction,
duration,
seek,
settled,
useBaseFriction,
useBaseDuration,
useDirection,
useFriction,
useDuration,
velocity,
}
return self
}
11 changes: 7 additions & 4 deletions packages/embla-carousel/src/components/ScrollTo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AnimationType } from './Animations'
import { CounterType } from './Counter'
import { EventHandlerType } from './EventHandler'
import { ScrollBodyType } from './ScrollBody'
import { ScrollTargetType, TargetType } from './ScrollTarget'
import { Vector1DType } from './Vector1d'

Expand All @@ -14,17 +15,19 @@ export function ScrollTo(
indexCurrent: CounterType,
indexPrevious: CounterType,
scrollTarget: ScrollTargetType,
scrollBody: ScrollBodyType,
targetVector: Vector1DType,
eventHandler: EventHandlerType,
): ScrollToType {
function scrollTo(target: TargetType): void {
const distanceDiff = target.distance
const indexDiff = target.index !== indexCurrent.get()

if (distanceDiff) {
animation.start()
targetVector.add(distanceDiff)
}
scrollBody.useDirection(distanceDiff)
targetVector.add(distanceDiff)

if (distanceDiff) animation.start()

if (indexDiff) {
indexPrevious.set(indexCurrent.get())
indexCurrent.set(target.index)
Expand Down
27 changes: 15 additions & 12 deletions packages/embla-carousel/src/components/SlideLooper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type EdgeType = 'start' | 'end'
type LoopPointType = {
index: number
translate: TranslateType
location: Vector1DType
slideLocation: Vector1DType
target: () => number
}

Expand All @@ -29,7 +29,7 @@ export function SlideLooper(
slideSizesWithGaps: number[],
scrollSnaps: number[],
slidesInView: SlidesInViewType,
scroll: Vector1DType,
location: Vector1DType,
slides: HTMLElement[],
): SlideLooperType {
const ascItems = arrayKeys(slideSizesWithGaps)
Expand Down Expand Up @@ -58,11 +58,14 @@ export function SlideLooper(
const initial = isStartEdge ? 0 : -contentSize
const altered = isStartEdge ? contentSize : 0
const bounds = slideBounds.filter((b) => b.index === index)[0]
const point = bounds[isStartEdge ? 'end' : 'start']
const location = Vector1D(-1)
const translate = Translate(axis, direction, slides[index])
const target = () => (scroll.get() > point ? initial : altered)
return { index, location, translate, target }
const loopPoint = bounds[isStartEdge ? 'end' : 'start']

return {
index,
slideLocation: Vector1D(-1),
translate: Translate(axis, direction, slides[index]),
target: () => (location.get() > loopPoint ? initial : altered),
}
})
}

Expand All @@ -87,11 +90,11 @@ export function SlideLooper(

function loop(): void {
loopPoints.forEach((loopPoint) => {
const { target, translate, location } = loopPoint
const shift = target()
if (shift === location.get()) return
translate.to(shift)
location.set(shift)
const { target, translate, slideLocation } = loopPoint
const shiftLocation = target()
if (shiftLocation === slideLocation.get()) return
translate.to(shiftLocation)
slideLocation.set(shiftLocation)
})
}

Expand Down