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:
@@ -35,9 +35,12 @@
|
|||||||
|
|
||||||
// 默认参数
|
// 默认参数
|
||||||
const defaults = {
|
const defaults = {
|
||||||
threshold: 8,
|
threshold: 30,
|
||||||
softness: 10,
|
softness: 10,
|
||||||
leftMargin: 0,
|
// leftMargin: 0,
|
||||||
|
// topOffset: -200,
|
||||||
|
// scalePercent: 125
|
||||||
|
leftMargin: 600,
|
||||||
topOffset: -200,
|
topOffset: -200,
|
||||||
scalePercent: 125,
|
scalePercent: 125,
|
||||||
rotationDeg: 0,
|
rotationDeg: 0,
|
||||||
@@ -151,7 +154,7 @@
|
|||||||
|
|
||||||
// 载入背景图(使用背景图做最终合成;如果你希望使用 CSS 背景而不是图片文件,可改这里)
|
// 载入背景图(使用背景图做最终合成;如果你希望使用 CSS 背景而不是图片文件,可改这里)
|
||||||
const bgImg = new Image();
|
const bgImg = new Image();
|
||||||
bgImg.src = "background.png";
|
bgImg.src = "../assets/background.png";
|
||||||
bgImg.onload = () => {
|
bgImg.onload = () => {
|
||||||
// 等背景加载后设置主 canvas 大小
|
// 等背景加载后设置主 canvas 大小
|
||||||
const w = bgImg.naturalWidth || 1080;
|
const w = bgImg.naturalWidth || 1080;
|
||||||
@@ -223,19 +226,38 @@
|
|||||||
const threshold = THRESHOLD;
|
const threshold = THRESHOLD;
|
||||||
const softness = Math.max(1, SOFTNESS);
|
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) {
|
for (let i = 0; i < len; i += 4) {
|
||||||
const r = data[i],
|
const r = data[i];
|
||||||
g = data[i + 1],
|
const g = data[i + 1];
|
||||||
b = data[i + 2];
|
const b = data[i + 2];
|
||||||
const lum = (r + g + b) / 3;
|
|
||||||
if (lum < threshold) {
|
// “绿色程度”与“非绿色程度”的差距
|
||||||
data[i + 3] = 0;
|
const greenDiff = g - Math.max(r, b);
|
||||||
} else if (lum < threshold + softness) {
|
|
||||||
const t = (lum - threshold) / softness;
|
// 以 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);
|
data[i + 3] = Math.round(255 * t);
|
||||||
} // else keep alpha
|
} // 其他保持原样
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxTemp.putImageData(img, 0, 0);
|
ctxTemp.putImageData(img, 0, 0);
|
||||||
processed = true;
|
processed = true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -6,24 +6,100 @@
|
|||||||
<title>Canvas 实时抠像(可控面板)</title>
|
<title>Canvas 实时抠像(可控面板)</title>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||||
<style type="text/tailwindcss">
|
<style type="text/tailwindcss">
|
||||||
@import "tailwindcss";
|
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
|
/* 🎨 定义自定义字体族变量 */
|
||||||
|
--font-bai-ge: "BaiGeTianXing", sans-serif;
|
||||||
|
--font-gu-huang: "ShangShouGuHuang", sans-serif;
|
||||||
|
--font-tang-ying: "YeZiTangYingHei", sans-serif;
|
||||||
|
|
||||||
--color-default: #4f46e5;
|
--color-default: #4f46e5;
|
||||||
--color-success: #10b981;
|
--color-success: #10b981;
|
||||||
--color-warning: #f59e0b;
|
--color-warning: #f59e0b;
|
||||||
--color-danger: #ef4444;
|
--color-danger: #ef4444;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "BaiGeTianXing";
|
||||||
|
src: url("../fonts/字魂白鸽天行体.ttf") format("truetype");
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "ShangShouGuHuang";
|
||||||
|
src: url("../fonts/ShangShouGuHuangTi-2.ttf") format("truetype");
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "YeZiTangYingHei";
|
||||||
|
src: url("../fonts/YeZiGongChangTangYingHei-2.ttf") format("truetype");
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
canvas#mainCanvas {
|
canvas#mainCanvas {
|
||||||
image-rendering: optimizeQuality;
|
image-rendering: optimizeQuality;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="min-h-screen flex items-center content-center">
|
<body class="min-h-screen flex items-center justify-center bg-black text-white">
|
||||||
<div class="stage" id="stage" class="relative w-full overflow-hidden">
|
<div class="stage relative w-full h-screen overflow-hidden">
|
||||||
<canvas id="mainCanvas" class="block w-full h-auto"></canvas>
|
<canvas id="mainCanvas" class="block w-full h-auto"></canvas>
|
||||||
|
|
||||||
|
<!-- 标题 -->
|
||||||
|
<h1 class="absolute top-4 text-center w-full font-bai-ge text-8xl text-yellow-300">
|
||||||
|
永平赵子龙庙
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<!-- 副标题描边层 -->
|
||||||
|
<h2
|
||||||
|
class="absolute top-28 w-full text-center font-bai-ge text-6xl text-transparent [-webkit-text-stroke:4px_yellow]"
|
||||||
|
>
|
||||||
|
庆祝赵子龙元帅暨众神圣诞千秋
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<!-- 副标题实色层 -->
|
||||||
|
<h2 class="absolute top-28 text-center w-full font-bai-ge text-6xl text-red-500">
|
||||||
|
庆祝赵子龙元帅暨众神圣诞千秋
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<!-- 四句诗边框容器 -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 flex items-center justify-between px-32 pointer-events-none"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
class="font-gu-huang text-7xl leading-loose text-center text-transparent
|
||||||
|
[writing-mode:vertical-lr] [text-orientation:upright]
|
||||||
|
[-webkit-text-stroke:8px_black]"
|
||||||
|
>
|
||||||
|
血染征袍透甲红<br>当阳谁敢与争锋
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p
|
||||||
|
class="font-gu-huang text-7xl leading-loose text-center text-transparent
|
||||||
|
[writing-mode:vertical-rl] [text-orientation:upright]
|
||||||
|
[-webkit-text-stroke:8px_black]"
|
||||||
|
>
|
||||||
|
古来冲锋扶危主<br>唯有常山赵子龙
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- 四句诗容器 -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 flex items-center justify-between px-32 pointer-events-none"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
class="font-gu-huang text-7xl leading-loose text-center text-white
|
||||||
|
[writing-mode:vertical-lr] [text-orientation:upright]"
|
||||||
|
>
|
||||||
|
血染征袍透甲红<br>当阳谁敢与争锋
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p
|
||||||
|
class="font-gu-huang text-7xl leading-loose text-center text-white
|
||||||
|
[writing-mode:vertical-rl] [text-orientation:upright]"
|
||||||
|
>
|
||||||
|
古来冲锋扶危主<br>唯有常山赵子龙
|
||||||
|
</p>
|
||||||
|
|
||||||
<!-- 来源资源:替换为你自己的文件,若跨域请加 crossorigin="anonymous" 并确保服务器允许 CORS -->
|
<!-- 来源资源:替换为你自己的文件,若跨域请加 crossorigin="anonymous" 并确保服务器允许 CORS -->
|
||||||
<video
|
<video
|
||||||
id="video"
|
id="video"
|
||||||
@@ -32,7 +108,7 @@
|
|||||||
muted
|
muted
|
||||||
loop
|
loop
|
||||||
autoplay
|
autoplay
|
||||||
src="赵子龙元帅-竖屏.mp4"
|
src="../assets/赵云绿幕.mp4"
|
||||||
></video>
|
></video>
|
||||||
|
|
||||||
<!-- Controls 面板(可关闭) -->
|
<!-- Controls 面板(可关闭) -->
|
||||||
|
|||||||
3
20251012/sponsor-list/main.css
Normal file
3
20251012/sponsor-list/main.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user