/* 首页「孕妈广场」效果稿 V2 · 广场人群:一块俯视的广场空地,十几位妈妈近大远小站着,3 位头上冒话题气泡轮换; 下方分类胶囊切换时人群换一批;右下角一个虚线「空位」是投稿入口。只在 ?gcv=2 时加载。 */ (function () { var sec = document.getElementById('gcHome'); var ALL = window.GC_TOPICS; if (!sec || !ALL || !ALL.length) return; var esc = function (s) { return String(s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }; var fmt = function (n) { return n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); }; var go = function (id) { location.href = (id ? 'guangchang/?t=' + id : 'guangchang/') + location.hash; }; var CATS = [['', '全部'], ['family', '家庭婚姻'], ['work', '职场'], ['baby', '经验']]; var CATN = { family: '家庭婚姻', work: '职场', baby: '经验' }; var MOMS = []; for (var i = 1; i <= 22; i++) MOMS.push('m' + (i < 10 ? '0' : '') + i); for (i = 1; i <= 14; i++) MOMS.push('p' + (i < 10 ? '0' : '') + i); var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches; /* 站位(x 为宽度百分比,y 为头像中心距空地顶 px,s 为直径):上远小、下近大;z 为气泡区 A 左上 / B 右上 / C 前排 */ var SLOTS = [ { x: 9, y: 22, s: 24 }, { x: 33, y: 16, s: 22 }, { x: 54, y: 30, s: 26 }, { x: 76, y: 15, s: 22 }, { x: 20, y: 74, s: 28 }, { x: 78, y: 82, s: 28 }, { x: 11, y: 148, s: 40, z: 'A' }, { x: 36, y: 154, s: 40, z: 'A' }, { x: 63, y: 140, s: 40, z: 'B' }, { x: 88, y: 152, s: 40, z: 'B' }, { x: 58, y: 222, s: 40 }, { x: 87, y: 212, s: 34 }, { x: 12, y: 278, s: 50, z: 'C' }, { x: 35, y: 264, s: 48, z: 'C' } ]; var BW = 158, PAD = 5; // 气泡宽(按空地宽度再收窄)、离空地边距 var hash = function (s) { var x = 7; for (var k = 0; k < s.length; k++) x = (x * 31 + s.charCodeAt(k)) | 0; return Math.abs(x); }; var shuffle = function (arr, seed) { var a = arr.slice(), r = seed || 1; for (var k = a.length - 1; k > 0; k--) { r = (r * 9301 + 49297) % 233280; var j = Math.floor(r / 233280 * (k + 1)); var t = a[k]; a[k] = a[j]; a[j] = t; } return a; }; var cat = '', pool = [], qi = 0, faces = [], topicOf = [], speak = { A: -1, B: -1, C: -1 }, timer = 0, turn = 0, batch = 0; sec.classList.add('gv2'); sec.classList.remove('hide'); sec.innerHTML = '
' + '

孕妈广场

' + '' + '
' + '
位妈妈正在广场上聊效果稿 V2
' + '
' + '' + SLOTS.map(function (p, k) { return ''; }).join('') + '
' + '' + '
' + '
' + '
' + CATS.map(function (c) { return ''; }).join('') + '
' + '
'; var ground = sec.querySelector('#g2Ground'); var moms = [].slice.call(sec.querySelectorAll('.g2-mom')); var bubs = {}; [].forEach.call(sec.querySelectorAll('.g2-bub'), function (b) { bubs[b.getAttribute('data-z')] = b; }); function nextTopic() { var t = pool[qi % pool.length]; qi++; return t; } function bubbleHTML(t) { return '' + CATN[t.cat] + ' · ' + fmt(t.talk) + ' 在聊' + '' + esc(t.name) + ''; } function place(z, k) { var b = bubs[z], p = SLOTS[k], W = ground.clientWidth || 340, cx = W * p.x / 100; BW = Math.min(158, Math.floor((W - PAD * 3) / 2)); b.style.width = BW + 'px'; var left = z === 'A' ? PAD : z === 'B' ? W - PAD - BW : Math.max(PAD, Math.min(W - PAD - BW, cx - BW / 2)); var t = topicOf[k]; b.innerHTML = bubbleHTML(t); b.style.left = left + 'px'; b.style.bottom = (ground.clientHeight - (p.y - p.s / 2) + 7) + 'px'; b.style.setProperty('--tx', Math.max(14, Math.min(BW - 14, cx - left)) + 'px'); b.style.setProperty('--bc', t.c[1]); b.style.setProperty('--bg', t.c[0]); b.setAttribute('data-k', k); b.setAttribute('role', 'button'); b.setAttribute('aria-label', t.name); moms.forEach(function (m) { if (+m.getAttribute('data-k') === k) { m.classList.add('talk'); m.style.setProperty('--ring', t.ink); } }); } function candidates(z) { var r = []; SLOTS.forEach(function (p, k) { if (p.z === z) r.push(k); }); return r; } function rotate(z, first) { var b = bubs[z], old = speak[z], c = candidates(z), k; do { k = c[Math.floor(Math.random() * c.length)]; } while (c.length > 1 && k === old); if (first) k = c[(batch + (z === 'B' ? 1 : 0)) % c.length]; var show = function () { if (old >= 0) moms[old].classList.remove('talk'); topicOf[k] = nextTopic(); speak[z] = k; place(z, k); b.classList.add('on'); }; if (first || reduce) { show(); return; } b.classList.remove('on'); setTimeout(show, 420); } function setCat(c, first) { cat = c; batch++; pool = shuffle(ALL.filter(function (t) { return !c || t.cat === c; }), hash(c || 'all') + batch); qi = 0; var picks = shuffle(MOMS, hash('m' + c) + batch * 7); [].forEach.call(sec.querySelectorAll('.g2-cats button'), function (b) { var on = b.getAttribute('data-cat') === c; b.classList.toggle('on', on); b.setAttribute('aria-selected', on ? 'true' : 'false'); }); sec.querySelector('#g2Cnt').textContent = pool.reduce(function (a, t) { return a + t.talk; }, 0).toLocaleString('en-US'); var apply = function () { moms.forEach(function (m, k) { faces[k] = picks[k % picks.length]; topicOf[k] = nextTopic(); m.querySelector('img').src = 'assets/img/mom/' + faces[k] + '.jpg'; m.classList.remove('talk'); m.setAttribute('aria-label', topicOf[k].name); }); speak = { A: -1, B: -1, C: -1 }; ['A', 'B', 'C'].forEach(function (z) { rotate(z, true); }); ground.classList.remove('swap'); }; if (first || reduce) { apply(); return; } ground.classList.add('swap'); ['A', 'B', 'C'].forEach(function (z) { bubs[z].classList.remove('on'); }); setTimeout(apply, 380); } function loop() { clearInterval(timer); if (reduce) return; timer = setInterval(function () { if (document.hidden) return; rotate(['A', 'C', 'B'][turn++ % 3]); }, 3200); } sec.addEventListener('click', function (e) { var el = e.target.closest('[data-cat],[data-go],.g2-mom,.g2-bub'); if (!el || !sec.contains(el)) return; if (el.hasAttribute('data-cat')) { var c = el.getAttribute('data-cat'); if (c !== cat) { setCat(c); loop(); } return; } if (el.hasAttribute('data-go')) { go(''); return; } var k = +el.getAttribute('data-k'); if (topicOf[k]) go(topicOf[k].id); }); setCat('', true); loop(); })();