首页孕妈广场模块五版效果稿:index.html 加 ?gcv=N 演示开关 + demo/gch 汇总与 v1~v5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
deploy
2026-11-02 00:46:38 +00:00
parent 228b06170f
commit 68fa31eea9
18 changed files with 1074 additions and 0 deletions

129
demo/gch/v3.js Normal file
View File

@@ -0,0 +1,129 @@
/* 11-02 首页「孕妈广场」效果稿 V3 · 话题弹幕流(只在 ?gcv=3 时加载)
「此刻最热」小卡(真实照片 + 热)→ 三行缓慢流动的话题弹幕(按住暂停、点进话题)→ 细长投稿入口。分类切换后弹幕换成该分类话题。 */
(function () {
var sec = document.getElementById('gcHome');
var T = window.GC_TOPICS;
if (!sec || !Array.isArray(T) || !T.length) return;
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); };
var kfmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); };
var fmtNum = function (n) { return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ','); };
var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches;
var POOL = [];
for (var i = 1; i <= 22; i++) POOL.push('m' + (i < 10 ? '0' : '') + i);
for (i = 1; i <= 14; i++) POOL.push('p' + (i < 10 ? '0' : '') + i);
var ava = function (k) { return 'assets/img/mom/' + POOL[k % POOL.length] + '.jpg'; };
var CAT = { family: ['家庭婚姻', '#E0566F'], work: ['职场', '#3A72B8'], baby: ['经验', '#2E8A7C'] };
var ORDER = ['family', 'work', 'baby'];
function go(id) {
location.href = 'guangchang/' + (id ? '?t=' + encodeURIComponent(id) : '') + location.hash;
}
/* 「全部」三块轮流排,避免一行同色;某一块:热门在前 */
function pick(cat) {
if (cat) { var l = T.filter(function (t) { return t.cat === cat; }); return l.filter(function (t) { return t.hot; }).concat(l.filter(function (t) { return !t.hot; })); }
var by = ORDER.map(function (c) { return T.filter(function (t) { return t.cat === c; }); }), out = [];
for (var r = 0; r < 20; r++) by.forEach(function (l) { if (l[r]) out.push(l[r]); });
return out;
}
var talkAll = T.reduce(function (a, t) { return a + (t.talk || 0); }, 0);
sec.className = 'gc-home gv3';
sec.innerHTML =
'<div class="v3-head">' +
'<h2 class="v3-title"><span>孕妈广场</span></h2>' +
'<span class="v3-live"><i></i>' + kfmt(talkAll) + ' 妈妈在聊</span>' +
'<button type="button" class="v3-more" data-go="">去逛逛<i aria-hidden="true">›</i></button>' +
'</div>' +
'<div class="v3-cat" role="tablist" aria-label="话题分类">' +
'<button type="button" class="on" data-cat="">全部</button>' +
'<button type="button" data-cat="family">家庭婚姻</button>' +
'<button type="button" data-cat="work">职场</button>' +
'<button type="button" data-cat="baby">经验</button>' +
'</div>' +
'<button type="button" class="v3-hot" id="v3Hot"></button>' +
'<div class="v3-dm" id="v3Dm" aria-label="正在聊的话题"></div>' +
'<button type="button" class="v3-post" data-go=""><b><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 20h4L19 9l-4-4L4 16z"/><path d="M13.5 6.5l4 4"/></svg></b><span>发一条你的故事</span><em>被选中 ¥30+500兜豆</em><i aria-hidden="true">›</i></button>' +
'<span class="v3-tag">效果稿 V3</span>';
sec.classList.remove('hide');
var hotEl = document.getElementById('v3Hot'), dm = document.getElementById('v3Dm');
var hotList = [], hotIdx = 0, hotTimer = 0;
function hotHtml(t) {
var c = CAT[t.cat] || ['', '#E0566F'], k = t.id.charCodeAt(1) * 3;
return '<span class="v3-hot-in">' +
(t.ph ? '<img class="v3-ph" src="' + esc(t.ph) + '" alt="" loading="lazy">' : '<span class="v3-ph v3-g" style="background:linear-gradient(150deg,' + t.c[0] + ',' + t.c[1] + ');color:' + t.ink + '">' + esc(t.g) + '</span>') +
'<span class="v3-hb">' +
'<span class="v3-hk"><em>热</em>此刻最热<i style="background:' + c[1] + '"></i>' + c[0] + '</span>' +
'<span class="v3-hn">' + esc(t.name) + '</span>' +
'<span class="v3-hm"><span class="v3-avs"><img src="' + ava(k) + '" alt="" loading="lazy"><img src="' + ava(k + 5) + '" alt="" loading="lazy"><img src="' + ava(k + 11) + '" alt="" loading="lazy"></span>' + fmtNum(t.talk) + ' 人在聊</span>' +
'</span><span class="v3-go" aria-hidden="true">›</span></span>';
}
function showHot(fade) {
var t = hotList[hotIdx % hotList.length];
if (!t) return;
hotEl.dataset.t = t.id;
if (!fade || reduce) { hotEl.innerHTML = hotHtml(t); return; }
hotEl.classList.add('out');
setTimeout(function () { hotEl.innerHTML = hotHtml(t); hotEl.classList.remove('out'); }, 320);
}
function chip(t, k) {
var c = CAT[t.cat] || ['', '#E0566F'];
return '<button type="button" class="v3-chip" data-t="' + esc(t.id) + '" style="--cc:' + c[1] + ';--c1:' + t.c[0] + '" tabindex="-1">' +
'<img src="' + ava(k * 7 + 3) + '" alt="" loading="lazy">' +
'<span>' + esc(t.name) + '</span>' + (t.hot ? '<em>热</em>' : '') + '<i></i></button>';
}
/* 三行:方向 左/右/左,速度 px/s 略不同;每行一组内容不够宽就重复,再整体复制一份做无缝循环 */
var ROWS = [{ dir: 1, v: 13, d: 0 }, { dir: -1, v: 10, d: -9 }, { dir: 1, v: 15.5, d: -4 }];
function paint(cat) {
var list = pick(cat);
hotList = list.filter(function (t) { return t.hot && t.ph; });
if (!hotList.length) hotList = list.slice(0, 3);
hotIdx = 0; showHot(false);
var rows = [[], [], []];
list.forEach(function (t, j) { rows[j % 3].push(t); });
dm.innerHTML = rows.map(function (r, ri) {
var base = r.slice();
while (base.length < 6) base = base.concat(r);
var g = base.map(function (t, j) { return chip(t, ri * 13 + j); }).join('');
return '<div class="v3-row"><div class="v3-track' + (ROWS[ri].dir < 0 ? ' rev' : '') + '"><div class="v3-grp">' + g + '</div><div class="v3-grp" aria-hidden="true">' + g + '</div></div></div>';
}).join('');
requestAnimationFrame(function () {
Array.prototype.forEach.call(dm.querySelectorAll('.v3-track'), function (tr, ri) {
var w = tr.firstElementChild.offsetWidth || 600, dur = w / ROWS[ri].v;
tr.style.animationDuration = dur.toFixed(1) + 's';
tr.style.animationDelay = (ROWS[ri].d - ri * 3) + 's';
});
});
}
paint('');
if (!reduce) hotTimer = setInterval(function () {
if (dm.classList.contains('hold') || document.hidden) return;
hotIdx++; showHot(true);
}, 5200);
/* 按住暂停(松手 / 纵向滚动被系统接管时恢复) */
var hold = function (on) { dm.classList.toggle('hold', on); };
dm.addEventListener('pointerdown', function () { hold(true); });
['pointerup', 'pointercancel', 'pointerleave'].forEach(function (ev) { dm.addEventListener(ev, function () { hold(false); }); });
dm.addEventListener('touchstart', function () { hold(true); }, { passive: true });
dm.addEventListener('touchend', function () { hold(false); }, { passive: true });
dm.addEventListener('touchcancel', function () { hold(false); }, { passive: true });
sec.addEventListener('click', function (e) {
var cb = e.target.closest('[data-cat]');
if (cb) {
if (cb.classList.contains('on')) return;
Array.prototype.forEach.call(sec.querySelectorAll('.v3-cat button'), function (x) { x.classList.toggle('on', x === cb); });
if (reduce) { paint(cb.dataset.cat); return; }
dm.classList.add('swap');
setTimeout(function () { paint(cb.dataset.cat); dm.classList.remove('swap'); }, 260);
return;
}
var t = e.target.closest('[data-t]');
if (t && sec.contains(t)) { go(t.dataset.t); return; }
if (e.target.closest('[data-go]')) go('');
});
})();