feat(sponsor-list): implement green screen keying and themed layout

This commit overhauls the display page by replacing the luminance-based keying with a more robust chroma key (green
screen) algorithm for cleaner video cutouts.

A new visual theme has been implemented, featuring:
- Custom fonts for titles and poems.
- A main title, subtitle, and vertical poems styled with Tailwind CSS.
- Reorganization of assets into dedicated `assets` and `fonts` directories.
- Updated video source to a green screen version and adjusted canvas parameters accordingly.
This commit is contained in:
xiaomai
2025-10-12 14:00:01 +08:00
parent 02065d9c63
commit ea4ccec42d
3 changed files with 120 additions and 19 deletions

View File

@@ -35,9 +35,12 @@
// 默认参数
const defaults = {
threshold: 8,
threshold: 30,
softness: 10,
leftMargin: 0,
// leftMargin: 0,
// topOffset: -200,
// scalePercent: 125
leftMargin: 600,
topOffset: -200,
scalePercent: 125,
rotationDeg: 0,
@@ -151,7 +154,7 @@
// 载入背景图(使用背景图做最终合成;如果你希望使用 CSS 背景而不是图片文件,可改这里)
const bgImg = new Image();
bgImg.src = "background.png";
bgImg.src = "../assets/background.png";
bgImg.onload = () => {
// 等背景加载后设置主 canvas 大小
const w = bgImg.naturalWidth || 1080;
@@ -223,19 +226,38 @@
const threshold = THRESHOLD;
const softness = Math.max(1, SOFTNESS);
// 基于平均亮度的简单抠像:黑色 -> 透明
// // 基于平均亮度的简单抠像:黑色 -> 透明
// for (let i = 0; i < len; i += 4) {
// const r = data[i],
// g = data[i + 1],
// b = data[i + 2];
// const lum = (r + g + b) / 3;
// if (lum < threshold) {
// data[i + 3] = 0;
// } else if (lum < threshold + softness) {
// const t = (lum - threshold) / softness;
// data[i + 3] = Math.round(255 * t);
// } // else keep alpha
// }
// 基于绿色背景的抠像Green Screen / Chroma Key
for (let i = 0; i < len; i += 4) {
const r = data[i],
g = data[i + 1],
b = data[i + 2];
const lum = (r + g + b) / 3;
if (lum < threshold) {
data[i + 3] = 0;
} else if (lum < threshold + softness) {
const t = (lum - threshold) / softness;
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
// “绿色程度”与“非绿色程度”的差距
const greenDiff = g - Math.max(r, b);
// 以 threshold / softness 控制去除强度和平滑边缘
if (greenDiff > threshold) {
data[i + 3] = 0; // 透明
} else if (greenDiff > threshold - softness) {
const t = (threshold - greenDiff) / softness;
data[i + 3] = Math.round(255 * t);
} // else keep alpha
} // 其他保持原样
}
ctxTemp.putImageData(img, 0, 0);
processed = true;
} catch (err) {