首页孕妈广场第五版「广场地面」:话题气泡之字形错落、头像站在气泡下、虚线小路串起、可横滑;v26110125
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
59
js/app.js
59
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26110124';
|
||||
var VER = '26110125';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -4206,21 +4206,54 @@
|
||||
for (let r = 0; r < 5; r++) by.forEach(l => { if (l[r]) out.push(l[r]); });
|
||||
return out;
|
||||
}
|
||||
/* 11-01 第五版「广场地面」(用户:重新调一版,要有广场那种创意):
|
||||
一块可横滑的地面,话题是一个个说话气泡、气泡下站着一位妈妈的头像,一高一低「之」字形排开、轻轻浮动;
|
||||
背景一条虚线小路从每个头像脚下穿过,空地上零星散着几个在逛的小头像。隔一个气泡带照片(topics.js 的 ph);「全部」里都是热门,不再逐个挂「热」。 */
|
||||
const CAT_CN = { family: '家庭', marriage: '婚姻', work: '职场', baby: '母婴' };
|
||||
const POOL = AVA_FEED.concat(AVA_TOP).filter(n => /^(p|m|mom-)\d/.test(n)); // 只用妈妈头像,k/s/baby 是孩子和风景
|
||||
function bubble(t, i, allHot) {
|
||||
const ph = i % 2 === 0 && t.ph;
|
||||
return '<button type="button" class="gb-b' + (ph ? ' ph' : '') + (t.hot ? ' hot' : '') + '" data-t="' + esc(t.id) + '" style="--c1:' + t.c[0] + ';--c2:' + t.c[1] + ';--ink:' + t.ink + ';--d:' + (i % 5) * -.8 + 's">' +
|
||||
'<span class="gb-in">' +
|
||||
(ph ? '<img class="gb-ph" src="' + esc(t.ph) + '" alt="" loading="lazy">' : '') +
|
||||
'<span class="gb-k">' + (CAT_CN[t.cat] || '') + (t.hot && !allHot ? '<em>热</em>' : '') + '</span>' +
|
||||
'<span class="gb-n">' + esc(t.name) + '</span>' +
|
||||
'<span class="gb-m"><i></i>' + kfmt(t.talk) + ' 人在聊</span></span>' +
|
||||
'<img class="gb-a" src="' + avaSrc(POOL[(i * 7 + 3) % POOL.length]) + '" alt="" loading="lazy"></button>';
|
||||
}
|
||||
function paint(cat) {
|
||||
const list = pick(cat);
|
||||
/* 隔一张换成真实照片卡(11-01 用户:首页广场也放一些真实图),照片取 topics.js 的 ph;没图的照旧渐变卡 */
|
||||
row.innerHTML = list.map((t, i) => {
|
||||
const ph = i % 2 === 0 && t.ph;
|
||||
return '<button type="button" class="gch-card' + (ph ? ' ph' : '') + '" data-t="' + esc(t.id) + '" style="--c1:' + t.c[0] + ';--c2:' + t.c[1] + ';--ink:' + t.ink + '">' +
|
||||
(ph ? '<img class="gp" src="' + esc(t.ph) + '" alt="" loading="lazy">' : '<i class="gb" aria-hidden="true"></i><span class="gg" aria-hidden="true">' + esc(t.g) + '</span>') +
|
||||
(t.hot ? '<span class="gh">热</span>' : '') +
|
||||
'<span class="gk">' + ({ family: '家庭', marriage: '婚姻', work: '职场', baby: '母婴' }[t.cat] || '') + '</span>' +
|
||||
'<span class="gn">' + esc(t.name) + '</span>' +
|
||||
'<span class="gm">' + kfmt(t.n) + ' 篇 · ' + kfmt(t.talk) + ' 人在聊</span></button>';
|
||||
}).join('') +
|
||||
'<button type="button" class="gch-card all" data-t=""><span class="ga" aria-hidden="true">›</span><b>全部话题</b><small>' + T.length + ' 个话题</small></button>';
|
||||
row.innerHTML = '<div class="gb-map"><svg class="gb-path" aria-hidden="true"><path/></svg>' +
|
||||
list.map((t, i) => '<div class="gb-col' + (i % 2 ? ' lo' : '') + '">' + bubble(t, i, !cat) + '</div>').join('') +
|
||||
'<div class="gb-col gb-end"><button type="button" class="gb-all" data-t=""><b>' + T.length + '</b><span>个话题<br>都在广场</span><i>去逛逛 ›</i></button></div></div>';
|
||||
row.scrollLeft = 0;
|
||||
requestAnimationFrame(walk);
|
||||
}
|
||||
/* 排好之后量一遍:小路穿过每个头像的脚下(平滑曲线),地面高度按最低的气泡收口,几个闲逛的小头像放在「低」气泡头顶的空地上 */
|
||||
function walk() {
|
||||
const map = row.firstElementChild;
|
||||
if (!map || !map.offsetWidth) return;
|
||||
const o = map.getBoundingClientRect(), W = map.scrollWidth;
|
||||
const pts = $$('.gb-a', map).map(a => { const r = a.getBoundingClientRect(); return [r.left - o.left + r.width / 2, r.top - o.top + r.height / 2]; });
|
||||
if (!pts.length) return;
|
||||
const H = Math.max.apply(null, $$('.gb-col', map).map(c => c.getBoundingClientRect().bottom - o.top)) + 14;
|
||||
map.style.height = row.style.height = H + 'px';
|
||||
const P = [[0, pts[0][1]]].concat(pts, [[W, pts[pts.length - 1][1]]]);
|
||||
let d = 'M' + P[0][0] + ' ' + P[0][1];
|
||||
for (let i = 1; i < P.length; i++) { const mx = (P[i - 1][0] + P[i][0]) / 2; d += ' C' + mx + ' ' + P[i - 1][1] + ' ' + mx + ' ' + P[i][1] + ' ' + P[i][0] + ' ' + P[i][1]; }
|
||||
const svg = $('.gb-path', map);
|
||||
svg.setAttribute('width', W); svg.setAttribute('height', H); svg.firstElementChild.setAttribute('d', d);
|
||||
$$('.gb-w', map).forEach(x => x.remove());
|
||||
$$('.gb-col.lo', map).forEach((c, k) => {
|
||||
if (k % 2) return;
|
||||
const r = c.getBoundingClientRect(), img = document.createElement('img');
|
||||
img.className = 'gb-w'; img.alt = ''; img.setAttribute('aria-hidden', 'true'); img.loading = 'lazy';
|
||||
img.src = avaSrc(POOL[(k * 5 + 11) % POOL.length]);
|
||||
img.style.left = (r.left - o.left + 18 + (k % 4 ? 50 : 0)) + 'px'; img.style.top = (k % 4 ? 22 : 12) + 'px';
|
||||
map.appendChild(img);
|
||||
});
|
||||
}
|
||||
window.addEventListener('resize', () => requestAnimationFrame(walk));
|
||||
paint('');
|
||||
const talk = T.reduce((a, t) => a + (t.talk || 0), 0);
|
||||
$('#gchCnt').innerHTML = '<b>' + fmtNum(talk) + '</b> 位妈妈正在聊';
|
||||
@@ -4242,7 +4275,7 @@
|
||||
});
|
||||
$('.gch-who', sec).before(b);
|
||||
}).catch(() => {});
|
||||
row.addEventListener('click', e => { const b = e.target.closest('.gch-card'); if (b) go(b.dataset.t); });
|
||||
row.addEventListener('click', e => { const b = e.target.closest('.gb-b,.gb-all'); if (b) go(b.dataset.t); });
|
||||
$('#gchMore').addEventListener('click', () => go(''));
|
||||
$('#gchCat').addEventListener('click', e => {
|
||||
const b = e.target.closest('button[data-cat]');
|
||||
|
||||
Reference in New Issue
Block a user