Files
mama-box/demo/gch/v3.js

130 lines
7.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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('');
});
})();