add lazyload background

This commit is contained in:
Spedon
2023-03-14 23:31:20 +08:00
parent 37d62f85fb
commit 81477f0ed8
3 changed files with 70 additions and 27 deletions

View File

@@ -1,14 +1,14 @@
import {
delay,
removeAllEventListeners,
layersPosSet,
layersStyleSet,
center,
createImgElement,
calcImageIndex,
FIFO
} from './utils'
import {
posArray,
layersStyleArray,
layers,
handleOnMove,
globalIndex,
@@ -64,7 +64,7 @@ export function overlayDisable(): void {
// handle close click
async function handleCloseClick(): Promise<void> {
overlayDisable()
layersPosSet(posArray, layers)
layersStyleSet(layersStyleArray, layers, true, false)
for (let i: number = 4; i >= 0; i--) {
layers[i].dataset.status = `r${4 - i}`
}
@@ -72,20 +72,21 @@ async function handleCloseClick(): Promise<void> {
for (let i: number = 4; i >= 0; i--) {
layers[i].dataset.status = 'null'
}
layersStyleSet(layersStyleArray, layers, false, true)
window.addEventListener('mousemove', handleOnMove)
}
function handlePrevClick(): void {
globalIndexDec()
const imgIndex = calcImageIndex(globalIndex, imagesArrayLen)
FIFO(createImgElement(imagesArray[imgIndex]), layers)
FIFO(createImgElement(imagesArray[imgIndex], false).image, layers)
imgIndexSpanUpdate(imgIndex + 1, imagesArrayLen)
}
function handleNextClick(): void {
globalIndexInc()
const imgIndex = calcImageIndex(globalIndex, imagesArrayLen)
FIFO(createImgElement(imagesArray[imgIndex]), layers)
FIFO(createImgElement(imagesArray[imgIndex], false).image, layers)
imgIndexSpanUpdate(imgIndex + 1, imagesArrayLen)
}

View File

@@ -1,17 +1,19 @@
import { overlayEnable } from './overlay'
import {
posCache,
styleCache,
FIFO,
layersPosSet,
layersStyleSet,
center,
type position,
createImgElement,
calcImageIndex,
delay
delay,
type imgElement
} from './utils'
import { thresholdSensitivityArray, thresholdIndex } from './thresholdCtl'
import { imgIndexSpanUpdate } from './indexDisp'
import { imagesArrayLen, imagesArray } from './dataFetch'
import { preloader } from './imageCache'
// get layer divs
export const layers: HTMLDivElement[] = [
@@ -23,9 +25,10 @@ export const layers: HTMLDivElement[] = [
]
// layers position caching
export const posArray: string[][] = [
export const layersStyleArray: string[][] = [
['0px', '0px', '0px', '0px', '0px'],
['0px', '0px', '0px', '0px', '0px']
['0px', '0px', '0px', '0px', '0px'],
['', '', '', '', '']
]
// global index for "activated"
@@ -36,9 +39,10 @@ let last: position = { x: 0, y: 0 }
// activate top image
const activate = (index: number, x: number, y: number): void => {
posCache(x, y, posArray)
layersPosSet(posArray, layers)
FIFO(createImgElement(imagesArray[index]), layers)
const imgElem: imgElement = createImgElement(imagesArray[index], true)
styleCache(x, y, imgElem.bgStyle, layersStyleArray)
layersStyleSet(layersStyleArray, layers)
FIFO(imgElem.image, layers)
last = { x, y }
}
@@ -60,11 +64,14 @@ export const handleOnMove = (e: MouseEvent): void => {
activate(imageIndex, e.clientX, e.clientY)
imgIndexSpanUpdate(imageIndex + 1, imagesArrayLen)
// self increment
globalIndex++
globalIndexInc()
}
}
async function enterOverlay(): Promise<void> {
layers[4].style.backgroundImage = ''
const topLayerImage = layers[4].lastElementChild as HTMLImageElement
topLayerImage.style.transition = ''
// stop images animation
window.removeEventListener('mousemove', handleOnMove)
// set top image
@@ -95,8 +102,10 @@ export function trackMouseInit(): void {
export function globalIndexDec(): void {
globalIndex--
preloader(globalIndex)
}
export function globalIndexInc(): void {
globalIndex++
preloader(globalIndex)
}

View File

@@ -3,6 +3,8 @@ export interface ImageData {
url: string
imgH: string
imgW: string
pColor: string
sColor: string
}
export interface position {
@@ -10,14 +12,26 @@ export interface position {
y: number
}
export interface imgElement {
image: HTMLImageElement
bgStyle: string
}
// cache a xy position to array
export const posCache = (x: number, y: number, xyArray: string[][]): void => {
export const styleCache = (
x: number,
y: number,
bg: string,
styleArray: string[][]
): void => {
// pop element if length surpass limitation
xyArray[0].shift()
xyArray[1].shift()
styleArray[0].shift()
styleArray[1].shift()
styleArray[2].shift()
// push new element
xyArray[0].push(`${x}px`)
xyArray[1].push(`${y}px`)
styleArray[0].push(`${x}px`)
styleArray[1].push(`${y}px`)
styleArray[2].push(bg)
}
// 0 to 0001, 25 to 0025
@@ -47,13 +61,18 @@ export const FIFO = (
}
// set position for 5 image display layers
export const layersPosSet = (
xyArray: string[][],
layersArray: HTMLDivElement[]
export const layersStyleSet = (
styleArray: string[][],
layersArray: HTMLDivElement[],
posOut: boolean = true,
styleOut: boolean = true
): void => {
function posSet(layer: HTMLDivElement, index: number): void {
layer.style.left = xyArray[0][index]
layer.style.top = xyArray[1][index]
if (posOut) {
layer.style.left = styleArray[0][index]
layer.style.top = styleArray[1][index]
}
if (styleOut) layer.style.backgroundImage = styleArray[2][index]
}
for (let i = 4; i >= 0; i--) {
posSet(layersArray[i], i)
@@ -80,13 +99,22 @@ export const center = (e: HTMLDivElement): void => {
}
}
export function createImgElement(input: ImageData): HTMLImageElement {
export function createImgElement(input: ImageData, returnBgStyle: boolean): imgElement {
const img = document.createElement('img')
img.setAttribute('src', input.url)
img.setAttribute('alt', input.index)
img.setAttribute('alt', '')
img.setAttribute('height', input.imgH)
img.setAttribute('width', input.imgW)
return img
img.setAttribute('loading', 'eager')
img.style.opacity = '0'
img.onload = async () => {
img.style.opacity = '1'
img.style.transition = 'opacity 0.5s ease-in'
await delay(500)
img.style.transition = ''
}
const style: string = `linear-gradient(15deg, ${input.pColor}, ${input.sColor})`
return returnBgStyle ? { image: img, bgStyle: style } : { image: img, bgStyle: '' }
}
export function calcImageIndex(index: number, imgCounts: number): number {
@@ -96,3 +124,8 @@ export function calcImageIndex(index: number, imgCounts: number): number {
return (imgCounts + (index % imgCounts)) % imgCounts
}
}
export function preloadImage(src: string): void {
const cache = new Image()
cache.src = src
}