Skip to content

Commit b83ca58

Browse files
committed
🎯 Mobile Optimization: Enhanced iOS Safari & Chrome Mobile Support
- Fixed iOS Safari scrolling issues with proper overflow and touch-action - Enhanced mobile viewport handling with dynamic viewport height (dvh) support - Improved touch responsiveness with larger touch targets (52px+) - Optimized HUD layout for mobile with compact design - Enhanced button interactions with proper iOS styling fixes - Fixed landscape/portrait orientation handling - Added comprehensive mobile browser compatibility - Improved mobile performance with hardware acceleration - Enhanced safe area support for iPhone notches/dynamic islands - Better mobile scrolling with -webkit-overflow-scrolling: touch
1 parent 93c4848 commit b83ca58

3 files changed

Lines changed: 531 additions & 655 deletions

File tree

index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8">
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover, maximum-scale=1.0">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover, maximum-scale=1.0, minimum-scale=1.0, shrink-to-fit=no">
66
<title>Target Nexus - 3D Target Game</title>
77

88
<!-- Cache Control for Mobile Updates -->
@@ -353,7 +353,7 @@ <h2 class="menu-title">🎯 GAME OVER</h2>
353353
<script src="scripts/particles.js"></script>
354354
<script src="scripts/multiplayer.js"></script>
355355
<script src="scripts/xr.js"></script>
356-
<script type="module" src="script.js?v=ios-scroll-fix-v20"></script>
356+
<script type="module" src="script.js?v=ios-mobile-optimized-nov2024"></script>
357357

358358
<!-- Mobile Orientation Notification -->
359359
<div id="rotateNotification" class="rotate-notification hidden">

script.js

Lines changed: 174 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,52 +2459,97 @@ window.addEventListener('orientationchange', () => {
24592459
}, 100);
24602460
});
24612461

2462-
// Update mobile viewport height dynamically - COMPREHENSIVE mobile support
2462+
// Update mobile viewport height dynamically - Enhanced for iOS Safari and Chrome mobile
24632463
function updateMobileViewport() {
2464-
// Only run on mobile devices
2465-
if (window.innerWidth <= 768) {
2466-
// Set CSS custom property for consistent viewport height
2467-
const vh = window.innerHeight * 0.01;
2464+
// Enhanced mobile detection
2465+
const isMobile = window.innerWidth <= 768 ||
2466+
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
2467+
2468+
if (isMobile) {
2469+
// Use dynamic viewport units when supported
2470+
let viewportHeight = window.innerHeight;
2471+
2472+
// iOS Safari specific fixes
2473+
if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) {
2474+
// Account for iOS Safari's dynamic UI
2475+
viewportHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;
2476+
}
2477+
2478+
// Set CSS custom properties for both standard and dynamic viewport
2479+
const vh = viewportHeight * 0.01;
2480+
const dvh = viewportHeight * 0.01;
24682481
document.documentElement.style.setProperty('--vh', `${vh}px`);
2482+
document.documentElement.style.setProperty('--dvh', `${dvh}px`);
24692483

2470-
// Force canvas sizing for mobile
2484+
// Enhanced canvas sizing for mobile browsers
24712485
const canvas = document.getElementById('webglCanvas');
24722486
if (canvas) {
2473-
canvas.style.width = '100vw';
2474-
canvas.style.height = '100vh';
2475-
canvas.style.position = 'fixed';
2476-
canvas.style.top = '0';
2477-
canvas.style.left = '0';
2487+
canvas.style.cssText = `
2488+
width: 100vw !important;
2489+
height: 100vh !important;
2490+
height: ${viewportHeight}px !important;
2491+
position: fixed !important;
2492+
top: 0 !important;
2493+
left: 0 !important;
2494+
z-index: 0 !important;
2495+
touch-action: none !important;
2496+
-webkit-user-select: none !important;
2497+
user-select: none !important;
2498+
`;
24782499
}
24792500

2480-
// Optimize HUD positioning for mobile browsers
2501+
// Optimize HUD positioning for different mobile browsers
24812502
const bottomHud = document.getElementById('bottomHud');
24822503
const topHud = document.getElementById('topHud');
24832504

24842505
if (bottomHud) {
2485-
// Smart bottom HUD positioning
24862506
const isLandscape = window.innerWidth > window.innerHeight;
2487-
const viewportHeight = window.innerHeight;
2488-
const safeAreaBottom = getComputedStyle(document.documentElement).getPropertyValue('--sab') || '0px';
2507+
const safeAreaBottom = getComputedStyle(document.documentElement)
2508+
.getPropertyValue('--sab') ||
2509+
getComputedStyle(document.documentElement)
2510+
.getPropertyValue('env(safe-area-inset-bottom)') || '0px';
24892511

2490-
// Position based on actual viewport and orientation
2512+
// Enhanced bottom HUD positioning for mobile browsers
2513+
let bottomOffset = 12;
24912514
if (isLandscape && viewportHeight < 500) {
2492-
bottomHud.style.bottom = `max(10px, ${safeAreaBottom})`;
2515+
bottomOffset = 8;
24932516
} else if (viewportHeight < 600) {
2494-
bottomHud.style.bottom = `max(15px, ${safeAreaBottom})`;
2495-
} else {
2496-
bottomHud.style.bottom = `max(20px, ${safeAreaBottom})`;
2517+
bottomOffset = 10;
24972518
}
24982519

2499-
// Ensure buttons are touchable
2500-
bottomHud.style.pointerEvents = 'auto';
2501-
bottomHud.style.zIndex = '999';
2520+
bottomHud.style.cssText += `
2521+
bottom: max(${bottomOffset}px, ${safeAreaBottom}) !important;
2522+
pointer-events: none !important;
2523+
z-index: 999 !important;
2524+
position: fixed !important;
2525+
left: 8px !important;
2526+
right: 8px !important;
2527+
width: auto !important;
2528+
background: linear-gradient(135deg, rgba(0, 255, 255, 0.25), rgba(0, 0, 0, 0.9)) !important;
2529+
border: 2px solid #00ffff !important;
2530+
box-shadow: 0 0 25px rgba(0, 255, 255, 0.6) !important;
2531+
`;
2532+
2533+
// Make HUD controls touchable
2534+
const hudControls = bottomHud.querySelector('.hud-controls');
2535+
if (hudControls) {
2536+
hudControls.style.pointerEvents = 'auto';
2537+
hudControls.style.zIndex = '1000';
2538+
}
25022539
}
25032540

25042541
if (topHud) {
2505-
// Minimize top HUD interference
2506-
topHud.style.pointerEvents = 'auto';
2507-
topHud.style.opacity = '0.9';
2542+
const safeAreaTop = getComputedStyle(document.documentElement)
2543+
.getPropertyValue('--sat') ||
2544+
getComputedStyle(document.documentElement)
2545+
.getPropertyValue('env(safe-area-inset-top)') || '0px';
2546+
2547+
topHud.style.cssText += `
2548+
top: max(4px, ${safeAreaTop}) !important;
2549+
pointer-events: auto !important;
2550+
opacity: 0.95 !important;
2551+
backdrop-filter: blur(8px) !important;
2552+
`;
25082553
}
25092554

25102555
// Force layout recalculation
@@ -2571,8 +2616,110 @@ window.addEventListener('load', () => {
25712616
soundManager.setMasterVolume(gameSettings.volume);
25722617
});
25732618

2574-
// Initialize mobile viewport handling
2619+
// Enhanced mobile initialization
2620+
initializeMobileSupport();
2621+
});
2622+
2623+
// Enhanced mobile support initialization
2624+
function initializeMobileSupport() {
2625+
console.log('📱 Initializing enhanced mobile support...');
2626+
2627+
// Initial mobile viewport setup
25752628
updateMobileViewport();
2629+
2630+
// Enhanced mobile event listeners
2631+
const isMobile = window.innerWidth <= 768 ||
2632+
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
2633+
2634+
if (isMobile) {
2635+
console.log('📱 Mobile device detected - applying mobile optimizations');
2636+
2637+
// iOS Safari specific optimizations
2638+
if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
2639+
console.log('🍎 iOS Safari optimizations active');
2640+
2641+
// Prevent iOS Safari zoom on input focus
2642+
document.addEventListener('touchstart', function(event) {
2643+
if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
2644+
event.target.style.fontSize = '16px';
2645+
}
2646+
});
2647+
2648+
// Handle iOS Safari viewport changes
2649+
if (window.visualViewport) {
2650+
window.visualViewport.addEventListener('resize', () => {
2651+
setTimeout(updateMobileViewport, 150);
2652+
});
2653+
}
2654+
}
2655+
2656+
// Chrome mobile specific optimizations
2657+
if (/Chrome/.test(navigator.userAgent) && /Mobile/.test(navigator.userAgent)) {
2658+
console.log('🤖 Chrome mobile optimizations active');
2659+
}
2660+
2661+
// Enhanced resize handling for mobile
2662+
let resizeTimeout;
2663+
window.addEventListener('resize', () => {
2664+
clearTimeout(resizeTimeout);
2665+
resizeTimeout = setTimeout(() => {
2666+
updateMobileViewport();
2667+
// Ensure three.js canvas resizes properly
2668+
camera.aspect = window.innerWidth / window.innerHeight;
2669+
camera.updateProjectionMatrix();
2670+
renderer.setSize(window.innerWidth, window.innerHeight);
2671+
}, 200);
2672+
});
2673+
2674+
// Enhanced orientation change handling
2675+
window.addEventListener('orientationchange', () => {
2676+
setTimeout(() => {
2677+
updateMobileViewport();
2678+
camera.aspect = window.innerWidth / window.innerHeight;
2679+
camera.updateProjectionMatrix();
2680+
renderer.setSize(window.innerWidth, window.innerHeight);
2681+
2682+
// Re-check mobile orientation after orientation change
2683+
setTimeout(() => {
2684+
checkMobileOrientation();
2685+
}, 300);
2686+
}, 300); // Increased delay for iOS Safari
2687+
});
2688+
2689+
// Mobile performance optimizations
2690+
document.body.style.cssText += `
2691+
-webkit-font-smoothing: antialiased;
2692+
-moz-osx-font-smoothing: grayscale;
2693+
text-rendering: optimizeLegibility;
2694+
`;
2695+
2696+
// Prevent mobile scroll bounce
2697+
document.addEventListener('touchmove', function(e) {
2698+
if (e.target === document.body || e.target === document.documentElement) {
2699+
e.preventDefault();
2700+
}
2701+
}, { passive: false });
2702+
2703+
// Enhanced touch event handling
2704+
let touchStartY = 0;
2705+
document.addEventListener('touchstart', function(e) {
2706+
touchStartY = e.touches[0].clientY;
2707+
});
2708+
2709+
document.addEventListener('touchmove', function(e) {
2710+
const touchY = e.touches[0].clientY;
2711+
const touchYDelta = touchStartY - touchY;
2712+
const el = e.target;
2713+
2714+
// Allow scrolling only in scrollable elements
2715+
if (!el.closest('.overlay-menu, .menu-container, .install-instructions, .leaderboard-list')) {
2716+
e.preventDefault();
2717+
}
2718+
}, { passive: false });
2719+
}
2720+
2721+
console.log('✅ Mobile support initialization complete');
2722+
}
25762723
});
25772724

25782725
// Also update viewport when DOM is ready

0 commit comments

Comments
 (0)