refactor(stage.ts): rename class 'watchable' to 'Watchable' for consistency and clarity

feat(utils.ts): add Watchable class to provide a generic watchable object with getter, setter, and watcher functionality
This commit is contained in:
Sped0n
2023-10-29 12:31:48 +08:00
parent d7cabdb894
commit bb9870176f
2 changed files with 32 additions and 23 deletions

View File

@@ -1,34 +1,20 @@
import { incIndex, getState } from './state' import { incIndex, getState } from './state'
import { gsap, Power3 } from 'gsap' import { gsap, Power3 } from 'gsap'
import { ImageJSON } from './resources' import { ImageJSON } from './resources'
import { Watchable } from './utils'
// types
export type HistoryItem = { i: number; x: number; y: number } export type HistoryItem = { i: number; x: number; y: number }
// variables
let imgs: HTMLImageElement[] = [] let imgs: HTMLImageElement[] = []
class watchable<T> {
constructor(private obj: T) {}
private watchers: (() => void)[] = []
get(): T {
return this.obj
}
set(e: T): void {
this.obj = e
this.watchers.forEach((watcher) => watcher())
}
addWatcher(watcher: () => void): void {
this.watchers.push(watcher)
}
}
let last = { x: 0, y: 0 } let last = { x: 0, y: 0 }
export const cordHist = new watchable<HistoryItem[]>([]) export const cordHist = new Watchable<HistoryItem[]>([])
export const isOpen = new watchable<boolean>(false) export const isOpen = new Watchable<boolean>(false)
export const isAnimating = new watchable<boolean>(false) export const isAnimating = new Watchable<boolean>(false)
export const active = new watchable<boolean>(false) export const active = new Watchable<boolean>(false)
// getter // getter
@@ -163,12 +149,17 @@ export function minimizeImage(): void {
// init // init
export function initStage(ijs: ImageJSON[]): void { export function initStage(ijs: ImageJSON[]): void {
// create stage element
createStage(ijs) createStage(ijs)
// get stage
const stage = document.getElementsByClassName('stage').item(0) as HTMLDivElement const stage = document.getElementsByClassName('stage').item(0) as HTMLDivElement
// get image elements
imgs = Array.from(stage.getElementsByTagName('img')) imgs = Array.from(stage.getElementsByTagName('img'))
// event listeners
stage.addEventListener('click', () => expandImage()) stage.addEventListener('click', () => expandImage())
stage.addEventListener('keydown', () => expandImage()) stage.addEventListener('keydown', () => expandImage())
window.addEventListener('mousemove', onMouse) window.addEventListener('mousemove', onMouse)
// watchers
isOpen.addWatcher(() => active.set(isOpen.get() && !isAnimating.get())) isOpen.addWatcher(() => active.set(isOpen.get() && !isAnimating.get()))
isAnimating.addWatcher(() => active.set(isOpen.get() && !isAnimating.get())) isAnimating.addWatcher(() => active.set(isOpen.get() && !isAnimating.get()))
cordHist.addWatcher(() => setPositions()) cordHist.addWatcher(() => setPositions())

View File

@@ -13,3 +13,21 @@ export function expand(num: number): string {
export function isMobile(): boolean { export function isMobile(): boolean {
return window.matchMedia('(hover: none)').matches return window.matchMedia('(hover: none)').matches
} }
export class Watchable<T> {
constructor(private obj: T) {}
private watchers: (() => void)[] = []
get(): T {
return this.obj
}
set(e: T): void {
this.obj = e
this.watchers.forEach((watcher) => watcher())
}
addWatcher(watcher: () => void): void {
this.watchers.push(watcher)
}
}