Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Commit

Permalink
refactor: change public api
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Change exported api
change scrollTo functions to centerElement, scrollTo, and scrollBy
and add screen scroll type
  • Loading branch information
davidpa9708 authored and David Perez Alvarez committed Nov 2, 2018
1 parent a1dd1ad commit 8b23c06
Showing 1 changed file with 76 additions and 44 deletions.
120 changes: 76 additions & 44 deletions src/scroll.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
import { ScrollElement } from "./element"
import { AnimationManager } from "./animation-manager"
import { EasingFunction, defaultEasingFunction } from "./easing"
import { Animation } from "./animation"

const defaultSettings = {
easing: defaultEasingFunction,
}
import { AnimationManager } from "./animation-manager"
import { defaultEasingFunction, EasingFunction } from "./easing"
import { ScrollElement } from "./element"

export type onScroll = (() => void) | null

enum ScrollType {
value = "value",
percent = "percent",
screen = "screen",
}

interface ISettings {
easing: EasingFunction
onScroll?: onScroll
onUtilityScroll?: onScroll
onExternalScroll?: onScroll
onScroll: onScroll
onUtilityScroll: onScroll
onExternalScroll: onScroll
options: Required<IOptions>
}

const defaultSettings: ISettings = {
easing: defaultEasingFunction,
onScroll: null,
onUtilityScroll: null,
onExternalScroll: null,
options: {
value: 0,
duration: 1000,
horizontal: false,
},
}

interface IOptions {
Expand All @@ -22,53 +37,70 @@ interface IOptions {
horizontal?: boolean
}

interface IScrollToElementOptions extends IOptions {
center?: number
}

class Scroll {
private element: ScrollElement
private settings: ISettings
private animationManager: AnimationManager
constructor(element?: HTMLElement, private settings: ISettings = defaultSettings) {
constructor(element?: HTMLElement | Window, settings: Partial<ISettings> = defaultSettings) {
this.element = new ScrollElement(element)
this.animationManager = new AnimationManager(
() => this.settings.onUtilityScroll && this.settings.onUtilityScroll(),
() => this.settings.onExternalScroll && this.settings.onExternalScroll(),
this.element.position,
)
this.element.onScroll = () => this.settings.onScroll && this.settings.onScroll()
this.settings = defaultSettings
this.updateSettings(settings)
}
public updateSettings(settings: Partial<ISettings>) {
this.settings = Object.assign(this.settings, settings)
this.element.onScroll = this.settings.onScroll
}
public stopAllAnimations() {
this.animationManager.stopAllAnimations()
}
public readonly scroll = {
toElement: (element: HTMLElement, options: IScrollToElementOptions = {}): Animation => {
const ratio = (options.value || 0) / 100
const horizontal = !!options.horizontal
const elementWrapper = new ScrollElement(element)
const screenOffset = (this.element.size(horizontal) - elementWrapper.size(horizontal)) * ratio
const elementPosition = elementWrapper.offset(horizontal) - this.element.offset(horizontal)
return this.scroll.offset(elementPosition - screenOffset, options)
},
toPercent: (percent: number, options: IOptions = {}): Animation => {
const horizontal = !!options.horizontal
const position =
((this.element.scrollSize(horizontal) - this.element.size(horizontal)) * percent) / 100
return this.scroll.toPosition(position, options)
},
toPosition: (position: number, options: IOptions = {}): Animation => {
const dist = position - this.element.position(!!options.horizontal)
return this.scroll.offset(dist, options)
},
offset: (amount: number, options: IOptions = {}): Animation => {
return this.animationManager.createScrollAnimation({
distToScroll: amount,
duration: options.duration || 0,
horizontal: options.horizontal || false,
easing: this.settings.easing,
})
},
public centerElement(
element: HTMLElement,
_options: IOptions = this.settings.options,
): Animation {
const options = this.getDefault(_options)
const ratio = (options.value || 0) / 100
const horizontal = options.horizontal
const elementWrapper = new ScrollElement(element)
const screenOffset = (this.element.size(horizontal) - elementWrapper.size(horizontal)) * ratio
const elementPosition = elementWrapper.offset(horizontal) - this.element.offset(horizontal)
return this.offsetScroll({ ...options, value: elementPosition - screenOffset })
}
public scrollTo(scrollType: ScrollType, _options: IOptions = this.settings.options) {
const options = this.getDefault(_options)
const dist = this.getDist(scrollType, options.value, options.horizontal)
this.offsetScroll({ ...options, value: dist - this.element.position(options.horizontal) })
}
public scrollBy(scrollType: ScrollType, _options: IOptions = this.settings.options) {
const options = this.getDefault(_options)
const dist = this.getDist(scrollType, options.value, options.horizontal)
this.offsetScroll({ ...options, value: dist })
}
private offsetScroll(options: Required<IOptions>) {
return this.animationManager.createScrollAnimation({
distToScroll: options.value,
easing: this.settings.easing,
duration: options.duration,
horizontal: options.horizontal,
})
}
private getDist(scrollType: ScrollType, value: number, horizontal: boolean): number {
switch (scrollType) {
case ScrollType.percent:
return ((this.element.scrollSize(horizontal) - this.element.size(horizontal)) * value) / 100
case ScrollType.screen:
return this.element.size(horizontal) * value
default:
return value
}
}
private getDefault(options: IOptions): Required<IOptions> {
return Object.assign(this.settings.options, options)
}
}

export { Scroll, IOptions, IScrollToElementOptions, Animation }
export { Scroll, IOptions, Animation }

0 comments on commit 8b23c06

Please sign in to comment.