Skip to content

Commit 4864aca

Browse files
fix: ios resize problem
1 parent d598cd5 commit 4864aca

2 files changed

Lines changed: 67 additions & 225 deletions

File tree

packages/webgal/index.html

Lines changed: 63 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,9 @@
1111
body {
1212
margin: 0;
1313
background: black;
14-
}
15-
16-
html {
17-
--ios-safe-area-top: env(safe-area-inset-top, 0px);
18-
--ios-safe-area-right: env(safe-area-inset-right, 0px);
19-
--ios-safe-area-bottom: env(safe-area-inset-bottom, 0px);
20-
--ios-safe-area-left: env(safe-area-inset-left, 0px);
14+
width: 100%;
15+
height: 100%;
16+
overflow: hidden;
2117
}
2218

2319
.html-body__effect-background {
@@ -139,33 +135,6 @@
139135
padding: 0 0 0.25em 0;
140136
}
141137

142-
html.ios-phone-viewport,
143-
html.ios-phone-viewport body {
144-
width: 100%;
145-
height: 100%;
146-
overflow: hidden;
147-
overscroll-behavior: none;
148-
background: black;
149-
}
150-
151-
html.ios-phone-viewport body {
152-
position: fixed;
153-
inset: 0;
154-
}
155-
156-
html.ios-phone-viewport #ebg {
157-
display: none;
158-
}
159-
160-
html.ios-phone-viewport #root,
161-
html.ios-phone-viewport .html-body__title-enter {
162-
width: 2560px;
163-
height: 1440px;
164-
position: absolute;
165-
top: 0;
166-
left: 0;
167-
transform-origin: top left;
168-
}
169138
</style>
170139
</head>
171140
<body>
@@ -193,24 +162,17 @@
193162
<!-- 在窗口大小改变时进行强制缩放 -->
194163
<script>
195164
(() => {
196-
const targetHeight = 1440;
197-
const targetWidth = 2560;
198165
const userAgent = navigator.userAgent;
199166
const platform = navigator.platform;
200167
const maxTouchPoints = navigator.maxTouchPoints || 0;
201168
const isIPhoneLike = /iPhone|iPod/i.test(userAgent);
202169
const isIPadLike = /iPad/i.test(userAgent) || (platform === 'MacIntel' && maxTouchPoints > 1);
203170
const isIOS = isIPhoneLike || isIPadLike;
204171
const isIOSPhone = isIOS && isIPhoneLike;
205-
const html = document.documentElement;
206-
const body = document.body;
207172
const root = document.querySelector('#root');
208173
const titleEnter = document.querySelector('.html-body__title-enter');
209174
const effectBackground = document.querySelector('.html-body__effect-background');
210175
let viewportMeta = document.querySelector('meta[name="viewport"]');
211-
let iosPhoneLayoutFrame = 0;
212-
let touchStartX = 0;
213-
let touchStartY = 0;
214176

215177
window.__WEBGAL_DEVICE_INFO__ = { isIOS, isIOSPhone };
216178

@@ -223,163 +185,21 @@
223185
return viewportMeta;
224186
};
225187

226-
const parseInset = (value) => {
227-
const parsed = Number.parseFloat(value);
228-
return Number.isFinite(parsed) ? parsed : 0;
229-
};
230-
231-
const getSafeAreaInsets = () => {
232-
const computedStyle = window.getComputedStyle(html);
233-
return {
234-
top: parseInset(computedStyle.getPropertyValue('--ios-safe-area-top')),
235-
right: parseInset(computedStyle.getPropertyValue('--ios-safe-area-right')),
236-
bottom: parseInset(computedStyle.getPropertyValue('--ios-safe-area-bottom')),
237-
left: parseInset(computedStyle.getPropertyValue('--ios-safe-area-left')),
238-
};
239-
};
240-
241-
const applyIOSPhoneLayout = () => {
242-
const safeArea = getSafeAreaInsets();
243-
const viewportWidth = window.innerWidth;
244-
const viewportHeight = window.innerHeight;
245-
const usableWidth = Math.max(viewportWidth - safeArea.left - safeArea.right, 1);
246-
const usableHeight = Math.max(viewportHeight - safeArea.top - safeArea.bottom, 1);
247-
const scale = Math.max(Math.min(usableWidth / targetWidth, usableHeight / targetHeight), 0.01);
248-
const left = safeArea.left + Math.max((usableWidth - targetWidth * scale) / 2, 0);
249-
const top = safeArea.top + Math.max((usableHeight - targetHeight * scale) / 2, 0);
250-
const transform = `translate(${left}px, ${top}px) scale(${scale})`;
251-
252-
if (effectBackground) {
253-
effectBackground.style.transform = '';
254-
}
255-
for (const element of [root, titleEnter]) {
256-
if (element) {
257-
element.style.transform = transform;
258-
}
259-
}
260-
};
261-
262-
const scheduleIOSPhoneLayout = () => {
263-
if (iosPhoneLayoutFrame) {
264-
window.cancelAnimationFrame(iosPhoneLayoutFrame);
265-
}
266-
iosPhoneLayoutFrame = window.requestAnimationFrame(() => {
267-
iosPhoneLayoutFrame = 0;
268-
applyIOSPhoneLayout();
269-
});
270-
};
271-
272-
const canScrollInDirection = (element, deltaX, deltaY) => {
273-
const style = window.getComputedStyle(element);
274-
const overflowY = style.overflowY;
275-
const overflowX = style.overflowX;
276-
const canScrollY = /(auto|scroll|overlay)/.test(overflowY) && element.scrollHeight > element.clientHeight + 1;
277-
const canScrollX = /(auto|scroll|overlay)/.test(overflowX) && element.scrollWidth > element.clientWidth + 1;
278-
279-
if (Math.abs(deltaY) >= Math.abs(deltaX) && canScrollY) {
280-
const maxScrollTop = element.scrollHeight - element.clientHeight;
281-
if (deltaY > 0 && element.scrollTop > 0) return true;
282-
if (deltaY < 0 && element.scrollTop < maxScrollTop) return true;
283-
}
284-
285-
if (Math.abs(deltaX) > Math.abs(deltaY) && canScrollX) {
286-
const maxScrollLeft = element.scrollWidth - element.clientWidth;
287-
if (deltaX > 0 && element.scrollLeft > 0) return true;
288-
if (deltaX < 0 && element.scrollLeft < maxScrollLeft) return true;
289-
}
290-
291-
return false;
292-
};
293-
294-
const findScrollableAncestor = (startElement, deltaX, deltaY) => {
295-
let current = startElement;
296-
while (current && current !== body) {
297-
if (current instanceof HTMLElement && canScrollInDirection(current, deltaX, deltaY)) {
298-
return current;
299-
}
300-
current = current.parentElement;
301-
}
302-
return null;
303-
};
304-
305-
const installIOSPhoneGestureGuards = () => {
306-
const blockEvent = (event) => {
307-
event.preventDefault();
308-
};
309-
310-
document.addEventListener(
311-
'gesturestart',
312-
(event) => {
313-
blockEvent(event);
314-
},
315-
{ passive: false },
316-
);
317-
document.addEventListener(
318-
'gesturechange',
319-
(event) => {
320-
blockEvent(event);
321-
},
322-
{ passive: false },
323-
);
324-
document.addEventListener(
325-
'gestureend',
326-
(event) => {
327-
blockEvent(event);
328-
},
329-
{ passive: false },
330-
);
331-
332-
document.addEventListener(
333-
'touchstart',
334-
(event) => {
335-
if (event.touches.length > 1) {
336-
blockEvent(event);
337-
return;
338-
}
339-
const touch = event.touches[0];
340-
if (touch) {
341-
touchStartX = touch.clientX;
342-
touchStartY = touch.clientY;
343-
}
344-
},
345-
{ passive: false },
346-
);
347-
348-
document.addEventListener(
349-
'touchmove',
350-
(event) => {
351-
if (event.touches.length > 1) {
352-
blockEvent(event);
353-
return;
354-
}
355-
const touch = event.touches[0];
356-
if (!touch) {
357-
return;
358-
}
359-
const deltaX = touch.clientX - touchStartX;
360-
const deltaY = touch.clientY - touchStartY;
361-
const target = event.target instanceof Element ? event.target : null;
362-
const scrollableAncestor = target ? findScrollableAncestor(target, deltaX, deltaY) : null;
363-
364-
if (!scrollableAncestor) {
365-
blockEvent(event);
366-
}
367-
},
368-
{ passive: false },
369-
);
370-
};
371-
372188
const resize = () => {
189+
const targetHeight = 1440; // 目标高度
190+
const targetWidth = 2560; // 目标宽度
373191
const h = window.innerHeight; // 窗口高度
374192
const w = window.innerWidth; // 窗口宽度
375-
const zoomH = h / targetHeight; // 以窗口高度为基准的变换比
193+
const iosBottomInset = isIOS ? 15 : 0;
194+
const layoutHeight = Math.max(h - iosBottomInset, 1);
195+
const zoomH = layoutHeight / targetHeight; // 以窗口高度为基准的变换比
376196
const zoomW = w / targetWidth; // 以窗口宽度为基准的变换比
377197
const zoomH2 = w / targetHeight; // 竖屏时以窗口高度为基础的变换比
378-
const zoomW2 = h / targetWidth; // 竖屏时以窗口宽度为基础的变换比
379-
let mh = (targetHeight - h) / 2; // y轴移动距离
198+
const zoomW2 = layoutHeight / targetWidth; // 竖屏时以窗口宽度为基础的变换比
199+
let mh = (targetHeight - layoutHeight) / 2; // y轴移动距离
380200
let mw = (targetWidth - w) / 2; // x轴移动距离
381201
let mh2os = targetWidth / 2 - w / 2; // 竖屏时 y轴移动距离
382-
let mw2os = targetHeight / 2 - h / 2; // 竖屏时 x轴移动距离
202+
let mw2os = targetHeight / 2 - layoutHeight / 2; // 竖屏时 x轴移动距离
383203
let transform = '';
384204
let effectBackgroundTransform = '';
385205
const elements = [root, titleEnter];
@@ -417,6 +237,11 @@
417237
// iOS 不强制旋转
418238
if (isIOS) {
419239
const zoomWi = w / targetWidth;
240+
if (effectBackground) {
241+
effectBackground.style.height = `100vh`;
242+
effectBackground.style.width = `100vw`;
243+
effectBackgroundTransform = '';
244+
}
420245
transform = `translate(${-mw}px, ${-mh}px) ` + `scale(${zoomWi},${zoomWi}) `;
421246
}
422247
}
@@ -429,39 +254,46 @@
429254
}
430255
}
431256
};
432-
if (!isIOS) {
433-
ensureViewportMeta().content = 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no';
434-
resize();
435-
window.onload = resize;
436-
window.onresize = resize;
437-
// 监听键盘 F11 键按下事件,全屏时触发页面调整
438-
document.onkeydown = (e) => {
439-
if (e && e.key === 'F11') {
440-
setTimeout(() => {
441-
resize();
442-
}, 100);
257+
let iosResizeTimer = null;
258+
const scheduleResize = () => {
259+
if (isIOS) {
260+
if (iosResizeTimer) {
261+
window.clearTimeout(iosResizeTimer);
443262
}
444-
};
445-
} else {
263+
iosResizeTimer = window.setTimeout(() => {
264+
resize();
265+
iosResizeTimer = null;
266+
}, 500);
267+
return;
268+
}
269+
resize();
270+
};
271+
if (isIOS) {
446272
const styleTag = document.createElement('style');
447-
styleTag.textContent = '* { font-synthesis: none !important; }';
273+
styleTag.textContent = `
274+
* { font-synthesis: none !important; }
275+
#ebg,
276+
#ebgOverlay {
277+
display: none !important;
278+
}
279+
`;
448280
document.head.appendChild(styleTag);
449-
if (isIOSPhone) {
450-
html.classList.add('ios-phone-viewport');
451-
body.classList.add('ios-phone-viewport');
452-
ensureViewportMeta().content = 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover';
453-
installIOSPhoneGestureGuards();
454-
scheduleIOSPhoneLayout();
455-
window.addEventListener('load', scheduleIOSPhoneLayout);
456-
window.addEventListener('resize', scheduleIOSPhoneLayout);
457-
window.addEventListener('orientationchange', () => {
458-
scheduleIOSPhoneLayout();
459-
setTimeout(scheduleIOSPhoneLayout, 300);
460-
});
461-
} else {
462-
ensureViewportMeta().content = 'width=device-width, initial-scale=0.22, minimum-scale=0.01, maximum-scale=1';
463-
}
281+
ensureViewportMeta().content =
282+
'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover';
283+
} else {
284+
ensureViewportMeta().content = 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no';
464285
}
286+
scheduleResize();
287+
window.onload = scheduleResize;
288+
window.onresize = scheduleResize;
289+
// 监听键盘 F11 键按下事件,全屏时触发页面调整
290+
document.onkeydown = (e) => {
291+
if (e && e.key === 'F11') {
292+
setTimeout(() => {
293+
scheduleResize();
294+
}, 100);
295+
}
296+
};
465297
})();
466298
</script>
467299
<!-- 注册 Service Worker -->
@@ -508,6 +340,17 @@
508340
});
509341
/** 点击屏幕,进入引擎主界面 */
510342
const enter = () => {
343+
const titleEnter = document.querySelector('.html-body__title-enter');
344+
if (isIOS) {
345+
if (titleEnter) {
346+
titleEnter.style.pointerEvents = 'none';
347+
titleEnter.style.transition = 'none';
348+
titleEnter.style.opacity = '0';
349+
titleEnter.style.display = 'none';
350+
}
351+
enterPromiseResolve();
352+
return;
353+
}
511354
const initialBackground = document.querySelector('.title-enter__initial-background');
512355
if (initialBackground) {
513356
initialBackground.style.opacity = '0';
@@ -522,7 +365,6 @@
522365
whiteBackground.style.opacity = '1';
523366
}
524367
}, 50); // 在50ms后开始显示白色渐变
525-
const titleEnter = document.querySelector('.html-body__title-enter');
526368
setTimeout(() => {
527369
if (titleEnter) titleEnter.style.opacity = '0';
528370
}, 500); // 500ms后开始降低落地页透明度

packages/webgal/src/Core/initializeScript.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ export const initializeScript = (): void => {
3030
loadTemplate();
3131
// 激活强制缩放
3232
// 在调整窗口大小时重新计算宽高,设计稿按照 1600*900。
33-
if (isIOS) {
33+
if (isIOS && window.innerWidth <= window.innerHeight) {
3434
/**
3535
* iOS
3636
*/
3737
alert(
38-
`iOS 用户请横屏使用以获得最佳体验
39-
| Please use landscape mode on iOS for the best experience
40-
| iOS ユーザーは横画面での使用をお勧めします`,
38+
`iOS 用户请横屏后刷新页面,以获得最佳体验
39+
| Please rotate to landscape and refresh the page on iOS for the best experience
40+
| iOS ユーザーは横画面にしてからページを再読み込みしてください`,
4141
);
4242
}
4343

0 commit comments

Comments
 (0)