mirror of
https://github.com/Sped0n/bridget.git
synced 2026-04-21 13:39:30 -07:00
fix(customCursor.ts): move import statement for active to the top for better organization
fix(customCursor.ts): add return type void to onMouse function for clarity fix(customCursor.ts): add passive option to window event listener for mousemove to improve performance fix(stageNav.ts): move import statement for setCustomCursor to the top for better organization fix(stageNav.ts): add return type void to handleClick function for clarity fix(stageNav.ts): add return type void to handleKey function for clarity fix(stageNav.ts): add passive option to overlay event listeners for click, keydown, mouseover, and focus to improve performance fix(stageNav.ts): add passive option to window event listener for keydown to improve performance fix(stageNav.ts): add return type void to nextImage function for clarity fix(stageNav.ts): add return type void to prevImage function for clarity fix(gallery.ts): move import statement for Swiper to the top for better organization fix(gallery.ts): add return type void to slideUp function for clarity fix(gallery.ts): add return type void to initGallery function for clarity fix(gallery.ts): add passive option to window event listener for touchstart to improve performance fix(gallery.ts): add return type void to changeSlide function for clarity fix(gallery.ts): add return type void to scrollToActive function for clarity fix(gallery.ts): add return type void to createGallery function for clarity fix(gallery.ts): add passive option to close event listeners for click and keydown to improve performance fix(gallery.ts): add passive option to overlay event listeners for click, keydown, mouseover, and focus to improve performance fix(gallery.ts): add passive option to window event listener for touchstart to improve performance fix(nav.ts): add return type void to initNav function for clarity fix(utils.ts): add return type number to getRandom function for clarity fix(utils.ts): add return type void to onVisible function for clarity fix(utils.ts): add return type void to addWatcher function in Watchable class for clarity
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { active } from './stage'
|
|
||||||
import { container } from '../container'
|
import { container } from '../container'
|
||||||
|
|
||||||
|
import { active } from './stage'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* variables
|
* variables
|
||||||
*/
|
*/
|
||||||
@@ -12,7 +13,7 @@ const cursorInner = document.createElement('div')
|
|||||||
* main functions
|
* main functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function onMouse(e: MouseEvent) {
|
function onMouse(e: MouseEvent): void {
|
||||||
const x = e.clientX
|
const x = e.clientX
|
||||||
const y = e.clientY
|
const y = e.clientY
|
||||||
cursor.style.transform = `translate3d(${x}px, ${y}px, 0)`
|
cursor.style.transform = `translate3d(${x}px, ${y}px, 0)`
|
||||||
@@ -35,7 +36,7 @@ export function initCustomCursor(): void {
|
|||||||
// append cursor to main
|
// append cursor to main
|
||||||
container.append(cursor)
|
container.append(cursor)
|
||||||
// bind mousemove event to window
|
// bind mousemove event to window
|
||||||
window.addEventListener('mousemove', onMouse)
|
window.addEventListener('mousemove', onMouse, { passive: true })
|
||||||
// add active callback
|
// add active callback
|
||||||
active.addWatcher(() => {
|
active.addWatcher(() => {
|
||||||
if (active.get()) {
|
if (active.get()) {
|
||||||
|
|||||||
11
assets/ts/desktop/init.ts
Normal file
11
assets/ts/desktop/init.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { type ImageJSON } from '../resources'
|
||||||
|
|
||||||
|
import { initCustomCursor } from './customCursor'
|
||||||
|
import { initStage } from './stage'
|
||||||
|
import { initStageNav } from './stageNav'
|
||||||
|
|
||||||
|
export function initDesktop(ijs: ImageJSON[]): void {
|
||||||
|
initCustomCursor()
|
||||||
|
initStage(ijs)
|
||||||
|
initStageNav()
|
||||||
|
}
|
||||||
@@ -1,14 +1,19 @@
|
|||||||
import { Power3, gsap } from 'gsap'
|
import { Power3, gsap } from 'gsap'
|
||||||
|
|
||||||
import { container } from '../container'
|
import { container } from '../container'
|
||||||
import { ImageJSON } from '../resources'
|
import { type ImageJSON } from '../resources'
|
||||||
import { incIndex, state } from '../state'
|
import { incIndex, state } from '../state'
|
||||||
import { Watchable } from '../utils'
|
import { Watchable, decrement, increment } from '../utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* types
|
* types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type HistoryItem = { i: number; x: number; y: number }
|
export interface HistoryItem {
|
||||||
|
i: number
|
||||||
|
x: number
|
||||||
|
y: number
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* variables
|
* variables
|
||||||
@@ -44,7 +49,22 @@ function getElCurrent(): HTMLImageElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getElNextFive(): HTMLImageElement[] {
|
function getElNextFive(): HTMLImageElement[] {
|
||||||
return state.get().nextFive.map((i) => imgs[i])
|
const s = state.get()
|
||||||
|
const els = []
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
els.push(imgs[increment(s.index + i, s.length)])
|
||||||
|
}
|
||||||
|
return els
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElPrev(): HTMLImageElement {
|
||||||
|
const s = state.get()
|
||||||
|
return imgs[increment(s.index, s.length)]
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElNext(): HTMLImageElement {
|
||||||
|
const s = state.get()
|
||||||
|
return imgs[decrement(s.index, s.length)]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,7 +89,7 @@ function onMouse(e: MouseEvent): void {
|
|||||||
// set image position with gsap
|
// set image position with gsap
|
||||||
function setPositions(): void {
|
function setPositions(): void {
|
||||||
const elTrail = getElTrail()
|
const elTrail = getElTrail()
|
||||||
if (!elTrail.length) return
|
if (elTrail.length === 0) return
|
||||||
|
|
||||||
// preload
|
// preload
|
||||||
lores(getElNextFive())
|
lores(getElNextFive())
|
||||||
@@ -98,7 +118,7 @@ function expandImage(): void {
|
|||||||
isOpen.set(true)
|
isOpen.set(true)
|
||||||
isAnimating.set(true)
|
isAnimating.set(true)
|
||||||
|
|
||||||
hires([getElCurrent()])
|
hires([getElCurrent(), getElPrev(), getElNext()])
|
||||||
|
|
||||||
const tl = gsap.timeline()
|
const tl = gsap.timeline()
|
||||||
// move down and hide trail inactive
|
// move down and hide trail inactive
|
||||||
@@ -125,6 +145,7 @@ function expandImage(): void {
|
|||||||
ease: Power3.easeInOut
|
ease: Power3.easeInOut
|
||||||
})
|
})
|
||||||
// finished
|
// finished
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
tl.then(() => {
|
tl.then(() => {
|
||||||
isAnimating.set(false)
|
isAnimating.set(false)
|
||||||
})
|
})
|
||||||
@@ -137,6 +158,9 @@ export function minimizeImage(): void {
|
|||||||
isOpen.set(false)
|
isOpen.set(false)
|
||||||
isAnimating.set(true)
|
isAnimating.set(true)
|
||||||
|
|
||||||
|
lores([getElCurrent()])
|
||||||
|
lores(getElTrailInactive())
|
||||||
|
|
||||||
const tl = gsap.timeline()
|
const tl = gsap.timeline()
|
||||||
// shrink current
|
// shrink current
|
||||||
tl.to(getElCurrent(), {
|
tl.to(getElCurrent(), {
|
||||||
@@ -161,6 +185,7 @@ export function minimizeImage(): void {
|
|||||||
opacity: 1
|
opacity: 1
|
||||||
})
|
})
|
||||||
// finished
|
// finished
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
tl.then(() => {
|
tl.then(() => {
|
||||||
isAnimating.set(false)
|
isAnimating.set(false)
|
||||||
})
|
})
|
||||||
@@ -178,13 +203,23 @@ export function initStage(ijs: ImageJSON[]): void {
|
|||||||
// get image elements
|
// get image elements
|
||||||
imgs = Array.from(stage.getElementsByTagName('img'))
|
imgs = Array.from(stage.getElementsByTagName('img'))
|
||||||
// event listeners
|
// event listeners
|
||||||
stage.addEventListener('click', () => expandImage())
|
stage.addEventListener('click', () => {
|
||||||
stage.addEventListener('keydown', () => expandImage())
|
expandImage()
|
||||||
window.addEventListener('mousemove', onMouse)
|
})
|
||||||
|
stage.addEventListener('keydown', () => {
|
||||||
|
expandImage()
|
||||||
|
})
|
||||||
|
window.addEventListener('mousemove', onMouse, { passive: true })
|
||||||
// watchers
|
// watchers
|
||||||
isOpen.addWatcher(() => active.set(isOpen.get() && !isAnimating.get()))
|
isOpen.addWatcher(() => {
|
||||||
isAnimating.addWatcher(() => active.set(isOpen.get() && !isAnimating.get()))
|
active.set(isOpen.get() && !isAnimating.get())
|
||||||
cordHist.addWatcher(() => setPositions())
|
})
|
||||||
|
isAnimating.addWatcher(() => {
|
||||||
|
active.set(isOpen.get() && !isAnimating.get())
|
||||||
|
})
|
||||||
|
cordHist.addWatcher(() => {
|
||||||
|
setPositions()
|
||||||
|
})
|
||||||
// preload
|
// preload
|
||||||
lores(getElNextFive())
|
lores(getElNextFive())
|
||||||
}
|
}
|
||||||
@@ -198,7 +233,7 @@ function createStage(ijs: ImageJSON[]): void {
|
|||||||
const stage: HTMLDivElement = document.createElement('div')
|
const stage: HTMLDivElement = document.createElement('div')
|
||||||
stage.className = 'stage'
|
stage.className = 'stage'
|
||||||
// append images to container
|
// append images to container
|
||||||
for (let ij of ijs) {
|
for (const ij of ijs) {
|
||||||
const e = document.createElement('img')
|
const e = document.createElement('img')
|
||||||
e.height = ij.loImgH
|
e.height = ij.loImgH
|
||||||
e.width = ij.loImgW
|
e.width = ij.loImgW
|
||||||
@@ -217,16 +252,16 @@ function createStage(ijs: ImageJSON[]): void {
|
|||||||
|
|
||||||
function hires(imgs: HTMLImageElement[]): void {
|
function hires(imgs: HTMLImageElement[]): void {
|
||||||
imgs.forEach((img) => {
|
imgs.forEach((img) => {
|
||||||
img.src = img.dataset.hiUrl!
|
img.src = img.dataset.hiUrl as string
|
||||||
img.height = parseInt(img.dataset.hiImgH!)
|
img.height = parseInt(img.dataset.hiImgH as string)
|
||||||
img.width = parseInt(img.dataset.hiImgW!)
|
img.width = parseInt(img.dataset.hiImgW as string)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function lores(imgs: HTMLImageElement[]): void {
|
function lores(imgs: HTMLImageElement[]): void {
|
||||||
imgs.forEach((img) => {
|
imgs.forEach((img) => {
|
||||||
img.src = img.dataset.loUrl!
|
img.src = img.dataset.loUrl as string
|
||||||
img.height = parseInt(img.dataset.loImgH!)
|
img.height = parseInt(img.dataset.loImgH as string)
|
||||||
img.width = parseInt(img.dataset.loImgW!)
|
img.width = parseInt(img.dataset.loImgW as string)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { container } from '../container'
|
import { container } from '../container'
|
||||||
import { decIndex, incIndex, state } from '../state'
|
import { decIndex, incIndex, state } from '../state'
|
||||||
import { decrement, increment } from '../utils'
|
import { decrement, increment } from '../utils'
|
||||||
|
|
||||||
import { setCustomCursor } from './customCursor'
|
import { setCustomCursor } from './customCursor'
|
||||||
import { active, cordHist, isAnimating, isOpen, minimizeImage } from './stage'
|
import { active, cordHist, isAnimating, isOpen, minimizeImage } from './stage'
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ const navItems = ['prev', 'close', 'next'] as const
|
|||||||
* main functions
|
* main functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function handleClick(type: NavItem) {
|
function handleClick(type: NavItem): void {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'prev':
|
case 'prev':
|
||||||
prevImage()
|
prevImage()
|
||||||
@@ -34,7 +35,7 @@ function handleClick(type: NavItem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKey(e: KeyboardEvent) {
|
function handleKey(e: KeyboardEvent): void {
|
||||||
if (isOpen.get() || isAnimating.get()) return
|
if (isOpen.get() || isAnimating.get()) return
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case 'ArrowLeft':
|
case 'ArrowLeft':
|
||||||
@@ -53,16 +54,40 @@ function handleKey(e: KeyboardEvent) {
|
|||||||
* init
|
* init
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function initStageNav() {
|
export function initStageNav(): void {
|
||||||
const navOverlay = document.createElement('div')
|
const navOverlay = document.createElement('div')
|
||||||
navOverlay.className = 'navOverlay'
|
navOverlay.className = 'navOverlay'
|
||||||
for (let navItem of navItems) {
|
for (const navItem of navItems) {
|
||||||
const overlay = document.createElement('div')
|
const overlay = document.createElement('div')
|
||||||
overlay.className = 'overlay'
|
overlay.className = 'overlay'
|
||||||
overlay.addEventListener('click', () => handleClick(navItem))
|
overlay.addEventListener(
|
||||||
overlay.addEventListener('keydown', () => handleClick(navItem))
|
'click',
|
||||||
overlay.addEventListener('mouseover', () => setCustomCursor(navItem))
|
() => {
|
||||||
overlay.addEventListener('focus', () => setCustomCursor(navItem))
|
handleClick(navItem)
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
|
overlay.addEventListener(
|
||||||
|
'keydown',
|
||||||
|
() => {
|
||||||
|
handleClick(navItem)
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
|
overlay.addEventListener(
|
||||||
|
'mouseover',
|
||||||
|
() => {
|
||||||
|
setCustomCursor(navItem)
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
|
overlay.addEventListener(
|
||||||
|
'focus',
|
||||||
|
() => {
|
||||||
|
setCustomCursor(navItem)
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
navOverlay.append(overlay)
|
navOverlay.append(overlay)
|
||||||
}
|
}
|
||||||
active.addWatcher(() => {
|
active.addWatcher(() => {
|
||||||
@@ -73,14 +98,14 @@ export function initStageNav() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
container.append(navOverlay)
|
container.append(navOverlay)
|
||||||
window.addEventListener('keydown', handleKey)
|
window.addEventListener('keydown', handleKey, { passive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hepler
|
* hepler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function nextImage() {
|
function nextImage(): void {
|
||||||
if (isAnimating.get()) return
|
if (isAnimating.get()) return
|
||||||
cordHist.set(
|
cordHist.set(
|
||||||
cordHist.get().map((item) => {
|
cordHist.get().map((item) => {
|
||||||
@@ -91,7 +116,7 @@ function nextImage() {
|
|||||||
incIndex()
|
incIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
function prevImage() {
|
function prevImage(): void {
|
||||||
if (isAnimating.get()) return
|
if (isAnimating.get()) return
|
||||||
cordHist.set(
|
cordHist.set(
|
||||||
cordHist.get().map((item) => {
|
cordHist.get().map((item) => {
|
||||||
|
|||||||
@@ -1,27 +1,20 @@
|
|||||||
import { initContainer } from './container'
|
import { initContainer } from './container'
|
||||||
import { initCustomCursor } from './desktop/customCursor'
|
|
||||||
import { initStage } from './desktop/stage'
|
|
||||||
import { initStageNav } from './desktop/stageNav'
|
|
||||||
import { initCollection } from './mobile/collection'
|
|
||||||
import { initGallery } from './mobile/gallery'
|
|
||||||
import { initNav } from './nav'
|
import { initNav } from './nav'
|
||||||
import { initResources } from './resources'
|
import { initResources } from './resources'
|
||||||
import { initState } from './state'
|
import { initState } from './state'
|
||||||
import { isMobile } from './utils'
|
import { isMobile } from './utils'
|
||||||
|
|
||||||
initContainer()
|
initContainer()
|
||||||
initCustomCursor()
|
|
||||||
const ijs = initResources()
|
const ijs = initResources()
|
||||||
initState(ijs.length)
|
initState(ijs.length)
|
||||||
|
|
||||||
initNav()
|
initNav()
|
||||||
|
|
||||||
if (ijs.length > 0) {
|
if (ijs.length > 0) {
|
||||||
if (!isMobile()) {
|
if (!isMobile()) {
|
||||||
initStage(ijs)
|
const d = await import('./desktop/stage')
|
||||||
initStageNav()
|
d.initStage(ijs)
|
||||||
} else {
|
} else {
|
||||||
initCollection(ijs)
|
const m = await import('./mobile/init')
|
||||||
initGallery(ijs)
|
m.initMobile(ijs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { container } from '../container'
|
import { container } from '../container'
|
||||||
import { ImageJSON } from '../resources'
|
import { type ImageJSON } from '../resources'
|
||||||
import { getNextFive, setIndex } from '../state'
|
import { setIndex } from '../state'
|
||||||
import { Watchable, getRandom, onVisible } from '../utils'
|
import { Watchable, getRandom, onVisible } from '../utils'
|
||||||
|
|
||||||
import { slideUp } from './gallery'
|
import { slideUp } from './gallery'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,16 +43,27 @@ export function initCollection(ijs: ImageJSON[]): void {
|
|||||||
imgs = Array.from(collection.getElementsByTagName('img'))
|
imgs = Array.from(collection.getElementsByTagName('img'))
|
||||||
// add event listeners
|
// add event listeners
|
||||||
imgs.forEach((img, i) => {
|
imgs.forEach((img, i) => {
|
||||||
img.addEventListener('click', () => handleClick(i))
|
img.addEventListener(
|
||||||
img.addEventListener('keydown', () => handleClick(i))
|
'click',
|
||||||
|
() => {
|
||||||
|
handleClick(i)
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
|
img.addEventListener(
|
||||||
|
'keydown',
|
||||||
|
() => {
|
||||||
|
handleClick(i)
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
// preload
|
// preload
|
||||||
onVisible(img, () => {
|
onVisible(img, () => {
|
||||||
// minues one because we want to preload the current and the next 4 images
|
for (let _i = 0; _i < 5; _i++) {
|
||||||
getNextFive(i - 1, imgs.length)
|
const n = i + _i
|
||||||
.map((i) => imgs[i])
|
if (n < 0 || n > imgs.length - 1) continue
|
||||||
.forEach((e) => {
|
imgs[n].src = imgs[n].dataset.src as string
|
||||||
e.src = e.dataset.src!
|
}
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -65,7 +77,7 @@ function createCollection(ijs: ImageJSON[]): void {
|
|||||||
const _collection: HTMLDivElement = document.createElement('div')
|
const _collection: HTMLDivElement = document.createElement('div')
|
||||||
_collection.className = 'collection'
|
_collection.className = 'collection'
|
||||||
// append images to container
|
// append images to container
|
||||||
for (let [i, ij] of ijs.entries()) {
|
for (const [i, ij] of ijs.entries()) {
|
||||||
// random x and y
|
// random x and y
|
||||||
const x = i !== 0 ? getRandom(-25, 25) : 0
|
const x = i !== 0 ? getRandom(-25, 25) : 0
|
||||||
const y = i !== 0 ? getRandom(-30, 30) : 0
|
const y = i !== 0 ? getRandom(-30, 30) : 0
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Power3, gsap } from 'gsap'
|
import { Power3, gsap } from 'gsap'
|
||||||
import Swiper from 'swiper'
|
import { Swiper } from 'swiper'
|
||||||
|
|
||||||
import { container } from '../container'
|
import { container } from '../container'
|
||||||
import { ImageJSON } from '../resources'
|
import { type ImageJSON } from '../resources'
|
||||||
import { setIndex, state } from '../state'
|
import { setIndex, state } from '../state'
|
||||||
import { Watchable, expand } from '../utils'
|
import { Watchable, expand } from '../utils'
|
||||||
|
|
||||||
import { imgs, mounted } from './collection'
|
import { imgs, mounted } from './collection'
|
||||||
import { scrollable } from './scroll'
|
import { scrollable } from './scroll'
|
||||||
|
|
||||||
@@ -46,7 +48,6 @@ export function slideUp(): void {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
scrollable.set(false)
|
scrollable.set(false)
|
||||||
isAnimating.set(false)
|
isAnimating.set(false)
|
||||||
console.log(swiper.activeIndex)
|
|
||||||
}, 1200)
|
}, 1200)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ export function initGallery(ijs: ImageJSON[]): void {
|
|||||||
createGallery(ijs)
|
createGallery(ijs)
|
||||||
// get elements
|
// get elements
|
||||||
indexDispNums = Array.from(
|
indexDispNums = Array.from(
|
||||||
document.getElementsByClassName('nav').item(0)!.getElementsByClassName('num')
|
document.getElementsByClassName('nav').item(0)?.getElementsByClassName('num') ?? []
|
||||||
) as HTMLSpanElement[]
|
) as HTMLSpanElement[]
|
||||||
swiperNode = document.getElementsByClassName('galleryInner').item(0) as HTMLDivElement
|
swiperNode = document.getElementsByClassName('galleryInner').item(0) as HTMLDivElement
|
||||||
gallery = document.getElementsByClassName('gallery').item(0) as HTMLDivElement
|
gallery = document.getElementsByClassName('gallery').item(0) as HTMLDivElement
|
||||||
@@ -100,9 +101,10 @@ export function initGallery(ijs: ImageJSON[]): void {
|
|||||||
setIndex(realIndex)
|
setIndex(realIndex)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// mounted
|
// mounted
|
||||||
mounted.set(true)
|
mounted.set(true)
|
||||||
|
// dynamic load
|
||||||
|
window.addEventListener('touchstart', () => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,7 +113,7 @@ export function initGallery(ijs: ImageJSON[]): void {
|
|||||||
|
|
||||||
function changeSlide(slide: number): void {
|
function changeSlide(slide: number): void {
|
||||||
loadImages()
|
loadImages()
|
||||||
swiper!.slideTo(slide, 0)
|
swiper.slideTo(slide, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollToActive(): void {
|
function scrollToActive(): void {
|
||||||
@@ -151,7 +153,7 @@ function createGallery(ijs: ImageJSON[]): void {
|
|||||||
const _swiperWrapper = document.createElement('div')
|
const _swiperWrapper = document.createElement('div')
|
||||||
_swiperWrapper.className = 'swiper-wrapper'
|
_swiperWrapper.className = 'swiper-wrapper'
|
||||||
// swiper slide
|
// swiper slide
|
||||||
for (let ij of ijs) {
|
for (const ij of ijs) {
|
||||||
const _swiperSlide = document.createElement('div')
|
const _swiperSlide = document.createElement('div')
|
||||||
_swiperSlide.className = 'swiper-slide'
|
_swiperSlide.className = 'swiper-slide'
|
||||||
// img
|
// img
|
||||||
@@ -179,8 +181,12 @@ function createGallery(ijs: ImageJSON[]): void {
|
|||||||
// close
|
// close
|
||||||
const _close = document.createElement('div')
|
const _close = document.createElement('div')
|
||||||
_close.innerText = 'Close'
|
_close.innerText = 'Close'
|
||||||
_close.addEventListener('click', () => slideDown())
|
_close.addEventListener('click', () => {
|
||||||
_close.addEventListener('keydown', () => slideDown())
|
slideDown()
|
||||||
|
})
|
||||||
|
_close.addEventListener('keydown', () => {
|
||||||
|
slideDown()
|
||||||
|
})
|
||||||
// nav
|
// nav
|
||||||
const _navDiv = document.createElement('div')
|
const _navDiv = document.createElement('div')
|
||||||
_navDiv.className = 'nav'
|
_navDiv.className = 'nav'
|
||||||
@@ -210,14 +216,14 @@ function createGallery(ijs: ImageJSON[]): void {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function loadImages(): void {
|
function loadImages(): void {
|
||||||
const activeImages = new Array()
|
const activeImages = []
|
||||||
// load current, next, prev image
|
// load current, next, prev image
|
||||||
activeImages.push(galleryImages[swiper.activeIndex])
|
activeImages.push(galleryImages[swiper.activeIndex])
|
||||||
activeImages.push(
|
activeImages.push(
|
||||||
galleryImages[Math.min(swiper.activeIndex + 1, swiper.slides.length)]
|
galleryImages[Math.min(swiper.activeIndex + 1, swiper.slides.length)]
|
||||||
)
|
)
|
||||||
activeImages.push(galleryImages[Math.max(swiper.activeIndex - 1, 0)])
|
activeImages.push(galleryImages[Math.max(swiper.activeIndex - 1, 0)])
|
||||||
for (let e of activeImages) {
|
for (const e of activeImages) {
|
||||||
e.src = e.dataset.src!
|
e.src = e.dataset.src as string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
assets/ts/mobile/init.ts
Normal file
9
assets/ts/mobile/init.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { type ImageJSON } from '../resources'
|
||||||
|
|
||||||
|
import { initCollection } from './collection'
|
||||||
|
import { initGallery } from './gallery'
|
||||||
|
|
||||||
|
export function initMobile(ijs: ImageJSON[]): void {
|
||||||
|
initCollection(ijs)
|
||||||
|
initGallery(ijs)
|
||||||
|
}
|
||||||
@@ -39,13 +39,16 @@ const links = Array.from(linksDiv.getElementsByClassName('link')) as HTMLAnchorE
|
|||||||
|
|
||||||
// current link index
|
// current link index
|
||||||
const currentLinkIndex = document
|
const currentLinkIndex = document
|
||||||
.getElementById('main')!
|
.getElementById('main')
|
||||||
.getAttribute('currentMenuItemIndex') as string
|
?.getAttribute('currentMenuItemIndex') as string
|
||||||
|
|
||||||
// set current link
|
// set current link
|
||||||
for (let [index, link] of links.entries()) {
|
for (const [index, link] of links.entries()) {
|
||||||
if (index === parseInt(currentLinkIndex)) {
|
if (index === parseInt(currentLinkIndex)) {
|
||||||
|
// set current link style
|
||||||
link.classList.add('current')
|
link.classList.add('current')
|
||||||
|
// set current link title (only if not home)
|
||||||
|
if (index !== 0) document.title = link.innerText + ' | ' + document.title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,14 +56,26 @@ for (let [index, link] of links.entries()) {
|
|||||||
* init
|
* init
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function initNav() {
|
export function initNav(): void {
|
||||||
// init threshold text
|
// init threshold text
|
||||||
updateThresholdText()
|
updateThresholdText()
|
||||||
// init index text
|
// init index text
|
||||||
updateIndexText()
|
updateIndexText()
|
||||||
// event listeners
|
// event listeners
|
||||||
decButton.addEventListener('click', () => decThreshold())
|
decButton.addEventListener(
|
||||||
incButton.addEventListener('click', () => incThreshold())
|
'click',
|
||||||
|
() => {
|
||||||
|
decThreshold()
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
|
incButton.addEventListener(
|
||||||
|
'click',
|
||||||
|
() => {
|
||||||
|
incThreshold()
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export interface ImageJSON {
|
|||||||
|
|
||||||
export function initResources(): ImageJSON[] {
|
export function initResources(): ImageJSON[] {
|
||||||
const imagesJson = document.getElementById('imagesSource')
|
const imagesJson = document.getElementById('imagesSource')
|
||||||
if (!imagesJson) {
|
if (imagesJson === null) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return JSON.parse(imagesJson.textContent as string).sort(
|
return JSON.parse(imagesJson.textContent as string).sort(
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ const thresholds = [
|
|||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
index: -1,
|
index: -1,
|
||||||
nextFive: new Array(), // for preload
|
|
||||||
length: 0,
|
length: 0,
|
||||||
threshold: thresholds[2].threshold,
|
threshold: thresholds[2].threshold,
|
||||||
trailLength: thresholds[2].trailLength
|
trailLength: thresholds[2].trailLength
|
||||||
@@ -36,7 +35,6 @@ export const state = new Watchable<State>(defaultState)
|
|||||||
export function initState(length: number): void {
|
export function initState(length: number): void {
|
||||||
const s = state.get()
|
const s = state.get()
|
||||||
s.length = length
|
s.length = length
|
||||||
s.nextFive = getNextFive(s.index, s.length)
|
|
||||||
state.set(s)
|
state.set(s)
|
||||||
state.addWatcher(() => {
|
state.addWatcher(() => {
|
||||||
updateIndexText()
|
updateIndexText()
|
||||||
@@ -47,21 +45,18 @@ export function initState(length: number): void {
|
|||||||
export function setIndex(index: number): void {
|
export function setIndex(index: number): void {
|
||||||
const s = state.get()
|
const s = state.get()
|
||||||
s.index = index
|
s.index = index
|
||||||
s.nextFive = getNextFive(s.index, s.length)
|
|
||||||
state.set(s)
|
state.set(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function incIndex(): void {
|
export function incIndex(): void {
|
||||||
const s = state.get()
|
const s = state.get()
|
||||||
s.index = increment(s.index, s.length)
|
s.index = increment(s.index, s.length)
|
||||||
s.nextFive = getNextFive(s.index, s.length)
|
|
||||||
state.set(s)
|
state.set(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decIndex(): void {
|
export function decIndex(): void {
|
||||||
const s = state.get()
|
const s = state.get()
|
||||||
s.index = decrement(s.index, s.length)
|
s.index = decrement(s.index, s.length)
|
||||||
s.nextFive = getNextFive(s.index, s.length)
|
|
||||||
state.set(s)
|
state.set(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,17 +77,9 @@ export function decThreshold(): void {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function updateThreshold(state: State, inc: number): State {
|
function updateThreshold(state: State, inc: number): State {
|
||||||
const i = thresholds.findIndex((t) => state.threshold === t.threshold)
|
const i = thresholds.findIndex((t) => state.threshold === t.threshold) + inc
|
||||||
const newItems = thresholds[i + inc]
|
// out of bounds
|
||||||
// out of range
|
if (i < 0 || i >= thresholds.length) return state
|
||||||
if (!newItems) return state
|
const newItems = thresholds[i]
|
||||||
return { ...state, ...newItems }
|
return { ...state, ...newItems }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNextFive(index: number, length: number): number[] {
|
|
||||||
const five = []
|
|
||||||
for (let i = 0; i < 5; i++) {
|
|
||||||
five.push(increment(index + i, length))
|
|
||||||
}
|
|
||||||
return five
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ export function isMobile(): boolean {
|
|||||||
return window.matchMedia('(hover: none)').matches
|
return window.matchMedia('(hover: none)').matches
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRandom(min: number, max: number) {
|
export function getRandom(min: number, max: number): number {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min
|
return Math.floor(Math.random() * (max - min + 1)) + min
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onVisible(
|
export function onVisible<T extends Element>(
|
||||||
element: HTMLImageElement,
|
element: T,
|
||||||
callback: (arg0: HTMLImageElement) => void
|
callback: (arg0: T) => void
|
||||||
) {
|
): void {
|
||||||
new IntersectionObserver((entries, observer) => {
|
new IntersectionObserver((entries, observer) => {
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
if (entry.intersectionRatio > 0) {
|
if (entry.intersectionRatio > 0) {
|
||||||
@@ -34,7 +34,6 @@ export function onVisible(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}).observe(element)
|
}).observe(element)
|
||||||
if (!callback) return new Promise((r) => (callback = r))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +42,7 @@ export function onVisible(
|
|||||||
|
|
||||||
export class Watchable<T> {
|
export class Watchable<T> {
|
||||||
constructor(private obj: T) {}
|
constructor(private obj: T) {}
|
||||||
private watchers: (() => void)[] = []
|
private readonly watchers: Array<() => void> = []
|
||||||
|
|
||||||
get(): T {
|
get(): T {
|
||||||
return this.obj
|
return this.obj
|
||||||
@@ -51,7 +50,9 @@ export class Watchable<T> {
|
|||||||
|
|
||||||
set(e: T): void {
|
set(e: T): void {
|
||||||
this.obj = e
|
this.obj = e
|
||||||
this.watchers.forEach((watcher) => watcher())
|
this.watchers.forEach((watcher) => {
|
||||||
|
watcher()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addWatcher(watcher: () => void): void {
|
addWatcher(watcher: () => void): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user