Skip to content

Commit

Permalink
Move wrapAround from ScrollLimit to ScrollLooper, ship ScrollBy feature
Browse files Browse the repository at this point in the history
  • Loading branch information
David Cetinkaya committed Jan 31, 2020
1 parent 937d856 commit 04ea670
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 36 deletions.
2 changes: 1 addition & 1 deletion docs/index.js

Large diffs are not rendered by default.

9 changes: 4 additions & 5 deletions src/__tests__/scrollLimit.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { ChunkSize } from '../components/chunkSize'
import { Limit } from '../components/limit'
import { ScrollLimit } from '../components/scrollLimit'

const snapSizes = [80, 40, 30, 40, 60]
const scrollSnaps = [10, -50, -85, -120, -170]
const contentSize = snapSizes.reduce((a, s) => a + s, 0)
const chunkSize = ChunkSize(1000)

const getScrollLimit = (loop: boolean) => {
const scrollLimit = ScrollLimit({ chunkSize, contentSize, loop })
const getScrollLimit = (loop: boolean): Limit => {
const scrollLimit = ScrollLimit({ contentSize, loop })
return scrollLimit.measure(scrollSnaps)
}

Expand All @@ -20,6 +19,6 @@ describe('ScrollLimit', () => {
test('Calculates correct scroll limit when loop is true', () => {
const scrollLimit = getScrollLimit(true)
expect(scrollLimit.max).toEqual(10)
expect(scrollLimit.min).toEqual(-239.9)
expect(scrollLimit.min).toEqual(-240)
})
})
3 changes: 3 additions & 0 deletions src/__tests__/scrollLooper.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ChunkSize } from '../components/chunkSize'
import { ScrollLooper } from '../components/scrollLooper'
import { Vector1D } from '../components/vector1d'
import { Limit } from '../components/limit'
Expand All @@ -9,6 +10,7 @@ const minLimit = 0
const maxLimit = 10
const contentSize = 10
const limit = Limit({ min: minLimit, max: maxLimit })
const chunkSize = ChunkSize(1000)
const vectorOneInitialValue = 5
const vectorTwoInitialValue = 10

Expand All @@ -19,6 +21,7 @@ beforeEach(() => {
Vector1D(vectorTwoInitialValue),
]
scrollLooper = ScrollLooper({
chunkSize,
limit,
location,
contentSize,
Expand Down
18 changes: 9 additions & 9 deletions src/__tests__/scrollProgress.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { ChunkSize } from '../components/chunkSize'
import { ScrollLimit } from '../components/scrollLimit'
import { ScrollProgress } from '../components/scrollProgress'
import { Vector1D } from '../components/vector1d'

const snapSizes = [80, 40, 30, 40, 60]
const scrollSnaps = [10, -50, -85, -120, -170]
const contentSize = snapSizes.reduce((a, s) => a + s, 0)
const chunkSize = ChunkSize(1000)
const startSnap = scrollSnaps[0]
const endSnap = scrollSnaps[scrollSnaps.length - 1]
const location = Vector1D(0)

const getScrollProgress = (loop: boolean) => {
const scrollLimit = ScrollLimit({ chunkSize, contentSize, loop })
const getScrollProgress = (loop: boolean): ScrollProgress => {
const scrollLimit = ScrollLimit({ contentSize, loop })
const limit = scrollLimit.measure(scrollSnaps)
return ScrollProgress({ location, limit })
}
Expand All @@ -19,18 +19,18 @@ describe('ScrollProgress', () => {
test('Calculates correct progress when loop is false', () => {
const scrollProgress = getScrollProgress(false)

location.setNumber(scrollSnaps[0])
location.setNumber(startSnap)
expect(scrollProgress.get()).toBe(-0)
location.setNumber(scrollSnaps[scrollSnaps.length - 1])
location.setNumber(endSnap)
expect(scrollProgress.get()).toBe(1)
})

test('Calculates correct progress when loop is true', () => {
const scrollProgress = getScrollProgress(true)

location.setNumber(scrollSnaps[0])
location.setNumber(startSnap)
expect(scrollProgress.get()).toBe(-0)
location.setNumber(scrollSnaps[scrollSnaps.length - 1])
expect(scrollProgress.get()).toBe(0.7202881152460984)
location.setNumber(endSnap)
expect(scrollProgress.get()).toBe(0.72)
})
})
2 changes: 1 addition & 1 deletion src/components/dragBehaviour.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export function DragBehaviour(params: Params): DragBehaviour {
const next = index.clone().add(indexDiff)
scrollTo.index(next.get(), 0)
} else {
scrollTo.distance(force)
scrollTo.distance(force, !dragFree)
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/components/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Mover } from './mover'
import { Options } from './options'
import { Pointer } from './pointer'
import { ScrollBounds } from './scrollBounds'
import { ScrollBy } from './scrollBy'
import { ScrollContain } from './scrollContain'
import { ScrollLimit } from './scrollLimit'
import { ScrollLooper } from './scrollLooper'
Expand All @@ -35,6 +36,7 @@ export type Engine = {
target: Vector1D
translate: Translate
scrollTo: ScrollTo
scrollBy: ScrollBy
}

export function Engine(
Expand Down Expand Up @@ -89,7 +91,7 @@ export function Engine(
const indexPrevious = index.clone()

// ScrollLimit
const scrollLimit = ScrollLimit({ loop, chunkSize, contentSize })
const scrollLimit = ScrollLimit({ loop, contentSize })
const limit = scrollLimit.measure(scrollSnaps)

// Direction
Expand Down Expand Up @@ -130,7 +132,6 @@ export function Engine(
scrollTarget: ScrollTarget({
align,
contentSize,
dragFree,
index,
limit,
loop,
Expand Down Expand Up @@ -173,7 +174,13 @@ export function Engine(
mover,
tolerance: 50,
}),
scrollBy: ScrollBy({
limit,
location,
loop,
}),
scrollLooper: ScrollLooper({
chunkSize,
contentSize,
limit,
location,
Expand Down
35 changes: 35 additions & 0 deletions src/components/scrollBy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Limit } from './limit'
import { Vector1D } from './vector1d'

type Params = {
loop: boolean
limit: Limit
location: Vector1D
}

export type ScrollBy = {
distance: (n: number) => number
}

export function ScrollBy(params: Params): ScrollBy {
const { loop, limit, location } = params
const { min, max, reachedMin, reachedMax } = limit
const scrollLength = min - max

function withinBounds(n: number): number {
const target = location.get() + n
if (reachedMax(target)) return max - location.get()
if (reachedMin(target)) return min - location.get()
return n
}

function distance(n: number): number {
const progress = scrollLength * n
return loop ? progress : withinBounds(progress)
}

const self: ScrollBy = {
distance,
}
return Object.freeze(self)
}
9 changes: 3 additions & 6 deletions src/components/scrollLimit.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { ChunkSize } from './chunkSize'
import { Limit } from './limit'

type Params = {
chunkSize: ChunkSize
contentSize: number
loop: boolean
}
Expand All @@ -12,15 +10,14 @@ export type ScrollLimit = {
}

export function ScrollLimit(params: Params): ScrollLimit {
const { contentSize, chunkSize, loop } = params
const loopSize = -contentSize + chunkSize.measure(1)
const { contentSize, loop } = params

function measure(scrollSnaps: number[]): Limit {
const startSnap = scrollSnaps[0]
const endSnap = scrollSnaps[scrollSnaps.length - 1]
const min = loop ? startSnap - contentSize : endSnap
const max = startSnap
const min = loop ? max + loopSize : endSnap
return Limit({ max, min })
return Limit({ min, max })
}

const self: ScrollLimit = {
Expand Down
10 changes: 7 additions & 3 deletions src/components/scrollLooper.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { ChunkSize } from './chunkSize'
import { Limit } from './limit'
import { Vector1D } from './vector1d'

type Params = {
chunkSize: ChunkSize
contentSize: number
limit: Limit
location: Vector1D
contentSize: number
vectors: Vector1D[]
}

Expand All @@ -13,8 +15,10 @@ export type ScrollLooper = {
}

export function ScrollLooper(params: Params): ScrollLooper {
const { limit, location, contentSize, vectors } = params
const { reachedMin, reachedMax } = limit
const { limit, location, chunkSize, contentSize, vectors } = params
const min = limit.min + chunkSize.measure(0.1)
const max = limit.max + chunkSize.measure(0.1)
const { reachedMin, reachedMax } = Limit({ min, max })

function shouldLoop(direction: number): boolean {
const reachedLimit = direction === -1 ? reachedMin : reachedMax
Expand Down
11 changes: 5 additions & 6 deletions src/components/scrollTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Vector1D } from './vector1d'

type Params = {
align: Alignments
dragFree: boolean
index: Counter
loop: boolean
snapSizes: number[]
Expand All @@ -27,7 +26,7 @@ export type Target = {

export type ScrollTarget = {
byIndex: (target: number, direction: number) => Target
byDistance: (force: number) => Target
byDistance: (force: number, snap: boolean) => Target
}

export function ScrollTarget(params: Params): ScrollTarget {
Expand Down Expand Up @@ -59,7 +58,7 @@ export function ScrollTarget(params: Params): ScrollTarget {
while (reachedMax(distance)) distance -= contentSize
while (reachedMin(distance)) distance += contentSize
const foundIndex = snapBounds.reduce((a, b, i) => {
return distance < b.start && distance > b.end ? i : a
return distance <= b.start && distance > b.end ? i : a
}, 0)
return { distance, index: foundIndex }
}
Expand Down Expand Up @@ -88,13 +87,13 @@ export function ScrollTarget(params: Params): ScrollTarget {
return target
}

function byDistance(force: number): Target {
const { target, dragFree, index } = params
function byDistance(force: number, snap: boolean): Target {
const { target, index } = params
const distance = target.get() + force
const targetSnap = findTargetSnapAt(distance)
const reachedEdge = !loop && reachedAny(distance)

if (reachedEdge || dragFree) {
if (reachedEdge || !snap) {
const { min, max } = index
const edgeIndex = reachedMax(distance) ? min : max
const targetIndex = reachedEdge ? edgeIndex : targetSnap.index
Expand Down
6 changes: 3 additions & 3 deletions src/components/scrollTo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Params = {
}

export type ScrollTo = {
distance: (n: number) => void
distance: (n: number, snap: boolean) => void
index: (n: number, direction: number) => void
}

Expand All @@ -37,8 +37,8 @@ export function ScrollTo(params: Params): ScrollTo {
}
}

function distance(n: number): void {
const target = scrollTarget.byDistance(n)
function distance(n: number, snap: boolean): void {
const target = scrollTarget.byDistance(n, snap)
scrollTo(target)
}

Expand Down
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type EmblaCarousel = {
off: (evt: EmblaEvent, cb: EmblaCallback) => void
on: (evt: EmblaEvent, cb: EmblaCallback) => void
previousScrollSnap: () => number
scrollBy: (progress: number) => void
scrollNext: () => void
scrollPrev: () => void
scrollProgress: () => number
Expand Down Expand Up @@ -179,6 +180,12 @@ export function EmblaCarousel(
slider.scrollTo.index(prev.get(), 1)
}

function scrollBy(progress: number): void {
const distance = slider.scrollBy.distance(progress)
slider.mover.useDefaultMass().useDefaultSpeed()
slider.scrollTo.distance(distance, false)
}

function scrollTo(index: number): void {
slider.mover.useDefaultMass().useDefaultSpeed()
slider.scrollTo.index(index, 0)
Expand Down Expand Up @@ -228,6 +235,7 @@ export function EmblaCarousel(
off,
on,
previousScrollSnap,
scrollBy,
scrollNext,
scrollPrev,
scrollProgress,
Expand Down

0 comments on commit 04ea670

Please sign in to comment.