Skip to content

Commit 17b098a

Browse files
Merge pull request #905 from OpenWebGAL/fix-safari-problem
Fix safari problem
2 parents 1bebc83 + fdc1572 commit 17b098a

3 files changed

Lines changed: 123 additions & 45 deletions

File tree

packages/webgal/index.html

Lines changed: 113 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@
77
<link rel="manifest" href="/manifest.json" />
88
<title>WebGAL</title>
99
<style>
10+
html,
1011
body {
12+
margin: 0;
1113
background: black;
14+
width: 100%;
15+
height: 100%;
16+
overflow: hidden;
1217
}
1318

1419
.html-body__effect-background {
@@ -129,6 +134,7 @@
129134
.title-enter-container__link-to-github > div {
130135
padding: 0 0 0.25em 0;
131136
}
137+
132138
</style>
133139
</head>
134140
<body>
@@ -153,29 +159,70 @@
153159
<div id="html-body__panic-overlay"></div>
154160
<!-- 应用挂载点 -->
155161
<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>
156177
<!-- 在窗口大小改变时进行强制缩放 -->
157178
<script>
158179
(() => {
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+
160210
const resize = () => {
161211
const targetHeight = 1440; // 目标高度
162212
const targetWidth = 2560; // 目标宽度
163-
164213
const h = window.innerHeight; // 窗口高度
165214
const w = window.innerWidth; // 窗口宽度
166-
const zoomH = h / targetHeight; // 以窗口高度为基准的变换比
215+
const layoutHeight = Math.max(h - layoutConfig.bottomInset, 1);
216+
const zoomH = layoutHeight / targetHeight; // 以窗口高度为基准的变换比
167217
const zoomW = w / targetWidth; // 以窗口宽度为基准的变换比
168218
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轴移动距离
171221
let mw = (targetWidth - w) / 2; // x轴移动距离
172222
let mh2os = targetWidth / 2 - w / 2; // 竖屏时 y轴移动距离
173-
let mw2os = targetHeight / 2 - h / 2; // 竖屏时 x轴移动距离
223+
let mw2os = targetHeight / 2 - layoutHeight / 2; // 竖屏时 x轴移动距离
174224
let transform = '';
175225
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');
179226
const elements = [root, titleEnter];
180227
if (w > h) {
181228
if (effectBackground) {
@@ -211,6 +258,11 @@
211258
// iOS 不强制旋转
212259
if (isIOS) {
213260
const zoomWi = w / targetWidth;
261+
if (effectBackground) {
262+
effectBackground.style.height = `100vh`;
263+
effectBackground.style.width = `100vw`;
264+
effectBackgroundTransform = '';
265+
}
214266
transform = `translate(${-mw}px, ${-mh}px) ` + `scale(${zoomWi},${zoomWi}) `;
215267
}
216268
}
@@ -223,42 +275,51 @@
223275
}
224276
}
225277
};
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);
243283
}
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) {
252293
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+
}
254303
document.head.appendChild(styleTag);
255304
}
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+
};
256317
})();
257318
</script>
258319
<!-- 注册 Service Worker -->
259320
<script>
260321
(() => {
261-
const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
322+
const isIOS = window.__WEBGAL_DEVICE_INFO__?.isIOS ?? false;
262323
if ('serviceWorker' in navigator && !isIOS) {
263324
navigator.serviceWorker
264325
.register('./webgal-serviceworker.js')
@@ -274,7 +335,10 @@
274335
<!-- 首屏加载 -->
275336
<script>
276337
(() => {
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 };
278342
let enterPromiseResolve;
279343
const enterPromise = new Promise((res) => {
280344
enterPromiseResolve = res;
@@ -299,6 +363,17 @@
299363
});
300364
/** 点击屏幕,进入引擎主界面 */
301365
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+
}
302377
const initialBackground = document.querySelector('.title-enter__initial-background');
303378
if (initialBackground) {
304379
initialBackground.style.opacity = '0';
@@ -313,7 +388,6 @@
313388
whiteBackground.style.opacity = '1';
314389
}
315390
}, 50); // 在50ms后开始显示白色渐变
316-
const titleEnter = document.querySelector('.html-body__title-enter');
317391
setTimeout(() => {
318392
if (titleEnter) titleEnter.style.opacity = '0';
319393
}, 500); // 500ms后开始降低落地页透明度
@@ -325,7 +399,7 @@
325399
if (titleEnter) {
326400
titleEnter.style.display = 'none';
327401
}
328-
}, 2000); // 将落地页设置为不显示
402+
}, enterConfig.hideDelay); // 将落地页设置为不显示
329403
enterPromiseResolve();
330404
};
331405
const titleEnter = document.querySelector('.html-body__title-enter');

packages/webgal/src/Core/initializeScript.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ import { __INFO } from '@/config/info';
1616
import { WebGAL } from '@/Core/WebGAL';
1717
import { loadTemplate } from '@/Core/util/coreInitialFunction/templateLoader';
1818

19-
const u = navigator.userAgent;
20-
export const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); // 判断是否是 iOS终端
19+
export const isIOS = window.__WEBGAL_DEVICE_INFO__?.isIOS ?? false; // 判断是否是 iOS 终端
2120

2221
/**
2322
* 引擎初始化函数
@@ -30,14 +29,14 @@ export const initializeScript = (): void => {
3029
loadTemplate();
3130
// 激活强制缩放
3231
// 在调整窗口大小时重新计算宽高,设计稿按照 1600*900。
33-
if (isIOS) {
32+
if (isIOS && window.innerWidth <= window.innerHeight) {
3433
/**
3534
* iOS
3635
*/
3736
alert(
38-
`iOS 用户请横屏使用以获得最佳体验
39-
| Please use landscape mode on iOS for the best experience
40-
| iOS ユーザーは横画面での使用をお勧めします`,
37+
`iOS 用户请横屏后刷新页面,以获得最佳体验
38+
| Please rotate to landscape and refresh the page on iOS for the best experience
39+
| iOS ユーザーは横画面にしてからページを再読み込みしてください`,
4140
);
4241
}
4342

packages/webgal/src/types/electron.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ export {};
22

33
declare global {
44
interface Window {
5+
__WEBGAL_DEVICE_INFO__?: {
6+
isIOS: boolean;
7+
isIOSPhone: boolean;
8+
isIPad: boolean;
9+
};
510
electronFuncs?: {
611
steam?: {
712
initialize: (appId: string) => boolean | Promise<boolean>;

0 commit comments

Comments
 (0)