Reverse the animation when popping the kick/ban notice.

This commit is contained in:
flash 2024-02-25 02:39:14 +00:00
parent ddd802d3ff
commit 5ea5b1e030
3 changed files with 55 additions and 13 deletions

View file

@ -66,10 +66,27 @@ const MamiAudioContext = function() {
return await ctx.decodeAudioData(result.body()); return await ctx.decodeAudioData(result.body());
}, },
createSource: buffer => { createSource: (buffer, reverse) => {
if(ctx === undefined || buffer === undefined) if(ctx === undefined || buffer === undefined)
return new MamiAudioSourceDummy; return new MamiAudioSourceDummy;
if(reverse) {
const reverse = new AudioBuffer({
length: buffer.length,
numberOfChannels: buffer.numberOfChannels,
sampleRate: buffer.sampleRate,
});
const data = new Float32Array(buffer.length);
for(let i = 0; i < reverse.numberOfChannels; ++i) {
buffer.copyFromChannel(data, i, 0);
data.reverse();
reverse.copyToChannel(data, i, 0);
}
buffer = reverse;
}
const gain = ctx.createGain(); const gain = ctx.createGain();
gain.connect(mainGain); gain.connect(mainGain);

View file

@ -27,16 +27,16 @@ const MamiForceDisconnectNotice = function(banInfo) {
marqueeElem.append(<div class="baka-marquee-text">{marqueeString}</div>); marqueeElem.append(<div class="baka-marquee-text">{marqueeString}</div>);
const rng = new MamiRNG; const rng = new MamiRNG;
let sfxBuf, sfxSrc, bgmSrc; const rotate = rng.next(-20, 20);
let sfxBuf, bgmSrc;
const pub = { const pub = {
getElement: () => html, getElement: () => html,
onViewPush: async () => { onViewPush: async () => {
try { try {
sfxBuf = await mami.sound.library.loadBuffer('touhou:pichuun'); sfxBuf = await mami.sound.library.loadBuffer('touhou:pichuun');
sfxSrc = mami.sound.audio.createSource(sfxBuf);
} catch(ex) { } catch(ex) {
sfxBuf = sfxSrc = undefined; sfxBuf = undefined;
} }
try { try {
@ -48,16 +48,16 @@ const MamiForceDisconnectNotice = function(banInfo) {
}, },
onViewPop: async () => { onViewPop: async () => {
bgmSrc?.stop(); bgmSrc?.stop();
bgmSrc = sfxBuf = sfxSrc = undefined; bgmSrc = sfxBuf = undefined;
}, },
pushOn: async views => { pushOn: async views => {
const rotate = rng.next(-20, 20);
await views.push(pub, ctx => MamiAnimate({ await views.push(pub, ctx => MamiAnimate({
async: true, async: true,
duration: (sfxBuf?.duration ?? 1.4) * 1000, duration: (sfxBuf?.duration ?? 1.4) * 1000,
start: () => { start: () => {
sfxSrc?.play(); if(sfxBuf !== undefined)
mami.sound.audio.createSource(sfxBuf).play();
ctx.toElem.style.top = '-100%'; ctx.toElem.style.top = '-100%';
}, },
update: t => { update: t => {
@ -76,6 +76,33 @@ const MamiForceDisconnectNotice = function(banInfo) {
}, },
})); }));
}, },
popOff: async views => {
await views.pop(ctx => MamiAnimate({
async: true,
duration: (sfxBuf?.duration ?? 1.4) * 1000,
start: () => {
bgmSrc?.stop();
if(sfxBuf !== undefined)
mami.sound.audio.createSource(sfxBuf, true).play();
ctx.toElem.style.transform = `scale(1) rotate(${rotate}deg)`;
ctx.toElem.style.filter = 'grayscale(100%)';
},
update: t => {
const tOutBounce = MamiEasings.inBounce(t);
ctx.fromElem.style.top = `${tOutBounce * -100}%`;
const tOutExpo = MamiEasings.inExpo(t);
ctx.toElem.style.transform = `scale(${1 * tOutExpo}) rotate(${rotate - (rotate * tOutExpo)}deg)`;
ctx.toElem.style.filter = `grayscale(${100 - (tOutExpo * 100)}%)`;
},
end: () => {
ctx.fromElem.style.top = null;
ctx.toElem.style.transform = null;
ctx.toElem.style.filter = null;
},
}));
},
}; };
return pub; return pub;

View file

@ -391,12 +391,10 @@ Umi.UI.Settings = (function() {
type: 'button', type: 'button',
invoke: async button => { invoke: async button => {
button.disabled = true; button.disabled = true;
await (new MamiForceDisconnectNotice({ const notice = new MamiForceDisconnectNotice({ perma: true, type: 'ban' });
perma: true, await notice.pushOn(mami.views);
type: 'ban',
})).pushOn(mami.views);
await MamiSleep(5000); await MamiSleep(5000);
await mami.views.pop(); await notice.popOff(mami.views);
button.disabled = false; button.disabled = false;
}, },
}, },