悄悄话流星六改:头窄尾宽光楔、字由小到大、亮头、起步更快后段加速 (v26100170)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
52
js/app.js
52
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26100169';
|
||||
var VER = '26100170';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -3370,7 +3370,7 @@
|
||||
const fresh = l.findIndex(x => !x.mine && !seen.has(x.id));
|
||||
$('#wskBright').innerHTML = l.map((it, i) => {
|
||||
const h = hsh(it.id), c = i % cols, r = Math.floor(i / cols);
|
||||
const x = 24 + ((c + .5 + ((h % 100) / 100 - .5) * .7) / cols) * 70;
|
||||
const x = 36 + ((c + .5 + ((h % 100) / 100 - .5) * .7) / cols) * 58;
|
||||
const y = 21 + ((r + .5 + (((h >> 8) % 100) / 100 - .5) * .6) / rows) * 38;
|
||||
const sz = it.mine ? 9 : Math.round(4 + Math.min(it.hugs || 0, 30) / 30 * 6);
|
||||
return '<button type="button" class="wsk-st' + (it.mine ? ' mine' : '') + (seen.has(it.id) ? ' seen' : '') + (i === fresh && !seen.size ? ' hint' : '') +
|
||||
@@ -3421,37 +3421,47 @@
|
||||
const pr = page.getBoundingClientRect(), br = btn.getBoundingClientRect();
|
||||
const x0 = br.left + br.width / 2 - pr.left, y0 = br.top + br.height / 2 - pr.top;
|
||||
/* 瞄准左下(屏幕左边外、六成高处):越靠左起步角度越陡,保证在屏幕里拖得够长 */
|
||||
const th = Math.max(22, Math.min(50, Math.atan2(pr.height * .62 - y0, x0 + 30) * 180 / Math.PI)) * Math.PI / 180, dx = -Math.cos(th), dy = Math.sin(th), rot = -th * 180 / Math.PI;
|
||||
const th = Math.max(24, Math.min(55, Math.atan2(pr.height * .8 - y0, x0 + 30) * 180 / Math.PI)) * Math.PI / 180, dx = -Math.cos(th), dy = Math.sin(th), rot = -th * 180 / Math.PI;
|
||||
/* 六改(用户:「头是窄的,往后越来越宽;前面的字小,后面慢慢变大,形成流星尾巴;头特别亮往前滑;
|
||||
点完亮一下就开始滑,一点点变快,不要太慢也别太快」):
|
||||
字号从头到尾 12px → 26px 渐大,尾巴是一条从头部尖起、往后张开的光楔;
|
||||
运动 = 起步就有速度、缓缓提速,整句出来后再猛加速唰出去。 */
|
||||
const chars = [...String(it.text)], n = chars.length;
|
||||
const cw = n > 16 ? 21 : 25, gap = 20, body = gap + n * cw;
|
||||
const f0 = 12, f1 = n > 20 ? 21 : n > 12 ? 24 : 27, gap = 22;
|
||||
const fs = chars.map((c, k) => f0 + (f1 - f0) * Math.pow(n > 1 ? k / (n - 1) : 1, .85));
|
||||
const off = [];
|
||||
fs.reduce((d, f) => { off.push(d + f * .55); return d + f * 1.08; }, gap);
|
||||
const body = off.length ? off[n - 1] + fs[n - 1] * .6 : gap;
|
||||
const el = document.createElement('div');
|
||||
el.className = 'wmt' + (it.mine ? ' mine' : '');
|
||||
el.style.setProperty('--fs', (cw - 4) + 'px');
|
||||
el.innerHTML = '<i class="wmt-l"></i><i class="wmt-h"></i>' + chars.map(c => '<span>' + esc(c) + '</span>').join('');
|
||||
el.innerHTML = '<i class="wmt-l"></i><i class="wmt-c"></i><i class="wmt-h"></i>' + chars.map((c, k) => '<span style="font-size:' + fs[k].toFixed(1) + 'px">' + esc(c) + '</span>').join('');
|
||||
page.insertBefore(el, card);
|
||||
const line = el.children[0], head = el.children[1], sp = $$('span', el);
|
||||
/* 节奏:星闪 380ms → 慢飘(按字数给阅读时间,起步再缓一点)→ 750ms 加速唰出去 */
|
||||
const T0 = 380, T1 = Math.min(11000, 2400 + n * 300), T2 = 800, L1 = body + 60, v1 = L1 / (.94 * T1);
|
||||
const line = el.children[0], core = el.children[1], head = el.children[2], sp = $$('span', el);
|
||||
line.style.height = (f1 * 1.9).toFixed(0) + 'px';
|
||||
line.style.marginTop = (-f1 * .95).toFixed(0) + 'px';
|
||||
/* 节奏:星闪 420ms → 以约 90px/s 起步并缓缓提速,整句拖出来后再留 0.7 秒给眼睛 → 加速度猛增,1.3 秒内唰出屏幕 */
|
||||
const T0 = 420, v0 = .09, TR = (body + 20) / v0 + 700, A = .0018, TE = 1300;
|
||||
btn.classList.add('flare');
|
||||
const t0 = performance.now();
|
||||
const frame = now => {
|
||||
const t = now - t0;
|
||||
if (t < T0) { mt.raf = requestAnimationFrame(frame); return; }
|
||||
btn.classList.add('gone');
|
||||
const t1 = t - T0;
|
||||
let s, u = 0;
|
||||
if (t1 < T1) { const p = t1 / T1; s = L1 * (p < .12 ? p * p / .24 : p - .06) / .94; }
|
||||
else { u = Math.min(1, (t1 - T1) / T2); s = L1 + v1 * T2 * u + 1600 * Math.pow(u, 2.6); }
|
||||
const hx = x0 + dx * s, hy = y0 + dy * s;
|
||||
head.style.transform = 'translate(' + hx.toFixed(1) + 'px,' + hy.toFixed(1) + 'px) rotate(' + rot.toFixed(1) + 'deg) scaleX(' + (1 + u * 5).toFixed(2) + ')';
|
||||
line.style.width = Math.min(s, body + 50 + 700 * u * u).toFixed(0) + 'px';
|
||||
line.style.transform = 'translate(' + hx.toFixed(1) + 'px,' + hy.toFixed(1) + 'px) rotate(' + rot.toFixed(1) + 'deg)';
|
||||
const fade = Math.max(0, 1 - u * 1.25);
|
||||
el.style.setProperty('--bl', (u * 5).toFixed(1) + 'px');
|
||||
const tc = t - T0, dt = Math.max(0, tc - TR), u = Math.min(1, dt / TE);
|
||||
const s = v0 * tc + v0 * tc * tc / 16000 + .5 * A * dt * dt;
|
||||
const v = v0 * (1 + tc / 8000) + A * dt;
|
||||
const hx = x0 + dx * s, hy = y0 + dy * s, at = 'translate(' + hx.toFixed(1) + 'px,' + hy.toFixed(1) + 'px) rotate(' + rot.toFixed(1) + 'deg)';
|
||||
const st = Math.min(1.6, Math.max(0, (v - .25) / .5));
|
||||
head.style.transform = at + ' scaleX(' + (1 + st * 1.6).toFixed(2) + ')';
|
||||
const tl = Math.min(s, body + 70 + 260 * st);
|
||||
line.style.width = core.style.width = tl.toFixed(0) + 'px';
|
||||
line.style.transform = core.style.transform = at;
|
||||
const fade = u < .6 ? 1 : Math.max(0, 1 - (u - .6) / .4);
|
||||
el.style.setProperty('--bl', (st * 1.6).toFixed(1) + 'px');
|
||||
sp.forEach((c, k) => {
|
||||
const d = s - gap - k * cw;
|
||||
const d = s - off[k];
|
||||
if (d < 0) { c.style.opacity = 0; return; }
|
||||
c.style.opacity = (Math.min(1, d / 22) * fade).toFixed(2);
|
||||
c.style.opacity = (Math.min(1, d / 26) * fade).toFixed(2);
|
||||
c.style.transform = 'translate(' + (x0 + dx * d).toFixed(1) + 'px,' + (y0 + dy * d).toFixed(1) + 'px) translate(-50%,-50%) rotate(' + rot.toFixed(1) + 'deg)';
|
||||
});
|
||||
if (u >= 1) { stopMeteor(); return; }
|
||||
|
||||
Reference in New Issue
Block a user