返回 Pixelle-Video
video_default.html
根目录 / templates / 1080x1920 / video_default.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 <meta name="template:media-width" content="512">
6 <meta name="template:media-height" content="288">
7 <style>
8 html {
9 margin: 0;
10 padding: 0;
11 height: 100%;
12 }
13
14 body {
15 margin: 0;
16 padding: 0;
17 width: 100%;
18 height: 100vh;
19 font-family: 'PingFang SC', 'Source Han Sans', 'Microsoft YaHei', sans-serif;
20 overflow: hidden;
21 /* background-color: #000; */
22 display: flex;
23 justify-content: center;
24 align-items: center;
25 }
26
27 /* 主容器 - 居中并包含所有内容 */
28 .main-container {
29 position: relative;
30 width: 1080px;
31 height: 1920px;
32 }
33
34 /* Background image layer (customizable using <img> tag) */
35 .background-image {
36 position: absolute;
37 top: 0;
38 left: 0;
39 width: 100%;
40 height: 100%;
41 z-index: 0;
42 }
43
44 /* Video overlay - 相对于main-container居中 */
45 .video-overlay {
46 position: absolute;
47 top: 50%;
48 left: 50%;
49 transform: translate(-50%, -50%);
50 width: 1080px;
51 height: 607px;
52 /* background: #f00; */
53 z-index: 1;
54 }
55
56 /* Title section - positioned above video */
57 .video-title-wrapper {
58 position: absolute;
59 top: calc(50% - 607px / 2 - 130px);
60 left: 50%;
61 transform: translateX(-50%);
62 z-index: 2;
63 }
64
65 .video-title {
66 width: 900px;
67 text-align: center;
68 /* 初始字体大小,JavaScript 会根据文本长度自动调整 */
69 font-size: 72px;
70 font-weight: 700;
71 color: #ffffff;
72 line-height: 1.3;
73 letter-spacing: 3px;
74 text-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
75 margin-bottom: 20px;
76 /* 确保文本不会溢出 */
77 word-wrap: break-word;
78 overflow-wrap: break-word;
79 white-space: nowrap;
80 }
81
82 /* 字幕区域 - 对齐视频底部 */
83 .content {
84 position: absolute;
85 bottom: calc(50% - 607px / 2 + 0px);
86 left: 50%;
87 transform: translateX(-50%);
88 width: 900px;
89 z-index: 4;
90 }
91
92 .text {
93 font-size: 40px;
94 color: #ffffff;
95 text-align: center;
96 line-height: 1.6;
97 font-weight: 500;
98 text-shadow:
99 2px 2px 4px rgba(0, 0, 0, 0.9),
100 0 0 8px rgba(0, 0, 0, 0.8),
101 0 0 16px rgba(0, 0, 0, 0.6);
102 padding: 10px 0px;
103 /* background-color: aqua; */
104 }
105
106 /* Footer - positioned below video */
107 .footer {
108 position: absolute;
109 top: calc(50% + 607px / 2 + 50px);
110 left: 50%;
111 transform: translateX(-50%);
112 width: 900px;
113 display: flex;
114 align-items: center;
115 justify-content: space-between;
116 padding-top: 40px;
117 border-top: 2px solid rgba(255, 255, 255, 0.3);
118 z-index: 2;
119 }
120
121 .author-section {
122 display: flex;
123 flex-direction: column;
124 gap: 8px;
125 }
126
127 .author {
128 font-size: 32px;
129 font-weight: 600;
130 color: #ffffff;
131 text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
132 }
133
134 .author-desc {
135 font-size: 24px;
136 color: rgba(255, 255, 255, 0.9);
137 font-weight: 400;
138 }
139
140 .logo-section {
141 display: flex;
142 flex-direction: column;
143 align-items: flex-end;
144 gap: 10px;
145 }
146
147 .logo {
148 font-size: 28px;
149 font-weight: 600;
150 color: #ffffff;
151 letter-spacing: 2px;
152 text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
153 }
154 </style>
155 </head>
156 <body>
157 <!-- 主容器 - 所有元素都在这里面,相对于video-overlay定位 -->
158 <div class="main-container">
159 <!-- Background image layer (customizable via background parameter) -->
160 <div class="background-image">
161
162 </div>
163
164 <!-- Video overlay - 居中参考点 -->
165 <div class="video-overlay"></div>
166
167 <!-- Video title - positioned above video -->
168 <div class="video-title-wrapper">
169 <div class="video-title">{{title}}</div>
170 </div>
171
172 <!-- 字幕区域 - 独立定位在视频底部 -->
173 <div class="content">
174 <div class="text">{{text}}</div>
175 </div>
176
177 <!-- Footer - positioned below video -->
178 <div class="footer">
179 <div class="author-section">
180 <div class="author">{{author=@Pixelle.AI}}</div>
181 <div class="author-desc">{{describe=Open Source Omnimodal AI Creative Agent}}</div>
182 </div>
183 <div class="logo-section">
184 <div class="logo">{{brand=Pixelle-Video}}</div>
185 </div>
186 </div>
187 </div>
188
189 <script>
190 /**
191 * 根据文本宽度自动调整字体大小
192 * @param {HTMLElement} element - 要调整的元素
193 * @param {number} maxWidth - 最大宽度(px)
194 * @param {number} minFontSize - 最小字体大小(px)
195 * @param {number} maxFontSize - 最大字体大小(px)
196 */
197 function autoFitFontSize(element, maxWidth, minFontSize, maxFontSize) {
198 try {
199 if (!element || !element.textContent || !element.textContent.trim()) {
200 return;
201 }
202
203 if (!document.body) {
204 return;
205 }
206
207 // 创建一个临时的测量元素
208 const measure = document.createElement('span');
209 measure.style.visibility = 'hidden';
210 measure.style.position = 'absolute';
211 measure.style.top = '-9999px';
212 measure.style.left = '-9999px';
213 measure.style.whiteSpace = 'nowrap';
214
215 // 复制元素的样式
216 const computedStyle = window.getComputedStyle(element);
217 measure.style.fontFamily = computedStyle.fontFamily;
218 measure.style.fontSize = computedStyle.fontSize;
219 measure.style.fontWeight = computedStyle.fontWeight;
220 measure.style.letterSpacing = computedStyle.letterSpacing;
221 measure.textContent = element.textContent;
222
223 document.body.appendChild(measure);
224
225 // 二分查找合适的字体大小
226 let low = minFontSize;
227 let high = maxFontSize;
228 let bestSize = maxFontSize;
229
230 // 先检查最大字体是否合适
231 measure.style.fontSize = maxFontSize + 'px';
232 if (measure.offsetWidth <= maxWidth) {
233 bestSize = maxFontSize;
234 } else {
235 // 使用二分查找
236 while (high - low > 0.5) {
237 const mid = (low + high) / 2;
238 measure.style.fontSize = mid + 'px';
239
240 if (measure.offsetWidth <= maxWidth) {
241 bestSize = mid;
242 low = mid;
243 } else {
244 high = mid;
245 }
246 }
247 }
248
249 // 应用找到的字体大小
250 element.style.fontSize = bestSize + 'px';
251
252 // 清理临时元素
253 if (measure.parentNode) {
254 document.body.removeChild(measure);
255 }
256 } catch (error) {
257 console.error('自动调整字体大小出错:', error);
258 }
259 }
260
261 // 页面加载完成后自动调整字体大小
262 function initAutoFit() {
263 try {
264 const titleElement = document.querySelector('.video-title');
265 if (titleElement) {
266 // 获取容器的实际宽度
267 const wrapper = document.querySelector('.video-title-wrapper');
268 const maxWidth = wrapper ? wrapper.offsetWidth : 900;
269
270 // 自动调整字体大小:最小12px,最大72px
271 autoFitFontSize(titleElement, maxWidth, 12, 72);
272 }
273 } catch (error) {
274 console.error('初始化自动调整字体大小出错:', error);
275 }
276 }
277
278 // 等待 DOM 加载完成
279 if (document.readyState === 'loading') {
280 document.addEventListener('DOMContentLoaded', initAutoFit);
281 } else {
282 // DOM 已经加载完成
283 initAutoFit();
284 }
285
286 // 如果内容是通过模板引擎动态插入的,可以监听内容变化
287 // 使用 MutationObserver 监听文本变化
288 if (typeof MutationObserver !== 'undefined') {
289 try {
290 const observer = new MutationObserver(function(mutations) {
291 let shouldUpdate = false;
292 mutations.forEach(function(mutation) {
293 if (mutation.type === 'childList' || mutation.type === 'characterData') {
294 shouldUpdate = true;
295 }
296 });
297
298 if (shouldUpdate) {
299 // 延迟执行,避免频繁调用
300 setTimeout(initAutoFit, 100);
301 }
302 });
303
304 // 等待 body 元素存在后再观察
305 if (document.body) {
306 observer.observe(document.body, {
307 childList: true,
308 subtree: true,
309 characterData: true
310 });
311 } else {
312 document.addEventListener('DOMContentLoaded', function() {
313 if (document.body) {
314 observer.observe(document.body, {
315 childList: true,
316 subtree: true,
317 characterData: true
318 });
319 }
320 });
321 }
322 } catch (error) {
323 console.error('设置 MutationObserver 出错:', error);
324 }
325 }
326 </script>
327 </body>
328 </html>
328 lines HTML