webgal-engine 4.5.17 → 4.5.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/OPPOSans-R-tAcFw8I3.ttf.gz +0 -0
- package/dist/assets/{LXGWWenKai-Regular-9375313a.ttf → ResourceHanRoundedCN-Regular-C1HdCLVq.ttf} +0 -0
- package/dist/assets/ResourceHanRoundedCN-Regular-C1HdCLVq.ttf.gz +0 -0
- package/dist/assets/SourceHanSerifCN-Regular-B_f-kQ2u.ttf.gz +0 -0
- package/dist/assets/conentsCash-BBWvsVB4.js +1 -0
- package/dist/assets/index-CkOq6uhz.css +1 -0
- package/dist/assets/index-CkOq6uhz.css.gz +0 -0
- package/dist/assets/index-MdzLVmuf.js +4137 -0
- package/dist/assets/index-MdzLVmuf.js.gz +0 -0
- package/dist/assets/{index.es-7d7e6d15.js → index.es-BeRKt7_j.js} +4 -4
- package/dist/assets/index.es-BeRKt7_j.js.gz +0 -0
- package/dist/assets/{initRegister-fdb36053.js → initRegister-xwJOf8RF.js} +1 -1
- package/dist/assets/initRegister-xwJOf8RF.js.gz +0 -0
- package/dist/index.html +136 -43
- package/dist/webgal-serviceworker.js +81 -58
- package/package.json +8 -8
- package/dist/assets/LXGWWenKai-Regular-9375313a.ttf.gz +0 -0
- package/dist/assets/OPPOSans-R-ea925359.ttf.gz +0 -0
- package/dist/assets/SourceHanSerifCN-Regular-1e60cc2e.ttf.gz +0 -0
- package/dist/assets/conentsCash-75763c1a.js +0 -1
- package/dist/assets/index-49446313.js +0 -4133
- package/dist/assets/index-49446313.js.gz +0 -0
- package/dist/assets/index-52a967b4.css +0 -1
- package/dist/assets/index-52a967b4.css.gz +0 -0
- package/dist/assets/index.es-7d7e6d15.js.gz +0 -0
- package/dist/assets/initRegister-fdb36053.js.gz +0 -0
- /package/dist/assets/{OPPOSans-R-ea925359.ttf → OPPOSans-R-tAcFw8I3.ttf} +0 -0
- /package/dist/assets/{SourceHanSerifCN-Regular-1e60cc2e.ttf → SourceHanSerifCN-Regular-B_f-kQ2u.ttf} +0 -0
- /package/dist/assets/{dialog-d5b91235.mp3 → dialog-BDvwibdp.mp3} +0 -0
- /package/dist/assets/{page-flip-1-7df32409.mp3 → page-flip-1-CZ8VQh4O.mp3} +0 -0
- /package/dist/assets/{switch-1-99b576bc.mp3 → switch-1-DI-7VpPw.mp3} +0 -0
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as B,W as z,C as D,b as G,a as N,S as U,c as R,B as O,R as X}from"./index-
|
|
1
|
+
import{r as B,W as z,C as D,b as G,a as N,S as U,c as R,B as O,R as X}from"./index-MdzLVmuf.js";const $=(b,W,k,v,E,M,m)=>{const w=z.gameplay.pixiStage,x=W==="foreground"?w.foregroundEffectsContainer:w.backgroundEffectsContainer,p=R.width,a=R.height,c=new D;c.angle=m;const C=c.rotation,y=Math.abs(Math.cos(C)),d=Math.abs(Math.sin(C)),i=p*y+a*d,f=p*d+a*y;c.width=i,c.height=f,c.pivot.set(i/2,f/2),c.position.set(p/2,a/2),x.addChild(c);const r=new G(E,{scale:!0,position:!0,rotation:!0,uvs:!1,alpha:!0});c.addChild(r);const u=[],I=N.from("./game/tex/cherryBlossoms.webp"),S=(h,l)=>h+Math.random()*(l-h);for(let h=0;h<E;h++){const l=Math.random()*Math.PI*2,n=U.from(I);n.anchor.set(.5),n.x=Math.random()*i,n.y=Math.random()*f,n.rotation=Math.random()*Math.PI*2,n.scale.set(Math.cos(l)*M,Math.sin(l)*M),n.speed=(S(.5,2)+S(.1,1))*k,n.rotationSpeed=Math.random()*.015*(Math.random()<.5?1:-1),n.positionPhase=Math.random()*Math.PI*2,n.scalePhase=l,u.push(n),r.addChild(n)}function A(h){const l=Date.now()/1e3;for(const n of u){const P=Math.sin(l+n.positionPhase)*v;n.x+=P*h,n.y+=n.speed*h,n.rotation+=n.rotationSpeed*h;const H=Math.cos(l+n.scalePhase)*M,F=Math.sin(l+n.scalePhase)*M;n.scale.set(H,F);const T=Math.abs(n.width*M),t=Math.abs(n.height*M);n.x+T/2<-i?n.x=i+T/2:n.x-T/2>i&&(n.x=-i-T/2),n.y-t/2>f&&(n.x=Math.random()*i,n.y=-Math.random()*50-t,n.positionPhase=Math.random()*Math.PI*2,n.scalePhase=Math.random()*Math.PI*2,n.speed=(S(.5,2)+S(.1,1))*k,n.rotationSpeed=Math.random()*.015*(Math.random()<.5?1:-1))}}return w.registerAnimation({setStartState:()=>{},setEndState:()=>{},tickerFunc:A},b),{container:c,tickerKey:b}};B("cherryBlossoms",{fg:()=>$("cherry-blossoms-foreground-ticker","foreground",2,3,100,.05,0),bg:()=>$("cherry-blossoms-background-ticker","background",1,2,300,.025,0)});const L=(b,W,k,v,E,M)=>{const m=z.gameplay.pixiStage;m.currentApp;const w=W==="foreground"?m.foregroundEffectsContainer:m.backgroundEffectsContainer,x=R.width,p=R.height,a=new D;a.angle=M;const c=a.rotation,C=Math.abs(Math.cos(c)),y=Math.abs(Math.sin(c)),d=x*C+p*y,i=x*y+p*C;a.width=d,a.height=i,a.pivot.set(d/2,i/2),a.position.set(x/2,p/2),w.addChild(a);const f=new G(v,{scale:!0,position:!0,rotation:!0,alpha:!0,uvs:!1});a.addChild(f);const r=[],u=[],I="./game/tex/rain.png",S=128,A=640,h=5,l=[10,5,2,2,1],n=t=>{if(!t||t.length===0)return 0;const e=t.reduce((o,g)=>o+g,0);if(e<=0)return Math.floor(Math.random()*t.length);let s=Math.random()*e;for(let o=0;o<t.length;o++){if(s<t[o])return o;s-=t[o]}return t.length-1},P=(t,e=!1)=>{const s=Math.random()*.5+.5;t.scale.set(E*s),t.anchor.set(.5),e?(t.x=Math.random()*d,t.y=Math.random()*i):(t.x=Math.random()*d,t.y=-Math.random()*50-t.height),t.alpha=Math.random()*.5+.5,t.vy=(Math.random()*.4+.8)*k},H=()=>{let t;r.length===h?t=n(l):t=Math.floor(Math.random()*r.length),t=Math.max(0,Math.min(t,r.length-1));const e=new U(r[t]);return P(e,!0),e},F=t=>{for(const e of u)e.y+=e.vy*t,(e.y-e.height/2>i||e.x<-e.width||e.x>d+e.width)&&P(e,!1)};return(()=>{for(r.length=0;u.length>0;)u.pop();f.removeChildren();const t=O.from(I),e=()=>{var s;if(t.valid)for(let o=0;o<h;o++){const g=new X(o*S,0,S,A);r.push(new N(t,g))}if(r.length===0){console.error("Failed to create any raindrop textures. Cannot create sprites.");return}(s=r[0])!=null&&s.valid||console.warn("First raindrop texture is invalid after creation. Sprites might not render correctly.");for(let o=0;o<v;o++){const g=H();f.addChild(g),u.push(g)}m.registerAnimation({setStartState:()=>{},setEndState:()=>{},tickerFunc:F},b)};t.valid?e():(t.once("loaded",()=>{e()}),t.once("error",s=>{console.error(`Error loading base texture ${I}:`,s),e()}))})(),{container:a,tickerKey:b}};B("rain",{fg:()=>L("rain-foreground-ticker","foreground",30,50,.4,1),bg:()=>L("rain-background-ticker","background",20,150,.3,1)});const _=(b,W,k,v,E,M)=>{const m=z.gameplay.pixiStage;m.currentApp;const w=W==="foreground"?m.foregroundEffectsContainer:m.backgroundEffectsContainer,x=R.width,p=R.height,a=new D;a.angle=M;const c=a.rotation,C=Math.abs(Math.cos(c)),y=Math.abs(Math.sin(c)),d=x*C+p*y,i=x*y+p*C;a.width=d,a.height=i,a.pivot.set(d/2,i/2),a.position.set(x/2,p/2),w.addChild(a);const f=new G(v,{scale:!0,position:!0,rotation:!0,alpha:!0,uvs:!1});a.addChild(f);const r=[],u=[],I="./game/tex/snow.png",S=128,A=128,h=10,l=[10,2,2,2,1,1,1,2,2,2],n=t=>{if(!t||t.length===0)return 0;const e=t.reduce((o,g)=>o+g,0);if(e<=0)return Math.floor(Math.random()*t.length);let s=Math.random()*e;for(let o=0;o<t.length;o++){if(s<t[o])return o;s-=t[o]}return t.length-1},P=(t,e=!1)=>{const s=Math.random()*.5+.5;t.scale.set(E*s),t.anchor.set(.5),e?(t.x=Math.random()*d,t.y=Math.random()*i):(t.x=Math.random()*d,t.y=-Math.random()*50-t.height),t.alpha=Math.random()*.2+.8,t.vy=(Math.random()*.4+.8)*k,t.vx=(Math.random()-.5)*.25*k,t.rotationSpeed=(Math.random()-.5)*.005},H=()=>{let t;r.length===h?t=n(l):t=Math.floor(Math.random()*r.length),t=Math.max(0,Math.min(t,r.length-1));const e=new U(r[t]);return P(e,!0),e},F=t=>{for(const e of u)e.y+=e.vy*t,e.x+=e.vx*t,e.rotation+=e.rotationSpeed*t,(e.y-e.height/2>i||e.x<-e.width||e.x>d+e.width)&&P(e,!1)};return(()=>{for(r.length=0;u.length>0;)u.pop();f.removeChildren();const t=O.from(I),e=()=>{var s;if(t.valid)for(let o=0;o<h;o++){const g=new X(o*S,0,S,A);r.push(new N(t,g))}if(r.length===0){console.error("Failed to create any snowflake textures. Cannot create sprites.");return}(s=r[0])!=null&&s.valid||console.warn("First snowflake texture is invalid after creation. Sprites might not render correctly.");for(let o=0;o<v;o++){const g=H();f.addChild(g),u.push(g)}m.registerAnimation({setStartState:()=>{},setEndState:()=>{},tickerFunc:F},b)};t.valid?e():(t.once("loaded",()=>{e()}),t.once("error",s=>{console.error(`Error loading base texture ${I}:`,s),e()}))})(),{container:a,tickerKey:b}};B("snow",{fg:()=>_("snow-foreground-ticker","foreground",3,250,.4,0),bg:()=>_("snow-background-ticker","background",1,750,.2,0)});B("heavySnow",{fg:()=>_("heavy-snow-foreground-ticker","foreground",20,1e3,.6,-75),bg:()=>_("heavy-snow-background-ticker","background",10,2e3,.3,-80)});
|
|
Binary file
|
package/dist/index.html
CHANGED
|
@@ -7,6 +7,15 @@
|
|
|
7
7
|
<link rel="manifest" href="./manifest.json" />
|
|
8
8
|
<title>WebGAL</title>
|
|
9
9
|
<style>
|
|
10
|
+
html,
|
|
11
|
+
body {
|
|
12
|
+
margin: 0;
|
|
13
|
+
background: black;
|
|
14
|
+
width: 100%;
|
|
15
|
+
height: 100%;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
}
|
|
18
|
+
|
|
10
19
|
.html-body__effect-background {
|
|
11
20
|
height: 100vh;
|
|
12
21
|
width: 100vw;
|
|
@@ -17,6 +26,20 @@
|
|
|
17
26
|
position: absolute;
|
|
18
27
|
top: 0;
|
|
19
28
|
left: 0;
|
|
29
|
+
background-color: black;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.html-body__effect-background-overlay {
|
|
33
|
+
height: 100%;
|
|
34
|
+
width: 100%;
|
|
35
|
+
background-position: center;
|
|
36
|
+
background-repeat: no-repeat;
|
|
37
|
+
background-size: cover;
|
|
38
|
+
position: absolute;
|
|
39
|
+
top: 0;
|
|
40
|
+
left: 0;
|
|
41
|
+
background-color: black;
|
|
42
|
+
opacity: 0;
|
|
20
43
|
}
|
|
21
44
|
|
|
22
45
|
.html-body__title-enter {
|
|
@@ -111,13 +134,16 @@
|
|
|
111
134
|
.title-enter-container__link-to-github > div {
|
|
112
135
|
padding: 0 0 0.25em 0;
|
|
113
136
|
}
|
|
137
|
+
|
|
114
138
|
</style>
|
|
115
|
-
<script type="module" crossorigin src="./assets/index-
|
|
116
|
-
<link rel="stylesheet" href="./assets/index-
|
|
139
|
+
<script type="module" crossorigin src="./assets/index-MdzLVmuf.js"></script>
|
|
140
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CkOq6uhz.css">
|
|
117
141
|
</head>
|
|
118
142
|
<body>
|
|
119
143
|
<!-- 背景模糊 -->
|
|
120
|
-
<div class="html-body__effect-background"
|
|
144
|
+
<div id="ebg" class="html-body__effect-background">
|
|
145
|
+
<div id="ebgOverlay" class="html-body__effect-background-overlay"></div>
|
|
146
|
+
</div>
|
|
121
147
|
<!-- 落地页 -->
|
|
122
148
|
<div class="html-body__title-enter">
|
|
123
149
|
<div class="title-enter__initial-background"></div>
|
|
@@ -135,29 +161,70 @@
|
|
|
135
161
|
<div id="html-body__panic-overlay"></div>
|
|
136
162
|
<!-- 应用挂载点 -->
|
|
137
163
|
<div id="root"></div>
|
|
164
|
+
<script>
|
|
165
|
+
(() => {
|
|
166
|
+
const userAgent = navigator.userAgent || '';
|
|
167
|
+
const platform = navigator.userAgentData?.platform || navigator.platform || '';
|
|
168
|
+
const maxTouchPoints = navigator.maxTouchPoints || 0;
|
|
169
|
+
const isIOSPhone = /iPhone|iPod/i.test(userAgent);
|
|
170
|
+
const isIPad = /iPad/i.test(userAgent) || (/Mac/i.test(platform) && maxTouchPoints > 1);
|
|
171
|
+
|
|
172
|
+
window.__WEBGAL_DEVICE_INFO__ = {
|
|
173
|
+
isIOS: isIOSPhone || isIPad,
|
|
174
|
+
isIOSPhone,
|
|
175
|
+
isIPad,
|
|
176
|
+
};
|
|
177
|
+
})();
|
|
178
|
+
</script>
|
|
138
179
|
<!-- 在窗口大小改变时进行强制缩放 -->
|
|
139
180
|
<script>
|
|
140
181
|
(() => {
|
|
141
|
-
const
|
|
182
|
+
const deviceInfo = window.__WEBGAL_DEVICE_INFO__ ?? { isIOS: false };
|
|
183
|
+
const isIOS = deviceInfo.isIOS;
|
|
184
|
+
const layoutConfig = isIOS
|
|
185
|
+
? {
|
|
186
|
+
bottomInset: 15,
|
|
187
|
+
resizeDelay: 500,
|
|
188
|
+
viewport:
|
|
189
|
+
'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover',
|
|
190
|
+
hideEffectBackground: true,
|
|
191
|
+
}
|
|
192
|
+
: {
|
|
193
|
+
bottomInset: 0,
|
|
194
|
+
resizeDelay: 0,
|
|
195
|
+
viewport: 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no',
|
|
196
|
+
hideEffectBackground: false,
|
|
197
|
+
};
|
|
198
|
+
const root = document.querySelector('#root');
|
|
199
|
+
const titleEnter = document.querySelector('.html-body__title-enter');
|
|
200
|
+
const effectBackground = document.querySelector('.html-body__effect-background');
|
|
201
|
+
let viewportMeta = document.querySelector('meta[name="viewport"]');
|
|
202
|
+
|
|
203
|
+
const ensureViewportMeta = () => {
|
|
204
|
+
if (!viewportMeta) {
|
|
205
|
+
viewportMeta = document.createElement('meta');
|
|
206
|
+
viewportMeta.name = 'viewport';
|
|
207
|
+
document.head.appendChild(viewportMeta);
|
|
208
|
+
}
|
|
209
|
+
return viewportMeta;
|
|
210
|
+
};
|
|
211
|
+
|
|
142
212
|
const resize = () => {
|
|
143
213
|
const targetHeight = 1440; // 目标高度
|
|
144
214
|
const targetWidth = 2560; // 目标宽度
|
|
145
|
-
|
|
146
215
|
const h = window.innerHeight; // 窗口高度
|
|
147
216
|
const w = window.innerWidth; // 窗口宽度
|
|
148
|
-
const
|
|
217
|
+
const layoutHeight = Math.max(h - layoutConfig.bottomInset, 1);
|
|
218
|
+
const zoomH = layoutHeight / targetHeight; // 以窗口高度为基准的变换比
|
|
149
219
|
const zoomW = w / targetWidth; // 以窗口宽度为基准的变换比
|
|
150
220
|
const zoomH2 = w / targetHeight; // 竖屏时以窗口高度为基础的变换比
|
|
151
|
-
const zoomW2 =
|
|
152
|
-
let mh = (targetHeight -
|
|
221
|
+
const zoomW2 = layoutHeight / targetWidth; // 竖屏时以窗口宽度为基础的变换比
|
|
222
|
+
let mh = (targetHeight - layoutHeight) / 2; // y轴移动距离
|
|
153
223
|
let mw = (targetWidth - w) / 2; // x轴移动距离
|
|
154
224
|
let mh2os = targetWidth / 2 - w / 2; // 竖屏时 y轴移动距离
|
|
155
|
-
let mw2os = targetHeight / 2 -
|
|
225
|
+
let mw2os = targetHeight / 2 - layoutHeight / 2; // 竖屏时 x轴移动距离
|
|
156
226
|
let transform = '';
|
|
157
227
|
let effectBackgroundTransform = '';
|
|
158
|
-
const root = document.querySelector('#root'); // 获取根元素
|
|
159
|
-
const titleEnter = document.querySelector('.html-body__title-enter');
|
|
160
|
-
const effectBackground = document.querySelector('.html-body__effect-background');
|
|
161
228
|
const elements = [root, titleEnter];
|
|
162
229
|
if (w > h) {
|
|
163
230
|
if (effectBackground) {
|
|
@@ -193,6 +260,11 @@
|
|
|
193
260
|
// iOS 不强制旋转
|
|
194
261
|
if (isIOS) {
|
|
195
262
|
const zoomWi = w / targetWidth;
|
|
263
|
+
if (effectBackground) {
|
|
264
|
+
effectBackground.style.height = `100vh`;
|
|
265
|
+
effectBackground.style.width = `100vw`;
|
|
266
|
+
effectBackgroundTransform = '';
|
|
267
|
+
}
|
|
196
268
|
transform = `translate(${-mw}px, ${-mh}px) ` + `scale(${zoomWi},${zoomWi}) `;
|
|
197
269
|
}
|
|
198
270
|
}
|
|
@@ -205,42 +277,51 @@
|
|
|
205
277
|
}
|
|
206
278
|
}
|
|
207
279
|
};
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
metaTag.content = 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no';
|
|
214
|
-
// 将该标签添加到 head 中
|
|
215
|
-
document.head.appendChild(metaTag);
|
|
216
|
-
resize();
|
|
217
|
-
window.onload = resize;
|
|
218
|
-
window.onresize = resize;
|
|
219
|
-
// 监听键盘 F11 键按下事件,全屏时触发页面调整
|
|
220
|
-
document.onkeydown = (e) => {
|
|
221
|
-
if (e && e.key === 'F11') {
|
|
222
|
-
setTimeout(() => {
|
|
223
|
-
resize();
|
|
224
|
-
}, 100);
|
|
280
|
+
let iosResizeTimer = null;
|
|
281
|
+
const scheduleResize = () => {
|
|
282
|
+
if (layoutConfig.resizeDelay > 0) {
|
|
283
|
+
if (iosResizeTimer) {
|
|
284
|
+
window.clearTimeout(iosResizeTimer);
|
|
225
285
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
286
|
+
iosResizeTimer = window.setTimeout(() => {
|
|
287
|
+
resize();
|
|
288
|
+
iosResizeTimer = null;
|
|
289
|
+
}, layoutConfig.resizeDelay);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
resize();
|
|
293
|
+
};
|
|
294
|
+
if (isIOS) {
|
|
234
295
|
const styleTag = document.createElement('style');
|
|
235
|
-
styleTag.textContent =
|
|
296
|
+
styleTag.textContent = `* { font-synthesis: none !important; }`;
|
|
297
|
+
if (layoutConfig.hideEffectBackground) {
|
|
298
|
+
styleTag.textContent += `
|
|
299
|
+
#ebg,
|
|
300
|
+
#ebgOverlay {
|
|
301
|
+
display: none !important;
|
|
302
|
+
}
|
|
303
|
+
`;
|
|
304
|
+
}
|
|
236
305
|
document.head.appendChild(styleTag);
|
|
237
306
|
}
|
|
307
|
+
ensureViewportMeta().content = layoutConfig.viewport;
|
|
308
|
+
scheduleResize();
|
|
309
|
+
window.onload = scheduleResize;
|
|
310
|
+
window.onresize = scheduleResize;
|
|
311
|
+
// 监听键盘 F11 键按下事件,全屏时触发页面调整
|
|
312
|
+
document.onkeydown = (e) => {
|
|
313
|
+
if (e && e.key === 'F11') {
|
|
314
|
+
setTimeout(() => {
|
|
315
|
+
scheduleResize();
|
|
316
|
+
}, 100);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
238
319
|
})();
|
|
239
320
|
</script>
|
|
240
321
|
<!-- 注册 Service Worker -->
|
|
241
322
|
<script>
|
|
242
323
|
(() => {
|
|
243
|
-
const isIOS =
|
|
324
|
+
const isIOS = window.__WEBGAL_DEVICE_INFO__?.isIOS ?? false;
|
|
244
325
|
if ('serviceWorker' in navigator && !isIOS) {
|
|
245
326
|
navigator.serviceWorker
|
|
246
327
|
.register('./webgal-serviceworker.js')
|
|
@@ -256,7 +337,10 @@
|
|
|
256
337
|
<!-- 首屏加载 -->
|
|
257
338
|
<script>
|
|
258
339
|
(() => {
|
|
259
|
-
const isIOS =
|
|
340
|
+
const isIOS = window.__WEBGAL_DEVICE_INFO__?.isIOS ?? false;
|
|
341
|
+
const enterConfig = isIOS
|
|
342
|
+
? { skipAnimation: true, hideDelay: 0 }
|
|
343
|
+
: { skipAnimation: false, hideDelay: 2000 };
|
|
260
344
|
let enterPromiseResolve;
|
|
261
345
|
const enterPromise = new Promise((res) => {
|
|
262
346
|
enterPromiseResolve = res;
|
|
@@ -281,6 +365,17 @@
|
|
|
281
365
|
});
|
|
282
366
|
/** 点击屏幕,进入引擎主界面 */
|
|
283
367
|
const enter = () => {
|
|
368
|
+
const titleEnter = document.querySelector('.html-body__title-enter');
|
|
369
|
+
if (enterConfig.skipAnimation) {
|
|
370
|
+
if (titleEnter) {
|
|
371
|
+
titleEnter.style.pointerEvents = 'none';
|
|
372
|
+
titleEnter.style.transition = 'none';
|
|
373
|
+
titleEnter.style.opacity = '0';
|
|
374
|
+
titleEnter.style.display = 'none';
|
|
375
|
+
}
|
|
376
|
+
enterPromiseResolve();
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
284
379
|
const initialBackground = document.querySelector('.title-enter__initial-background');
|
|
285
380
|
if (initialBackground) {
|
|
286
381
|
initialBackground.style.opacity = '0';
|
|
@@ -295,7 +390,6 @@
|
|
|
295
390
|
whiteBackground.style.opacity = '1';
|
|
296
391
|
}
|
|
297
392
|
}, 50); // 在50ms后开始显示白色渐变
|
|
298
|
-
const titleEnter = document.querySelector('.html-body__title-enter');
|
|
299
393
|
setTimeout(() => {
|
|
300
394
|
if (titleEnter) titleEnter.style.opacity = '0';
|
|
301
395
|
}, 500); // 500ms后开始降低落地页透明度
|
|
@@ -307,7 +401,7 @@
|
|
|
307
401
|
if (titleEnter) {
|
|
308
402
|
titleEnter.style.display = 'none';
|
|
309
403
|
}
|
|
310
|
-
},
|
|
404
|
+
}, enterConfig.hideDelay); // 将落地页设置为不显示
|
|
311
405
|
enterPromiseResolve();
|
|
312
406
|
};
|
|
313
407
|
const titleEnter = document.querySelector('.html-body__title-enter');
|
|
@@ -360,6 +454,5 @@
|
|
|
360
454
|
})();
|
|
361
455
|
</script>
|
|
362
456
|
<!-- main文件 -->
|
|
363
|
-
|
|
364
457
|
</body>
|
|
365
458
|
</html>
|
|
@@ -1,63 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const CACHE_NAME = 'webgal-critical-assets-v3';
|
|
2
|
+
const GAME_PREFIX = '/game/';
|
|
3
|
+
const CRITICAL_PATHS = ['/game/background/', '/game/figure/', '/game/bgm/', '/game/vocal/', '/game/video/'];
|
|
4
|
+
const LOG_PREFIX = '[WebGAL SW]';
|
|
5
|
+
const loggedKeys = new Set();
|
|
6
|
+
|
|
7
|
+
function logOnce(key, ...args) {
|
|
8
|
+
if (loggedKeys.has(key)) return;
|
|
9
|
+
loggedKeys.add(key);
|
|
10
|
+
console.log(LOG_PREFIX, ...args);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
self.addEventListener('install', (event) => {
|
|
14
|
+
logOnce('install', `install ${CACHE_NAME}`);
|
|
15
|
+
event.waitUntil(self.skipWaiting());
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
self.addEventListener('activate', (event) => {
|
|
19
|
+
logOnce('activate', `activate ${CACHE_NAME}`);
|
|
20
|
+
event.waitUntil(
|
|
21
|
+
(async () => {
|
|
22
|
+
const keys = await caches.keys();
|
|
23
|
+
await Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key)));
|
|
24
|
+
await self.clients.claim();
|
|
25
|
+
})(),
|
|
26
|
+
);
|
|
4
27
|
});
|
|
5
28
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const url =
|
|
9
|
-
|
|
10
|
-
if (
|
|
11
|
-
|
|
29
|
+
function isCriticalGameRequest(request) {
|
|
30
|
+
if (request.method !== 'GET') return false;
|
|
31
|
+
const url = new URL(request.url);
|
|
32
|
+
if (url.origin !== self.location.origin) return false;
|
|
33
|
+
if (!url.pathname.startsWith(GAME_PREFIX)) return false;
|
|
34
|
+
return CRITICAL_PATHS.some((prefix) => url.pathname.startsWith(prefix));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Stale-while-revalidate: return cached response immediately, then update cache in background.
|
|
38
|
+
async function staleWhileRevalidate(request) {
|
|
39
|
+
const cache = await caches.open(CACHE_NAME);
|
|
40
|
+
const cached = await cache.match(request.url);
|
|
41
|
+
|
|
42
|
+
const fetchAndUpdate = async () => {
|
|
43
|
+
try {
|
|
44
|
+
const response = await fetch(request);
|
|
45
|
+
if (response.ok) {
|
|
46
|
+
await cache.put(request.url, response.clone());
|
|
47
|
+
}
|
|
48
|
+
return response;
|
|
49
|
+
} catch (e) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (cached) {
|
|
55
|
+
logOnce(`hit:${request.url}`, 'cache hit (revalidating):', new URL(request.url).pathname);
|
|
56
|
+
// Revalidate in background — don't await
|
|
57
|
+
fetchAndUpdate();
|
|
58
|
+
return cached;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// No cache — must wait for network
|
|
62
|
+
const response = await fetch(request);
|
|
63
|
+
if (response.ok) {
|
|
64
|
+
await cache.put(request.url, response.clone());
|
|
65
|
+
logOnce(`cache:${request.url}`, 'cached:', new URL(request.url).pathname);
|
|
12
66
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return fetch(event.request)
|
|
26
|
-
.then(function (networkResponse) {
|
|
27
|
-
console.log('%cCACHED: ' + url, 'color: #005CAF; padding: 2px;');
|
|
28
|
-
if (networkResponse.status === 206 && event.request.headers.has('range')) {
|
|
29
|
-
// 如果是部分响应且请求带有Range头,则创建新的请求,将完整响应返回给客户端
|
|
30
|
-
// eslint-disable-next-line max-nested-callbacks
|
|
31
|
-
return fetch(event.request.url).then(function (fullNetworkResponse) {
|
|
32
|
-
const headers = {};
|
|
33
|
-
for (let entry of fullNetworkResponse.headers.entries()) {
|
|
34
|
-
headers[entry[0]] = entry[1];
|
|
35
|
-
}
|
|
36
|
-
const fullResponse = new Response(fullNetworkResponse.body, {
|
|
37
|
-
status: fullNetworkResponse.status,
|
|
38
|
-
statusText: fullNetworkResponse.statusText,
|
|
39
|
-
headers: headers,
|
|
40
|
-
});
|
|
41
|
-
const clonedResponse = fullResponse.clone();
|
|
42
|
-
// eslint-disable-next-line max-nested-callbacks
|
|
43
|
-
caches.open('my-cache').then(function (cache) {
|
|
44
|
-
cache.put(event.request, clonedResponse);
|
|
45
|
-
});
|
|
46
|
-
return fullResponse;
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
const clonedResponse = networkResponse.clone();
|
|
50
|
-
// eslint-disable-next-line max-nested-callbacks
|
|
51
|
-
caches.open('my-cache').then(function (cache) {
|
|
52
|
-
cache.put(event.request, clonedResponse);
|
|
53
|
-
});
|
|
54
|
-
return networkResponse;
|
|
55
|
-
})
|
|
56
|
-
.catch(function (error) {
|
|
57
|
-
console.error('Fetching failed:', error);
|
|
58
|
-
throw error;
|
|
59
|
-
});
|
|
60
|
-
}),
|
|
61
|
-
);
|
|
67
|
+
return response;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
self.addEventListener('fetch', (event) => {
|
|
71
|
+
const { request } = event;
|
|
72
|
+
if (!isCriticalGameRequest(request)) return;
|
|
73
|
+
|
|
74
|
+
// Audio/video range requests are passed through to avoid partial-content edge cases.
|
|
75
|
+
if (request.headers.has('range')) {
|
|
76
|
+
logOnce(`range:${request.url}`, 'range passthrough:', new URL(request.url).pathname);
|
|
77
|
+
event.respondWith(fetch(request));
|
|
78
|
+
return;
|
|
62
79
|
}
|
|
80
|
+
|
|
81
|
+
event.respondWith(
|
|
82
|
+
staleWhileRevalidate(request).catch(() => {
|
|
83
|
+
return fetch(request);
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
63
86
|
});
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webgal-engine",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.19",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite --host --port 3000",
|
|
6
|
-
"build": "cross-env NODE_ENV=production tsc && vite build --base=./",
|
|
6
|
+
"build": "node scripts/update-engine-version.js && cross-env NODE_ENV=production tsc && vite build --base=./",
|
|
7
7
|
"preview": "vite preview",
|
|
8
8
|
"lint": "eslint src/** --fix",
|
|
9
9
|
"prepublishOnly": "npm run build"
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"@icon-park/react": "^1.4.2",
|
|
14
14
|
"@reduxjs/toolkit": "^1.8.1",
|
|
15
15
|
"angular-expressions": "^1.4.3",
|
|
16
|
-
"axios": "^
|
|
16
|
+
"axios": "^1.13.5",
|
|
17
17
|
"cloudlogjs": "^1.0.9",
|
|
18
18
|
"gifuct-js": "^2.1.2",
|
|
19
19
|
"i18next": "^22.4.15",
|
|
20
20
|
"localforage": "^1.10.0",
|
|
21
|
-
"lodash": "^4.17.
|
|
21
|
+
"lodash": "^4.17.23",
|
|
22
22
|
"mitt": "^3.0.0",
|
|
23
23
|
"modern-css-reset": "^1.4.0",
|
|
24
24
|
"pixi-filters": "^4.2.0",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"@types/react": "^17.0.33",
|
|
40
40
|
"@types/react-dom": "^17.0.10",
|
|
41
41
|
"@types/uuid": "^8.3.4",
|
|
42
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
43
|
-
"@typescript-eslint/parser": "^
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
43
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
44
44
|
"@vitejs/plugin-react": "^4.0.4",
|
|
45
45
|
"cross-env": "^7.0.3",
|
|
46
|
-
"eslint": "^
|
|
46
|
+
"eslint": "^9.26.0",
|
|
47
47
|
"eslint-config-alloy": "^4.5.1",
|
|
48
48
|
"eslint-config-prettier": "^8.5.0",
|
|
49
49
|
"eslint-plugin-prettier": "^4.2.1",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"rollup-plugin-visualizer": "^5.6.0",
|
|
54
54
|
"typescript": "^4.5.4",
|
|
55
55
|
"unplugin-info": "^1.2.2",
|
|
56
|
-
"vite": "^4.
|
|
56
|
+
"vite": "^5.4.21",
|
|
57
57
|
"vite-plugin-compression": "^0.5.1"
|
|
58
58
|
}
|
|
59
59
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var e=Object.defineProperty;var c=(n,t,s)=>t in n?e(n,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):n[t]=s;var o=(n,t,s)=>(c(n,typeof t!="symbol"?t+"":t,s),s);class h{constructor(){o(this,"_content","")}push(t){this._content=t}pop(){const t=this._content;return this._content="",t}}class i{constructor(){o(this,"_content","")}push(t){this._content=t}pop(){const t=this._content;return this._content="",t}}const _=new h,p=new i;export{h as FigureConentsCash,i as VoiceConentsCash,_ as figureCash,p as voiceCash};
|