feat(mobile): 全屏自适应布局,适配手机/折叠屏/平板
- #wrap 去除外框限制,竖屏/方形屏占满全屏(逻辑分辨率动态:宽240、高按屏比 clamp[280,640]) - 横屏 letterbox:中间 3:4 竖屏显示区域居中,UI 收紧压缩 - viewport-fit=cover + safe-area-inset 适配刘海屏/底部横条 - 星星背景按视口面积重建,保持星空密度 - resize/orientationchange 自动重新适配,对局中旋转位置自动修正
This commit is contained in:
parent
bb0d7e5704
commit
559e70fac5
@ -12,9 +12,8 @@ body{
|
|||||||
user-select:none;
|
user-select:none;
|
||||||
}
|
}
|
||||||
#wrap{
|
#wrap{
|
||||||
position:relative; width:min(96vw,calc(96vh * 0.75)); aspect-ratio:3/4;
|
position:fixed; inset:0; width:100%; height:100%;
|
||||||
border:4px solid var(--line); background:#000;
|
background:#000;
|
||||||
box-shadow:0 0 0 2px #000, 0 0 42px rgba(65,230,255,.12), 0 24px 80px rgba(0,0,0,.7);
|
|
||||||
}
|
}
|
||||||
canvas#game{width:100%;height:100%;display:block;image-rendering:pixelated;image-rendering:crisp-edges;background:#05070f;touch-action:none}
|
canvas#game{width:100%;height:100%;display:block;image-rendering:pixelated;image-rendering:crisp-edges;background:#05070f;touch-action:none}
|
||||||
#scan{position:absolute;inset:0;pointer-events:none;z-index:40;
|
#scan{position:absolute;inset:0;pointer-events:none;z-index:40;
|
||||||
@ -24,7 +23,9 @@ canvas#game{width:100%;height:100%;display:block;image-rendering:pixelated;image
|
|||||||
background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,.5) 100%)}
|
background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,.5) 100%)}
|
||||||
/* ---------- overlays ---------- */
|
/* ---------- overlays ---------- */
|
||||||
.ovl{position:absolute;inset:0;z-index:50;display:flex;flex-direction:column;align-items:center;justify-content:center;
|
.ovl{position:absolute;inset:0;z-index:50;display:flex;flex-direction:column;align-items:center;justify-content:center;
|
||||||
background:rgba(4,7,16,.88); text-align:center; padding:4%; gap:10px; overflow-y:auto}
|
background:rgba(4,7,16,.88); text-align:center;
|
||||||
|
padding:max(4%,env(safe-area-inset-top,0px)) max(4%,env(safe-area-inset-right,0px)) max(4%,env(safe-area-inset-bottom,0px)) max(4%,env(safe-area-inset-left,0px));
|
||||||
|
gap:10px; overflow-y:auto}
|
||||||
.ovl.hide{display:none}
|
.ovl.hide{display:none}
|
||||||
#o-title{background:rgba(4,7,16,.5)} /* 半透明:露出背后实战模拟 */
|
#o-title{background:rgba(4,7,16,.5)} /* 半透明:露出背后实战模拟 */
|
||||||
h1.logo{font-size:clamp(20px,5.4vw,44px);color:#fff;letter-spacing:4px;line-height:1.35;
|
h1.logo{font-size:clamp(20px,5.4vw,44px);color:#fff;letter-spacing:4px;line-height:1.35;
|
||||||
@ -110,10 +111,10 @@ h1.logo{font-size:clamp(20px,5.4vw,44px);color:#fff;letter-spacing:4px;line-heig
|
|||||||
#tbtns button{pointer-events:auto;font:inherit;font-size:10px;width:64px;height:64px;border-radius:8px;
|
#tbtns button{pointer-events:auto;font:inherit;font-size:10px;width:64px;height:64px;border-radius:8px;
|
||||||
background:rgba(16,26,51,.7);border:3px solid var(--line);color:var(--ink);letter-spacing:1px}
|
background:rgba(16,26,51,.7);border:3px solid var(--line);color:var(--ink);letter-spacing:1px}
|
||||||
#tbtns button:active{background:var(--cyan);color:#000}
|
#tbtns button:active{background:var(--cyan);color:#000}
|
||||||
#tb-pause{position:absolute;top:6px;right:6px;z-index:46;font:inherit;font-size:11px;width:40px;height:40px;
|
#tb-pause{position:absolute;top:calc(6px + env(safe-area-inset-top,0px));right:calc(6px + env(safe-area-inset-right,0px));z-index:46;font:inherit;font-size:11px;width:40px;height:40px;
|
||||||
background:rgba(16,26,51,.7);border:3px solid var(--line);color:var(--ink);letter-spacing:1px}
|
background:rgba(16,26,51,.7);border:3px solid var(--line);color:var(--ink);letter-spacing:1px}
|
||||||
#tb-pause:active{background:var(--cyan);color:#000}
|
#tb-pause:active{background:var(--cyan);color:#000}
|
||||||
#b-mute{position:absolute;top:10px;right:10px;z-index:5;width:42px;height:42px;
|
#b-mute{position:absolute;top:calc(10px + env(safe-area-inset-top,0px));right:calc(10px + env(safe-area-inset-right,0px));z-index:5;width:42px;height:42px;
|
||||||
display:flex;align-items:center;justify-content:center;
|
display:flex;align-items:center;justify-content:center;
|
||||||
background:rgba(16,26,51,.85);border:3px solid var(--line);color:var(--ink);cursor:pointer;padding:0;line-height:1}
|
background:rgba(16,26,51,.85);border:3px solid var(--line);color:var(--ink);cursor:pointer;padding:0;line-height:1}
|
||||||
#b-mute canvas{image-rendering:pixelated;pointer-events:none}
|
#b-mute canvas{image-rendering:pixelated;pointer-events:none}
|
||||||
@ -161,3 +162,36 @@ h1.logo{font-size:clamp(20px,5.4vw,44px);color:#fff;letter-spacing:4px;line-heig
|
|||||||
.lb-row.me{background:rgba(65,230,255,.12);outline:1px solid rgba(65,230,255,.35)}
|
.lb-row.me{background:rgba(65,230,255,.12);outline:1px solid rgba(65,230,255,.35)}
|
||||||
.lb-list{flex:1;min-height:100px;overflow-y:auto}
|
.lb-list{flex:1;min-height:100px;overflow-y:auto}
|
||||||
.lb-empty{color:var(--dim);font-size:clamp(7px,1.3vw,9px);padding:14px 0;letter-spacing:2px}
|
.lb-empty{color:var(--dim);font-size:clamp(7px,1.3vw,9px);padding:14px 0;letter-spacing:2px}
|
||||||
|
|
||||||
|
/* ---------- 横屏:中间竖屏显示区域(letterbox),UI 收紧 ---------- */
|
||||||
|
@media (orientation: landscape){
|
||||||
|
#wrap{position:fixed;inset:0;margin:auto;width:min(100vw,calc(100dvh * 0.75));height:auto;aspect-ratio:3/4}
|
||||||
|
/* 横屏高度矮:居中溢出不可滚 → 改顶部对齐 + 伪元素弹性撑开(内容少时视觉居中,多时可滚动) */
|
||||||
|
.ovl:not(#o-home):not(#o-demo){justify-content:flex-start}
|
||||||
|
.ovl:not(#o-home):not(#o-demo)::before,
|
||||||
|
.ovl:not(#o-home):not(#o-demo)::after{content:"";flex:1 0 auto;min-height:8px}
|
||||||
|
.ovl{gap:6px;padding:max(2.5%,env(safe-area-inset-top,0px)) max(2.5%,env(safe-area-inset-right,0px)) max(2.5%,env(safe-area-inset-bottom,0px)) max(2.5%,env(safe-area-inset-left,0px))}
|
||||||
|
h1.logo{font-size:clamp(14px,6vh,20px);letter-spacing:3px;line-height:1.2}
|
||||||
|
.logo-cn{font-size:clamp(9px,2.2vh,12px);letter-spacing:6px}
|
||||||
|
.tag{font-size:clamp(6px,1.4vh,8px)}
|
||||||
|
.h2{font-size:clamp(10px,2.6vh,14px)}
|
||||||
|
.h3{font-size:clamp(8px,2vh,10px)}
|
||||||
|
.small{font-size:clamp(6px,1.5vh,8px)}
|
||||||
|
.btn{font-size:clamp(8px,2.2vh,11px);padding:8px 14px;min-width:min(44vw,200px)}
|
||||||
|
.btn.primary{padding:9px 14px}
|
||||||
|
.row{gap:6px}.col{gap:6px}
|
||||||
|
.panel{padding:10px}
|
||||||
|
.auth-f input{padding:7px 10px}
|
||||||
|
#o-auth .panel{width:min(80%,320px)}
|
||||||
|
#tb-pause{width:36px;height:36px;font-size:10px}
|
||||||
|
.wallet{font-size:clamp(9px,2.2vh,11px)}
|
||||||
|
.pcard{width:min(26vw,120px);padding:8px 5px}
|
||||||
|
.pcard canvas{width:44px;height:54px}
|
||||||
|
.ucard{width:min(24vw,130px);padding:9px 6px}
|
||||||
|
.slotbox{width:min(18vw,76px);padding:6px 3px}
|
||||||
|
.litem{font-size:clamp(7px,1.7vh,9px);padding:4px 6px}
|
||||||
|
.cx-grid{grid-template-columns:repeat(auto-fill,minmax(54px,1fr));gap:5px}
|
||||||
|
.stat-grid{font-size:clamp(8px,1.9vh,10px);gap:5px 12px}
|
||||||
|
.lb-row{grid-template-columns:24px 1fr 40px 50px 62px;font-size:clamp(7px,1.6vh,9px)}
|
||||||
|
#b-go,#b-hangar,#b-codex,#b-rush{min-width:min(40vw,180px)}
|
||||||
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
|
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
|
||||||
<link rel="icon" href="data:,">
|
<link rel="icon" href="data:,">
|
||||||
<title>星尘突击队 STAR RAID</title>
|
<title>星尘突击队 STAR RAID</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
|||||||
@ -2,7 +2,21 @@
|
|||||||
/* ================= 全局状态 ================= */
|
/* ================= 全局状态 ================= */
|
||||||
const cv=$("game"),ctx=cv.getContext("2d");
|
const cv=$("game"),ctx=cv.getContext("2d");
|
||||||
ctx.imageSmoothingEnabled=false;
|
ctx.imageSmoothingEnabled=false;
|
||||||
const W=240,H=320;
|
let W=240,H=320;
|
||||||
|
/* 动态视口适配(手机/折叠屏/平板):
|
||||||
|
竖屏/方形(高>=宽):占满全屏——宽固定 240,高按屏幕比例动态(限幅 [280,640])
|
||||||
|
横屏(高<宽):保持标准竖屏 3:4 逻辑分辨率(240x320),CSS 层 letterbox 居中显示
|
||||||
|
逻辑分辨率随屏变化,canvas 拉伸铺满游戏区域,像素不变形;所有实体坐标均为相对 W/H,安全。 */
|
||||||
|
function fitViewport(){
|
||||||
|
const vw=Math.max(1,window.innerWidth), vh=Math.max(1,window.innerHeight);
|
||||||
|
if(vh>=vw){
|
||||||
|
W=240; H=clamp(Math.round(240*vh/vw),280,640);
|
||||||
|
}else{
|
||||||
|
W=240; H=320;
|
||||||
|
}
|
||||||
|
cv.width=W; cv.height=H;
|
||||||
|
if(typeof initStars==="function")initStars();
|
||||||
|
}
|
||||||
let G=null,UI="title";
|
let G=null,UI="title";
|
||||||
function newRun(mode,shipKey,diff){
|
function newRun(mode,shipKey,diff){
|
||||||
const ship=SHIPS[shipKey],m=ship.mod,meta=SAVE.m;
|
const ship=SHIPS[shipKey],m=ship.mod,meta=SAVE.m;
|
||||||
|
|||||||
@ -76,3 +76,9 @@ function startHomeSim() {
|
|||||||
G.demoSim = { home: true };
|
G.demoSim = { home: true };
|
||||||
G.homeSim = true;
|
G.homeSim = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================= 视口自适应(手机/折叠屏/平板) =================
|
||||||
|
首次加载即适配当前屏幕;旋转/缩放时重新计算逻辑分辨率并铺满全屏 */
|
||||||
|
addEventListener("resize",fitViewport);
|
||||||
|
addEventListener("orientationchange",()=>setTimeout(fitViewport,250));
|
||||||
|
fitViewport();
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/* ================= 背景:星空与星云 ================= */
|
/* ================= 背景:星空与星云 ================= */
|
||||||
const STARS=[[],[],[]];
|
const STARS=[[],[],[]];
|
||||||
for(let i=0;i<3;i++)for(let j=0;j<26-i*6;j++)STARS[i].push({x:rnd(W),y:rnd(H),s:(0.35+i*0.4),sz:i===2?2:1,col:i===2?pick(["#aab8d8","#8fa8d8","#c0a8c8"]):"#3f4c74"});
|
/* 星星按视口面积重建:fitViewport 改变逻辑分辨率后调用,保持星空密度一致 */
|
||||||
|
function initStars(){
|
||||||
|
const k=(W*H)/(240*320);
|
||||||
|
for(let i=0;i<3;i++){STARS[i].length=0;
|
||||||
|
const n=Math.round((26-i*6)*k);
|
||||||
|
for(let j=0;j<n;j++)STARS[i].push({x:rnd(W),y:rnd(H),s:(0.35+i*0.4),sz:i===2?2:1,col:i===2?pick(["#aab8d8","#8fa8d8","#c0a8c8"]):"#3f4c74"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initStars();
|
||||||
const NEB=["#131c3f","#33102a","#0f2a1c","#101a33","#2a1030","#330f0f"];
|
const NEB=["#131c3f","#33102a","#0f2a1c","#101a33","#2a1030","#330f0f"];
|
||||||
let nebY=0,planet=null;
|
let nebY=0,planet=null;
|
||||||
function drawBG(dt){
|
function drawBG(dt){
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user