/* 11-02 首页「孕妈广场」效果稿 V4 · 故事卡堆(翻一翻) 一叠微微错开的真实照片卡,左右拖/轻扫/点箭头翻页,最后一张是「轮到你了」投稿卡;下方一行 #话题 入口。 只在 ?gcv=4 时由 index.html 加载;笔记是从 guangchang/data.js 摘的精选(占位示例)。 */ (function () { var sec = document.getElementById('gcHome'), 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 { '&': '&', '<': '<', '>': '>', '"': '"' }[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 ava = function (n) { return 'assets/img/mom/' + n + '.jpg'; }; var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches; var CAT_CN = { family: '家庭婚姻', work: '职场', baby: '经验' }; var TOP = {}; T.forEach(function (t) { TOP[t.id] = t; }); /* 精选笔记(摘自 guangchang/data.js):[话题id, 标题, 作者, 孕周, 点赞, 照片] */ var N = { family: [['f01', '怀孕后我妈每天三个电话,第四个是我爸打的', '栗子慢慢', '孕22周', 1286, 'd9d596acde1f'], ['f03', '表姑说我肚子尖肯定是男孩,我回家对着镜子看了半天', '一颗糖糖', '孕24周', 1680, 'ed263579a24d'], ['f04', '我家清淡婆家重口,孕期一桌菜吃出了两种味道', '桃子味汽水', '孕26周', 1940, 'bcfe0afdde7c'], ['f05', '关心太密的时候,我试着给自己留出了一点空间', '夏天的柚子', '孕31周', 1730, 'e2736880c759'], ['f06', '婆婆远在老家,每天给我转发十几条养胎文章', '远方的橙', '孕23周', 1460, 'cbd9db78f705'], ['f07', '我想顺其自然,我妈要我天天躺着保胎,我们僵了一周', '半杯温水', '孕19周', 1390, '9ed29de3419c'], ['f02', '奶奶让我别伸手晾衣服,说会绕脐带,我差点当场反驳', '青柠小满', '孕25周', 1520, '5cc12b5ca19d']], work: [['w04', '赶方案到晚上九点,第一次感觉到胎动是在工位上', '七月的汽水', '孕21周', 2410, '6b374c98a040'], ['w01', '孕 11 周还没告诉领导,周会上差点没忍住吐出来', '青柠半杯', '孕16周', 1862, '874abee3d741'], ['w02', '第一次请产检假,我在领导门口来回走了三趟', '芋圆奶冻', '孕19周', 1544, '41ceb30d229a'], ['w03', '孕 20 周,会议室的椅子让我第一次意识到这件事', '半糖布丁', '孕24周', 1398, '0eb3d4ebc595'], ['w05', '孕 15 周在电梯里头晕,我还笑着说是没吃早饭', '蓝莓小山', '孕18周', 1683, 'bd8a5ddc39f5'], ['w06', '每天被问「今天还好吗」,我开始害怕走进办公室', '芒果西米露', '孕23周', 1576, '657bd5779003'], ['w08', '交接会上讲完最后一页,我在洗手间待了十分钟', '红豆沙沙', '孕35周', 2130, 'b88db204c69f']], baby: [['b07', '我的顺产经历:对我来说最难熬的不是疼,是等', '小船靠岸', '宝宝3个月', 3126, '6440eaf30b5a'], ['b03', '孕20周半夜刷到一个案例,我躺在床上哭到凌晨', '不刷了周周', '孕22周', 2734, 'e4ff8785f404'], ['b02', '孕28周翻了下记账本,零碎小钱加起来吓我一跳', '记账的鱼', '孕28周', 2106, 'c5443c035a02'], ['b04', '孕30周囤了一柜子小衣服,宝宝出生后一半没穿上', '囤囤收手了', '宝宝5个月', 2251, '269846ead50f'], ['b05', '每次产检称体重前,我都会偷偷把外套脱掉', '秤上的梨', '孕26周', 1978, '81541ebb328d'], ['b06', '关于留意胎动,医生教的方法让我不再整天瞎想', '夜里数星星', '孕30周', 1687, 'fba0aa35ada9'], ['b01', '烧心鼻塞加腿抽筋,同事一句「都这样」让我闭了嘴', '豆豆妈咪', '孕21周', 1862, 'b9f151713ad0']] }; var MOMS = ['m03', 'p02', 'm07', 'p05', 'm11', 'p09', 'm14', 'm16', 'p12', 'm19', 'm21', 'p07']; function notes(cat) { var l = cat ? N[cat] : [N.family[0], N.work[0], N.baby[0], N.family[1], N.work[1], N.baby[1], N.family[2]]; return l.map(function (a, i) { return { t: a[0], title: a[1], author: a[2], stage: a[3], likes: a[4], photo: 'guangchang/img/' + a[5] + '.jpg', av: MOMS[(i * 5 + (cat ? cat.length : 0)) % MOMS.length] }; }); } function topics(cat) { var l = T.filter(function (t) { return !cat || t.cat === cat; }); var hot = l.filter(function (t) { return t.hot; }); return (cat ? hot : hot.filter(function (_, i) { return i % 3 === 0; })).concat(l.filter(function (t) { return !t.hot; })).slice(0, 3); } function go(id) { location.href = 'guangchang/' + (id ? '?t=' + encodeURIComponent(id) : '') + location.hash; } sec.className = sec.className.replace(/\bgv\d\b/g, '') + ' gv4'; sec.innerHTML = '

孕妈广场

' + '
' + '
翻一翻,看看其他妈妈的故事
' + '
' + '
1/8' + '
' + '
' + '
效果稿 V4
'; sec.classList.remove('hide'); var deck = sec.querySelector('.g4-deck'), pgB = sec.querySelector('.g4-pg b'), pgI = sec.querySelector('.g4-pg i'), tags = sec.querySelector('.g4-tags'); var cards = [], idx = 0, cur = ''; function storyCard(n) { var tp = TOP[n.t] || {}, cat = tp.cat || 'family'; return '
' + '' + '' + CAT_CN[cat] + '' + '' + esc(n.title) + '' + '' + esc(n.author) + '' + esc(n.stage) + '' + '' + kfmt(n.likes) + '
'; } function submitCard() { return '
' + '投稿征集' + '轮到你了' + '你的孕期故事,正是别的妈妈想听的' + '¥30现金+500兜豆' + '被选中即可获得' + '去投稿 ›' + '
'; } function paint(cat, first) { cur = cat; idx = 0; deck.innerHTML = notes(cat).map(storyCard).join('') + submitCard(); cards = [].slice.call(deck.children); if (!first && !reduce) { deck.classList.add('deal'); cards.forEach(function (c, i) { c.style.transitionDelay = (Math.min(i, 3) * 60) + 'ms'; }); layout(); requestAnimationFrame(function () { requestAnimationFrame(function () { deck.classList.remove('deal'); layout(); setTimeout(function () { cards.forEach(function (c) { c.style.transitionDelay = ''; }); }, 500); }); }); } else layout(); tags.innerHTML = '大家在聊' + topics(cat).map(function (t) { return ''; }).join(''); tags.scrollLeft = 0; } /* depth:0 顶层;1、2 在后面错开;>2 藏在后面;<0 已翻走(左侧飞出) */ function layout() { cards.forEach(function (c, i) { var d = i - idx; c.setAttribute('data-d', d < 0 ? 'out' : d > 3 ? 3 : d); c.style.zIndex = 20 - Math.abs(d); c.style.transform = ''; c.setAttribute('aria-hidden', d === 0 ? 'false' : 'true'); c.tabIndex = d === 0 ? 0 : -1; }); pgB.textContent = idx + 1; pgI.textContent = '/' + cards.length; sec.querySelector('.g4-arr.prev').disabled = idx === 0; } function next() { if (idx < cards.length - 1) { idx++; layout(); return; } /* 最后一张再往后 → 整叠收回,从第 1 张重新开始 */ idx = 0; deck.classList.add('reset'); layout(); setTimeout(function () { deck.classList.remove('reset'); }, 380); } function prev() { if (idx > 0) { idx--; layout(); } else bounce(1); } function bounce(dir) { var c = cards[idx]; if (!c || reduce) return; c.style.transform = 'translateX(' + dir * 14 + 'px) rotate(' + dir * 1.5 + 'deg)'; setTimeout(function () { c.style.transform = ''; }, 160); } /* 拖动:方向锁 —— 先判断横 / 竖,竖向直接放行给页面滚动,横向才拦截(touchmove passive:false 才能 preventDefault) */ var drag = null, moved = false; function start(x, y) { var c = cards[idx]; if (!c) return; drag = { x: x, y: y, dx: 0, lock: '', t: Date.now(), c: c }; moved = false; } function move(x, y, e) { if (!drag) return; var dx = x - drag.x, dy = y - drag.y; if (!drag.lock) { if (Math.abs(dx) < 6 && Math.abs(dy) < 6) return; drag.lock = Math.abs(dx) > Math.abs(dy) ? 'x' : 'y'; if (drag.lock === 'y') { drag = null; return; } drag.c.classList.add('drag'); deck.classList.add('dragging'); } if (e && e.cancelable) e.preventDefault(); if (e) e.stopPropagation(); moved = true; if ((idx === 0 && dx > 0)) dx = dx * 0.3; // 第一张往右拖:阻尼 drag.dx = dx; drag.c.style.transform = 'translateX(' + dx + 'px) translateY(' + Math.abs(dx) * 0.04 + 'px) rotate(' + dx / 18 + 'deg)'; } function end() { if (!drag) return false; var d = drag; drag = null; d.c.classList.remove('drag'); deck.classList.remove('dragging'); if (!d.lock) return false; var v = Math.abs(d.dx) / Math.max(1, Date.now() - d.t); if (d.dx < -70 || (d.dx < -24 && v > 0.45)) next(); else if ((d.dx > 70 || (d.dx > 24 && v > 0.45)) && idx > 0) prev(); else d.c.style.transform = ''; return true; } deck.addEventListener('touchstart', function (e) { if (e.touches.length === 1) start(e.touches[0].clientX, e.touches[0].clientY); else drag = null; }, { passive: true }); deck.addEventListener('touchmove', function (e) { if (drag && e.touches.length === 1) move(e.touches[0].clientX, e.touches[0].clientY, e); }, { passive: false }); /* 首页在 document 上有「左右滑切底部 tab」的手势(app.js touchend):卡堆横拖结束时截住 touchend,别让它把页面切走 */ deck.addEventListener('touchend', function (e) { if (end()) e.stopPropagation(); }); deck.addEventListener('touchcancel', end); deck.addEventListener('mousedown', function (e) { if (e.button) return; start(e.clientX, e.clientY); e.preventDefault(); var mm = function (ev) { move(ev.clientX, ev.clientY, ev); }, mu = function () { end(); document.removeEventListener('mousemove', mm); document.removeEventListener('mouseup', mu); }; document.addEventListener('mousemove', mm); document.addEventListener('mouseup', mu); }); deck.addEventListener('click', function (e) { if (moved) { moved = false; return; } var c = e.target.closest('.g4-card'); if (!c) return; if (c !== cards[idx]) { next(); return; } // 点到后面露出的卡角 → 翻到下一张 go(c.dataset.sub ? '' : c.dataset.t); }); deck.addEventListener('keydown', function (e) { if (e.key === 'ArrowRight') next(); else if (e.key === 'ArrowLeft') prev(); else if (e.key === 'Enter') { var c = cards[idx]; if (c) go(c.dataset.sub ? '' : c.dataset.t); } }); sec.querySelector('.g4-arr.next').addEventListener('click', next); sec.querySelector('.g4-arr.prev').addEventListener('click', prev); tags.addEventListener('click', function (e) { var b = e.target.closest('button[data-t]'); if (b) go(b.dataset.t); }); sec.querySelector('.g4-all').addEventListener('click', function () { go(''); }); sec.querySelector('.g4-cat').addEventListener('click', function (e) { var b = e.target.closest('button[data-cat]'); if (!b || b.classList.contains('on')) return; [].forEach.call(sec.querySelectorAll('.g4-cat button'), function (x) { x.classList.toggle('on', x === b); }); paint(b.dataset.cat); }); paint('', true); })();