This commit is contained in:
2026-05-23 17:17:56 -07:00
commit 448f2e33ef
135 changed files with 11817 additions and 0 deletions
+106
View File
@@ -0,0 +1,106 @@
:root {
--animation-transition: 200ms;
--border-thickness: 2px;
--background-tertiary: hsl(0, 0%, 0%);
--background-secondary: hsl(0, 0%, 16%);
--background-primary: hsl(0, 0%, 32%);
--font-color-accent: hsl(0, 50%, 80%);
--font-color-primary: hsl(0, 0%, 95%);
--font-color-secondary: hsl(0, 0%, 65%);
}
html,
body {
box-sizing: border-box;
margin: 0;
background: transparent;
padding: 0;
overflow: hidden;
}
.effect-centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
a.layout-wrapper {
display: inline-block;
position: relative;
cursor: pointer;
width: 100vw;
height: 100vh;
overflow: hidden;
}
a.layout-wrapper img.watermark {
position: absolute;
right: 16px;
bottom: 16px;
opacity: 0.8;
transition: var(--animation-transition) ease-in-out opacity;
height: 4vw;
min-height: 20px;
}
a.layout-wrapper:hover img.watermark,
a.layout-wrapper:focus-visible img.watermark {
opacity: 1;
}
/* Layout: Error */
a.layout-wrapper div.error {
box-sizing: border-box;
border: var(--border-thickness) solid var(--background-primary);
background-image:
repeating-linear-gradient(
45deg,
transparent,
transparent 8px,
var(--background-secondary) 8px,
var(--background-secondary) 9px
),
repeating-linear-gradient(
-45deg,
transparent,
transparent 8px,
var(--background-secondary) 8px,
var(--background-secondary) 9px
);
background-color: var(--background-tertiary);
width: 100%;
height: 100%;
}
a.layout-wrapper div.error p {
border: var(--border-thickness) solid var(--background-primary);
background-color: var(--background-tertiary);
padding: 16px 32px;
width: fit-content;
color: var(--font-color-primary);
font-size: large;
font-family: monospace;
text-align: center;
}
/* Layout: Canvas */
a.layout-wrapper video.decoder {
position: absolute;
visibility: hidden;
}
a.layout-wrapper canvas.render {
width: 100%;
height: 100%;
object-fit: contain;
}
/* Layout: Image */
a.layout-wrapper img.render {
width: 100%;
height: 100%;
object-fit: contain;
}
+269
View File
@@ -0,0 +1,269 @@
;(() => {
let defer: (() => void)[] = []
let running = false
let paramQuality: 'standard' | 'transparent'
let paramID: bigint
const elemHost = document.querySelector<HTMLAnchorElement>('a.layout-wrapper')
// @ts-expect-error
const BASE_CDN = window.__ENV__.CDN
// @ts-expect-error
const BASE_WEB = window.__ENV__.WEB
if (BASE_CDN === undefined || BASE_WEB === undefined || !elemHost) {
console.error('[gifuu] Invalid Document')
return
}
try {
const search = new URLSearchParams(window.location.search)
const givenQuality = search.get('quality')
const givenID = BigInt(search.get('id') ?? '0')
if (givenID < 1) {
return exit('Invalid ID')
}
if (givenQuality !== 'standard' && givenQuality !== 'transparent') {
return exit('Invalid Quality')
}
paramQuality = givenQuality
paramID = givenID
} catch (error) {
exit(error)
return
}
function setupGL() {
if (!elemHost) throw 'Missing Anchor Node'
// Setup Elements
const elemCanvas = document.createElement('canvas')
elemCanvas.classList.add('render')
elemCanvas.addEventListener('webglcontextlost', (ev) => {
ev.preventDefault()
console.warn('[gifuu] Failed to allocate a WebGL context for us! Using image fallback...')
teardown()
setupImage()
})
elemHost.appendChild(elemCanvas)
defer.push(() => elemCanvas.remove())
const elemVideo = document.createElement('video')
elemVideo.classList.add('decode')
elemVideo.crossOrigin = 'anonymous'
elemVideo.playsInline = true
elemVideo.autoplay = true
elemVideo.muted = true
elemVideo.loop = true
elemHost.appendChild(elemVideo)
defer.push(() => elemVideo.remove())
// Setup Context
const gl = elemCanvas.getContext('webgl', {
powerPreference: 'low-power',
premultipliedAlpha: false,
antialias: false,
alpha: true,
depth: false,
})
if (!gl) {
console.warn('[gifuu] WebGL is unsupported, using image fallback...')
teardown()
setupImage()
return
}
try {
const VERT = `
precision mediump float;
attribute vec2 aPos;
uniform mat3 uMatrix;
varying vec2 vUV;
void main() {
gl_Position = vec4(uMatrix * vec3(aPos, 1.0), 1.0);
vUV = aPos;
}`
const FRAG = `
precision mediump float;
uniform sampler2D uFrame;
varying vec2 vUV;
void main() {
vec2 colorUV = vec2(vUV.x, vUV.y * 0.5);
vec2 alphaUV = vec2(vUV.x, 0.5 + vUV.y * 0.5);
vec4 color = texture2D(uFrame, colorUV);
float alpha = texture2D(uFrame, alphaUV).r;
gl_FragColor = vec4(color.rgb, alpha);
}`
function compileShader(type: number, src: string) {
if (!gl) throw 'Missing GL Context'
const s = gl.createShader(type)
if (!s) throw 'Shader compilation failed'
gl.shaderSource(s, src)
gl.compileShader(s)
return s
}
const prog = gl.createProgram()
gl.attachShader(prog, compileShader(gl.VERTEX_SHADER, VERT))
gl.attachShader(prog, compileShader(gl.FRAGMENT_SHADER, FRAG))
gl.linkProgram(prog)
gl.useProgram(prog)
defer.push(() => gl.deleteProgram(prog))
// --- Quad ---
const buf = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buf)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1]), gl.STATIC_DRAW)
defer.push(() => gl.deleteBuffer(buf))
const aPos = gl.getAttribLocation(prog, 'aPos')
gl.enableVertexAttribArray(aPos)
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0)
gl.uniformMatrix3fv(gl.getUniformLocation(prog, 'uMatrix'), false, [2, 0, 0, 0, -2, 0, -1, 1, 1])
// --- Texture ---
const tex = gl.createTexture()
gl.bindTexture(gl.TEXTURE_2D, tex)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
gl.uniform1i(gl.getUniformLocation(prog, 'uFrame'), 0)
defer.push(() => gl.deleteTexture(tex))
} catch (error) {
console.error('[gifuu] Failed to Initialize WebGL dependencies:', error)
teardown()
setupImage()
return
}
// Tick Function
let cancel = 0
let sized = false
function tick() {
cancel = requestAnimationFrame(tick)
try {
if (!gl) throw 'Missing GL Context'
if (!sized && elemVideo.videoWidth > 0) {
sized = true
elemCanvas.width = elemVideo.videoWidth
elemCanvas.height = Math.floor(elemVideo.videoHeight / 2)
gl.viewport(0, 0, elemCanvas.width, elemCanvas.height)
}
if (!sized) return
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, elemVideo)
gl.drawArrays(gl.TRIANGLES, 0, 6)
} catch (error) {
console.warn('[gifuu] Draw failed, using image fallback...', error)
teardown()
setupImage()
return
}
}
defer.push(() => cancelAnimationFrame(cancel))
// Download Video
fetch(`${BASE_CDN}/${paramID}/alpha.webm`, { mode: 'cors', cache: 'force-cache' })
.then((r) => r.blob())
.then((blob) => {
const content = URL.createObjectURL(blob)
defer.push(() => URL.revokeObjectURL(content))
elemVideo.src = content
elemVideo.play().catch(() => {})
tick()
})
.catch((error) => {
console.warn('[gifuu] Video download failed, using image fallback...', error)
teardown()
setupImage()
})
}
function setupImage() {
if (!elemHost) throw 'Missing Image Node'
// Create Element
const elemImage = document.createElement('img')
elemImage.classList.add('render')
elemHost.appendChild(elemImage)
defer.push(() => elemImage.remove())
// Download Image
fetch(`${BASE_CDN}/${paramID}/${paramQuality}.avif`, { mode: 'cors', cache: 'force-cache' })
.then((r) => r.blob())
.then((blob) => {
const content = URL.createObjectURL(blob)
defer.push(() => URL.revokeObjectURL(content))
elemImage.src = content
})
.catch((error) => {
console.warn('[gifuu] Image download failed, quitting...', error)
teardown()
exit('Media Unavailable')
})
}
function teardown() {
let func
while ((func = defer.shift())) {
try {
func()
} catch (error) {
console.error('[gifuu] Teardown failed:', error)
}
}
}
function exit(error: any) {
console.error('[gifuu] Exiting Embed:', error)
teardown()
if (!elemHost) return
elemHost.href = BASE_WEB
const container = document.createElement('div')
container.classList.add('error')
const message = document.createElement('p')
message.classList.add('message', 'effect-centered')
message.textContent = String(error)
container.append(message)
elemHost.append(container)
}
// Lifecycle
elemHost.href = `${BASE_WEB}/art/${paramID}`
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && !running) {
running = true
console.log('[gifuu] Showtime! Setting up...')
paramQuality === 'transparent' ? setupGL() : setupImage()
} else if (!entries[0].isIntersecting && running) {
running = false
console.log('[gifuu] Out of View! Tearing down...')
teardown()
}
},
{ threshold: 0.1 },
)
observer.observe(elemHost)
window.addEventListener('pagehide', () => {
console.log('[gifuu] Goodbye!')
observer.disconnect()
elemHost.remove()
teardown()
})
})()