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

View File

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

View File

@@ -3,6 +3,8 @@ export interface ImageData {
url: string url: string
imgH: string imgH: string
imgW: string imgW: string
pColor: string
sColor: string
} }
export interface position { export interface position {
@@ -10,14 +12,26 @@ export interface position {
y: number y: number
} }
export interface imgElement {
image: HTMLImageElement
bgStyle: string
}
// cache a xy position to array // 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 // pop element if length surpass limitation
xyArray[0].shift() styleArray[0].shift()
xyArray[1].shift() styleArray[1].shift()
styleArray[2].shift()
// push new element // push new element
xyArray[0].push(`${x}px`) styleArray[0].push(`${x}px`)
xyArray[1].push(`${y}px`) styleArray[1].push(`${y}px`)
styleArray[2].push(bg)
} }
// 0 to 0001, 25 to 0025 // 0 to 0001, 25 to 0025
@@ -47,13 +61,18 @@ export const FIFO = (
} }
// set position for 5 image display layers // set position for 5 image display layers
export const layersPosSet = ( export const layersStyleSet = (
xyArray: string[][], styleArray: string[][],
layersArray: HTMLDivElement[] layersArray: HTMLDivElement[],
posOut: boolean = true,
styleOut: boolean = true
): void => { ): void => {
function posSet(layer: HTMLDivElement, index: number): void { function posSet(layer: HTMLDivElement, index: number): void {
layer.style.left = xyArray[0][index] if (posOut) {
layer.style.top = xyArray[1][index] 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--) { for (let i = 4; i >= 0; i--) {
posSet(layersArray[i], 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') const img = document.createElement('img')
img.setAttribute('src', input.url) img.setAttribute('src', input.url)
img.setAttribute('alt', input.index) img.setAttribute('alt', '')
img.setAttribute('height', input.imgH) img.setAttribute('height', input.imgH)
img.setAttribute('width', input.imgW) 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 { 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 return (imgCounts + (index % imgCounts)) % imgCounts
} }
} }
export function preloadImage(src: string): void {
const cache = new Image()
cache.src = src
}