|
7 | 7 | <link rel="manifest" href="/manifest.json" /> |
8 | 8 | <title>WebGAL</title> |
9 | 9 | <style> |
| 10 | + html, |
10 | 11 | body { |
| 12 | + margin: 0; |
11 | 13 | background: black; |
| 14 | + width: 100%; |
| 15 | + height: 100%; |
| 16 | + overflow: hidden; |
12 | 17 | } |
13 | 18 |
|
14 | 19 | .html-body__effect-background { |
|
129 | 134 | .title-enter-container__link-to-github > div { |
130 | 135 | padding: 0 0 0.25em 0; |
131 | 136 | } |
| 137 | + |
132 | 138 | </style> |
133 | 139 | </head> |
134 | 140 | <body> |
|
153 | 159 | <div id="html-body__panic-overlay"></div> |
154 | 160 | <!-- 应用挂载点 --> |
155 | 161 | <div id="root"></div> |
| 162 | + <script> |
| 163 | + (() => { |
| 164 | + const userAgent = navigator.userAgent || ''; |
| 165 | + const platform = navigator.userAgentData?.platform || navigator.platform || ''; |
| 166 | + const maxTouchPoints = navigator.maxTouchPoints || 0; |
| 167 | + const isIOSPhone = /iPhone|iPod/i.test(userAgent); |
| 168 | + const isIPad = /iPad/i.test(userAgent) || (/Mac/i.test(platform) && maxTouchPoints > 1); |
| 169 | + |
| 170 | + window.__WEBGAL_DEVICE_INFO__ = { |
| 171 | + isIOS: isIOSPhone || isIPad, |
| 172 | + isIOSPhone, |
| 173 | + isIPad, |
| 174 | + }; |
| 175 | + })(); |
| 176 | + </script> |
156 | 177 | <!-- 在窗口大小改变时进行强制缩放 --> |
157 | 178 | <script> |
158 | 179 | (() => { |
159 | | - const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); |
| 180 | + const deviceInfo = window.__WEBGAL_DEVICE_INFO__ ?? { isIOS: false }; |
| 181 | + const isIOS = deviceInfo.isIOS; |
| 182 | + const layoutConfig = isIOS |
| 183 | + ? { |
| 184 | + bottomInset: 15, |
| 185 | + resizeDelay: 500, |
| 186 | + viewport: |
| 187 | + 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover', |
| 188 | + hideEffectBackground: true, |
| 189 | + } |
| 190 | + : { |
| 191 | + bottomInset: 0, |
| 192 | + resizeDelay: 0, |
| 193 | + viewport: 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no', |
| 194 | + hideEffectBackground: false, |
| 195 | + }; |
| 196 | + const root = document.querySelector('#root'); |
| 197 | + const titleEnter = document.querySelector('.html-body__title-enter'); |
| 198 | + const effectBackground = document.querySelector('.html-body__effect-background'); |
| 199 | + let viewportMeta = document.querySelector('meta[name="viewport"]'); |
| 200 | + |
| 201 | + const ensureViewportMeta = () => { |
| 202 | + if (!viewportMeta) { |
| 203 | + viewportMeta = document.createElement('meta'); |
| 204 | + viewportMeta.name = 'viewport'; |
| 205 | + document.head.appendChild(viewportMeta); |
| 206 | + } |
| 207 | + return viewportMeta; |
| 208 | + }; |
| 209 | + |
160 | 210 | const resize = () => { |
161 | 211 | const targetHeight = 1440; // 目标高度 |
162 | 212 | const targetWidth = 2560; // 目标宽度 |
163 | | - |
164 | 213 | const h = window.innerHeight; // 窗口高度 |
165 | 214 | const w = window.innerWidth; // 窗口宽度 |
166 | | - const zoomH = h / targetHeight; // 以窗口高度为基准的变换比 |
| 215 | + const layoutHeight = Math.max(h - layoutConfig.bottomInset, 1); |
| 216 | + const zoomH = layoutHeight / targetHeight; // 以窗口高度为基准的变换比 |
167 | 217 | const zoomW = w / targetWidth; // 以窗口宽度为基准的变换比 |
168 | 218 | const zoomH2 = w / targetHeight; // 竖屏时以窗口高度为基础的变换比 |
169 | | - const zoomW2 = h / targetWidth; // 竖屏时以窗口宽度为基础的变换比 |
170 | | - let mh = (targetHeight - h) / 2; // y轴移动距离 |
| 219 | + const zoomW2 = layoutHeight / targetWidth; // 竖屏时以窗口宽度为基础的变换比 |
| 220 | + let mh = (targetHeight - layoutHeight) / 2; // y轴移动距离 |
171 | 221 | let mw = (targetWidth - w) / 2; // x轴移动距离 |
172 | 222 | let mh2os = targetWidth / 2 - w / 2; // 竖屏时 y轴移动距离 |
173 | | - let mw2os = targetHeight / 2 - h / 2; // 竖屏时 x轴移动距离 |
| 223 | + let mw2os = targetHeight / 2 - layoutHeight / 2; // 竖屏时 x轴移动距离 |
174 | 224 | let transform = ''; |
175 | 225 | let effectBackgroundTransform = ''; |
176 | | - const root = document.querySelector('#root'); // 获取根元素 |
177 | | - const titleEnter = document.querySelector('.html-body__title-enter'); |
178 | | - const effectBackground = document.querySelector('.html-body__effect-background'); |
179 | 226 | const elements = [root, titleEnter]; |
180 | 227 | if (w > h) { |
181 | 228 | if (effectBackground) { |
|
211 | 258 | // iOS 不强制旋转 |
212 | 259 | if (isIOS) { |
213 | 260 | const zoomWi = w / targetWidth; |
| 261 | + if (effectBackground) { |
| 262 | + effectBackground.style.height = `100vh`; |
| 263 | + effectBackground.style.width = `100vw`; |
| 264 | + effectBackgroundTransform = ''; |
| 265 | + } |
214 | 266 | transform = `translate(${-mw}px, ${-mh}px) ` + `scale(${zoomWi},${zoomWi}) `; |
215 | 267 | } |
216 | 268 | } |
|
223 | 275 | } |
224 | 276 | } |
225 | 277 | }; |
226 | | - if (!isIOS) { |
227 | | - // 非 IOS |
228 | | - // 创建一个新的 meta 标签 |
229 | | - const metaTag = document.createElement('meta'); |
230 | | - metaTag.name = 'viewport'; |
231 | | - metaTag.content = 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no'; |
232 | | - // 将该标签添加到 head 中 |
233 | | - document.head.appendChild(metaTag); |
234 | | - resize(); |
235 | | - window.onload = resize; |
236 | | - window.onresize = resize; |
237 | | - // 监听键盘 F11 键按下事件,全屏时触发页面调整 |
238 | | - document.onkeydown = (e) => { |
239 | | - if (e && e.key === 'F11') { |
240 | | - setTimeout(() => { |
241 | | - resize(); |
242 | | - }, 100); |
| 278 | + let iosResizeTimer = null; |
| 279 | + const scheduleResize = () => { |
| 280 | + if (layoutConfig.resizeDelay > 0) { |
| 281 | + if (iosResizeTimer) { |
| 282 | + window.clearTimeout(iosResizeTimer); |
243 | 283 | } |
244 | | - }; |
245 | | - } else { |
246 | | - // IOS |
247 | | - const metaTag = document.createElement('meta'); |
248 | | - metaTag.name = 'viewport'; |
249 | | - metaTag.content = 'width=device-width, initial-scale=0.22, minimum-scale=0.01, maximum-scale=1'; |
250 | | - // 将该标签添加到 head 中 |
251 | | - document.head.appendChild(metaTag); |
| 284 | + iosResizeTimer = window.setTimeout(() => { |
| 285 | + resize(); |
| 286 | + iosResizeTimer = null; |
| 287 | + }, layoutConfig.resizeDelay); |
| 288 | + return; |
| 289 | + } |
| 290 | + resize(); |
| 291 | + }; |
| 292 | + if (isIOS) { |
252 | 293 | const styleTag = document.createElement('style'); |
253 | | - styleTag.textContent = '* { font-synthesis: none !important; }'; |
| 294 | + styleTag.textContent = `* { font-synthesis: none !important; }`; |
| 295 | + if (layoutConfig.hideEffectBackground) { |
| 296 | + styleTag.textContent += ` |
| 297 | + #ebg, |
| 298 | + #ebgOverlay { |
| 299 | + display: none !important; |
| 300 | + } |
| 301 | + `; |
| 302 | + } |
254 | 303 | document.head.appendChild(styleTag); |
255 | 304 | } |
| 305 | + ensureViewportMeta().content = layoutConfig.viewport; |
| 306 | + scheduleResize(); |
| 307 | + window.onload = scheduleResize; |
| 308 | + window.onresize = scheduleResize; |
| 309 | + // 监听键盘 F11 键按下事件,全屏时触发页面调整 |
| 310 | + document.onkeydown = (e) => { |
| 311 | + if (e && e.key === 'F11') { |
| 312 | + setTimeout(() => { |
| 313 | + scheduleResize(); |
| 314 | + }, 100); |
| 315 | + } |
| 316 | + }; |
256 | 317 | })(); |
257 | 318 | </script> |
258 | 319 | <!-- 注册 Service Worker --> |
259 | 320 | <script> |
260 | 321 | (() => { |
261 | | - const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); |
| 322 | + const isIOS = window.__WEBGAL_DEVICE_INFO__?.isIOS ?? false; |
262 | 323 | if ('serviceWorker' in navigator && !isIOS) { |
263 | 324 | navigator.serviceWorker |
264 | 325 | .register('./webgal-serviceworker.js') |
|
274 | 335 | <!-- 首屏加载 --> |
275 | 336 | <script> |
276 | 337 | (() => { |
277 | | - const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); |
| 338 | + const isIOS = window.__WEBGAL_DEVICE_INFO__?.isIOS ?? false; |
| 339 | + const enterConfig = isIOS |
| 340 | + ? { skipAnimation: true, hideDelay: 0 } |
| 341 | + : { skipAnimation: false, hideDelay: 2000 }; |
278 | 342 | let enterPromiseResolve; |
279 | 343 | const enterPromise = new Promise((res) => { |
280 | 344 | enterPromiseResolve = res; |
|
299 | 363 | }); |
300 | 364 | /** 点击屏幕,进入引擎主界面 */ |
301 | 365 | const enter = () => { |
| 366 | + const titleEnter = document.querySelector('.html-body__title-enter'); |
| 367 | + if (enterConfig.skipAnimation) { |
| 368 | + if (titleEnter) { |
| 369 | + titleEnter.style.pointerEvents = 'none'; |
| 370 | + titleEnter.style.transition = 'none'; |
| 371 | + titleEnter.style.opacity = '0'; |
| 372 | + titleEnter.style.display = 'none'; |
| 373 | + } |
| 374 | + enterPromiseResolve(); |
| 375 | + return; |
| 376 | + } |
302 | 377 | const initialBackground = document.querySelector('.title-enter__initial-background'); |
303 | 378 | if (initialBackground) { |
304 | 379 | initialBackground.style.opacity = '0'; |
|
313 | 388 | whiteBackground.style.opacity = '1'; |
314 | 389 | } |
315 | 390 | }, 50); // 在50ms后开始显示白色渐变 |
316 | | - const titleEnter = document.querySelector('.html-body__title-enter'); |
317 | 391 | setTimeout(() => { |
318 | 392 | if (titleEnter) titleEnter.style.opacity = '0'; |
319 | 393 | }, 500); // 500ms后开始降低落地页透明度 |
|
325 | 399 | if (titleEnter) { |
326 | 400 | titleEnter.style.display = 'none'; |
327 | 401 | } |
328 | | - }, 2000); // 将落地页设置为不显示 |
| 402 | + }, enterConfig.hideDelay); // 将落地页设置为不显示 |
329 | 403 | enterPromiseResolve(); |
330 | 404 | }; |
331 | 405 | const titleEnter = document.querySelector('.html-body__title-enter'); |
|
0 commit comments