795 lines
55 KiB
HTML
795 lines
55 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<!-- 11-04 UGC 总开关关着时本页不展示,直接回首页(js/ugc.js) -->
|
||
<script src="../../js/ugc.js?v=26110445" data-guard></script>
|
||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
|
||
<meta name="format-detection" content="telephone=no">
|
||
<title>测一测你是什么样的妈妈?</title>
|
||
<!-- 孕期专题 · 趣味测试(孕期首页「其他妈妈也在搜」第 2 条入口)。
|
||
2026-10-31 v3:按《孕期专题页设计规范 v3》重做成「妈妈类型卡」——主色 #7C5CFC、浅底 #F1EDFF。
|
||
一页三屏:开始 / 答题(一题一屏,左右滑动)/ 结果(类型卡 + 雷达 + 结合作答的解读 + 按类型推荐工具 + 保存结果卡)。
|
||
结果存 localStorage「mmbox.ceshi.v3」(含每题作答,刷新后解读可复现;题目已重写,不复用 v2)。
|
||
插画复用 img/*.webp(hero + 4 种类型同一画风)。自成一页:不引 app.js;返回走 history 或相对路径 ../../,
|
||
推荐工具走 ../_shared/tools.js(同源 /<slug>/,带 search + hash)。
|
||
纯娱乐,不采集、不上报答题数据。「已有 N 位妈妈测过」没有真实数据源,按 AGENTS.md 第 2/12 条不造数字:TESTED_COUNT=0 时不显示。 -->
|
||
<style>
|
||
:root{--c:#7C5CFC;--cbg:#F1EDFF;--c06:rgba(124,92,252,.06);--c10:rgba(124,92,252,.10);--c20:rgba(124,92,252,.20);--ink:#1F2329;--txt:#4E5969;--sub:#86909C;--line:#EEF0F3;--soft:#F7F8FA}
|
||
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
|
||
html,body{height:100%;overflow:hidden;background:#fff;color:var(--txt);font:15px/1.75 -apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif}
|
||
#scroll{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;padding-bottom:calc(24px + env(safe-area-inset-bottom))}
|
||
img{display:block;max-width:100%}
|
||
button{font:inherit;border:0;background:none;color:inherit;cursor:pointer}
|
||
.ic{width:20px;height:20px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
|
||
.hide{position:absolute;width:0;height:0;overflow:hidden}
|
||
[hidden]{display:none !important}
|
||
.num{font-variant-numeric:tabular-nums}
|
||
mark{background:linear-gradient(transparent 62%,var(--c20) 0);color:inherit;padding:0 1px}
|
||
|
||
/* 顶栏 */
|
||
.bar{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:4px;height:48px;padding:0 8px;padding-top:env(safe-area-inset-top);background:transparent;border-bottom:1px solid transparent;transition:background .2s,border-color .2s}
|
||
.bar.sh{background:#fff;border-bottom-color:var(--line)}
|
||
.bar .back{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;color:var(--ink)}
|
||
.bar .back .ic{width:22px;height:22px}
|
||
.bar .t{font-weight:600;font-size:16px;color:var(--ink)}
|
||
|
||
/* 三屏 */
|
||
.view{display:none}
|
||
.view.on{display:block;animation:vin .35s ease both}
|
||
@keyframes vin{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
|
||
.wrap{padding:0 20px}
|
||
|
||
.btn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;height:46px;border-radius:99px;font-size:16px;font-weight:700;transition:transform .15s,opacity .15s}
|
||
.btn.pri{background:var(--c);color:#fff;box-shadow:0 6px 16px rgba(124,92,252,.28)}
|
||
.btn.sec{background:#fff;color:var(--c);border:1px solid var(--c)}
|
||
.btn:active,.tap:active{transform:scale(.98)}
|
||
|
||
/* 区块标题:小号序号 + 标题 */
|
||
.sh2{display:flex;align-items:baseline;gap:8px;margin-bottom:14px}
|
||
.sh2 i{font-style:normal;font-size:13px;font-weight:800;color:var(--c);letter-spacing:.5px}
|
||
.sh2 b{font-size:18px;font-weight:800;color:var(--ink);line-height:1.4}
|
||
.sh2 span{margin-left:auto;font-size:12.5px;color:var(--sub)}
|
||
|
||
/* ---------- ① 开始 ---------- */
|
||
#vStart{margin-top:-48px}
|
||
.hero{position:relative;overflow:hidden;min-height:430px;padding:72px 20px 0;background:linear-gradient(160deg,var(--cbg) 0%,#fff 72%)}
|
||
.hero .o1,.hero .o2{position:absolute;border-radius:50%;background:var(--c10);pointer-events:none}
|
||
.hero .o1{width:260px;height:260px;right:-90px;top:-70px}
|
||
.hero .o2{width:150px;height:150px;left:-60px;bottom:40px;background:var(--c06)}
|
||
.hero .eb{position:relative;display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 12px;border-radius:99px;background:#fff;color:var(--c);font-size:12.5px;font-weight:700;letter-spacing:.5px;box-shadow:0 2px 8px var(--c10)}
|
||
.hero h1{position:relative;margin-top:16px;font-size:30px;font-weight:800;line-height:1.32;color:var(--ink);letter-spacing:.5px}
|
||
.hero .meta{position:relative;display:flex;flex-direction:column;gap:8px;margin-top:18px;width:150px}
|
||
.hero .meta span{display:flex;align-items:center;gap:6px;font-size:13.5px;color:var(--txt);line-height:1.4}
|
||
.hero .meta .ic{width:18px;height:18px;color:var(--c)}
|
||
.hero .meta b{color:var(--ink);font-weight:800}
|
||
.hero .pic{position:absolute;right:-18px;bottom:0;width:min(228px,calc(100vw - 162px));height:min(228px,calc(100vw - 162px));object-fit:cover;object-position:center 30%;border-radius:28px 0 0 0;box-shadow:0 8px 24px var(--c10)}
|
||
.types{margin-top:28px}
|
||
.tgrid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
|
||
.tcard{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:18px;background:var(--soft)}
|
||
.tcard img{flex:none;width:46px;height:46px;border-radius:50%;object-fit:cover;object-position:center 22%;border:2px solid #fff;box-shadow:0 2px 8px var(--c10)}
|
||
.tcard b{display:block;font-size:14.5px;color:var(--ink);line-height:1.35}
|
||
.tcard small{display:block;font-size:12px;color:var(--sub);line-height:1.4}
|
||
.startbox{margin-top:28px;text-align:center}
|
||
.startbox .note{margin-top:10px;font-size:12.5px;color:var(--sub)}
|
||
|
||
/* ---------- ② 答题 ---------- */
|
||
#vQuiz{padding-top:4px}
|
||
.qtop{display:flex;align-items:center;justify-content:space-between;height:34px}
|
||
.qtop button{display:inline-flex;align-items:center;gap:2px;font-size:13.5px;color:var(--sub);padding:4px 8px 4px 0}
|
||
.qtop button .ic{width:16px;height:16px}
|
||
.qtop button:disabled{visibility:hidden}
|
||
.qtop .no{font-size:13px;color:var(--sub)}
|
||
.qtop .no b{font-size:18px;color:var(--c);font-weight:800}
|
||
.feet{display:flex;justify-content:space-between;align-items:center;height:30px;margin-top:4px;padding:0 2px}
|
||
.feet svg{width:15px;height:15px;fill:#E4DDFD;transition:fill .3s,transform .3s}
|
||
.feet svg:nth-child(odd){transform:translateY(-4px) rotate(-12deg)}
|
||
.feet svg:nth-child(even){transform:translateY(4px) rotate(12deg) scaleX(-1)}
|
||
.feet svg.done{fill:var(--c)}
|
||
.feet svg.cur{fill:var(--c)}
|
||
.feet svg.cur:nth-child(odd){transform:translateY(-4px) rotate(-12deg) scale(1.35)}
|
||
.feet svg.cur:nth-child(even){transform:translateY(4px) rotate(12deg) scaleX(-1) scale(1.35)}
|
||
.stage{margin-top:14px;transition:opacity .22s ease,transform .22s ease}
|
||
.stage.outL{opacity:0;transform:translateX(-36px)}
|
||
.stage.outR{opacity:0;transform:translateX(36px)}
|
||
.stage.inR{opacity:0;transform:translateX(36px);transition:none}
|
||
.stage.inL{opacity:0;transform:translateX(-36px);transition:none}
|
||
.qcard{position:relative;overflow:hidden;padding:20px 20px 18px;border-radius:24px;background:linear-gradient(160deg,var(--cbg),#fff 78%);box-shadow:0 8px 24px var(--c10)}
|
||
.qcard:after{content:"";position:absolute;width:120px;height:120px;right:-40px;top:-40px;border-radius:50%;background:var(--c10)}
|
||
.qcard .hd{position:relative;display:flex;align-items:center;justify-content:space-between}
|
||
.qcard .qi{width:56px;height:56px;border-radius:18px;display:grid;place-items:center;background:#fff;color:var(--c);box-shadow:0 4px 12px var(--c10)}
|
||
.qcard .qi .ic{width:30px;height:30px;stroke-width:1.6}
|
||
.qcard .cat{position:relative;z-index:1;height:24px;padding:0 10px;border-radius:99px;background:#fff;color:var(--c);font-size:12px;font-weight:700;line-height:24px}
|
||
.qcard h2{position:relative;margin-top:16px;font-size:21px;font-weight:800;line-height:1.45;color:var(--ink);min-height:61px;text-wrap:balance}
|
||
.opts{display:flex;flex-direction:column;gap:10px;margin-top:16px}
|
||
.opt{position:relative;display:flex;align-items:center;gap:12px;width:100%;min-height:56px;padding:11px 46px 11px 14px;border-radius:18px;background:#fff;border:1.5px solid var(--line);text-align:left;font-size:15.5px;line-height:1.45;color:var(--ink);transition:border-color .2s,background .2s,transform .15s}
|
||
.opt:active{transform:scale(.98)}
|
||
.opt .l{flex:none;width:26px;height:26px;border-radius:9px;display:grid;place-items:center;background:var(--soft);color:var(--sub);font-size:13px;font-weight:800;transition:background .2s,color .2s}
|
||
.opt .ck{position:absolute;right:14px;top:50%;width:22px;height:22px;margin-top:-11px;border-radius:50%;background:var(--c);color:#fff;display:grid;place-items:center;transform:scale(0);transition:transform .25s cubic-bezier(.3,1.6,.5,1)}
|
||
.opt .ck .ic{width:14px;height:14px;stroke-width:2.6}
|
||
.opt.sel{border-color:var(--c);background:#FBFAFF;font-weight:600}
|
||
.opt.sel .l{background:var(--c);color:#fff}
|
||
.opt.sel .ck{transform:scale(1)}
|
||
.qtip{margin-top:16px;text-align:center;font-size:12.5px;color:var(--sub)}
|
||
|
||
/* ---------- ③ 结果 ---------- */
|
||
#vResult{padding-top:6px}
|
||
.rcard{position:relative;overflow:hidden;padding:22px 20px 18px;border-radius:28px;background:linear-gradient(170deg,#E9E2FF 0%,#F6F3FF 44%,#fff 100%);box-shadow:0 8px 24px var(--c10);text-align:center}
|
||
.rcard .o1,.rcard .o2{position:absolute;border-radius:50%;pointer-events:none}
|
||
.rcard .o1{width:220px;height:220px;right:-80px;top:-60px;background:rgba(255,255,255,.55)}
|
||
.rcard .o2{width:140px;height:140px;left:-50px;top:150px;background:var(--c06)}
|
||
.rcard .top{position:relative;display:flex;justify-content:space-between;align-items:center;font-size:12px;line-height:24px}
|
||
.rcard .top b{padding:0 10px;border-radius:99px;background:#fff;color:var(--c);font-weight:700}
|
||
.rcard .top span{color:var(--sub)}
|
||
.rcard .ava{position:relative;width:172px;height:172px;margin:14px auto 0;border-radius:32px;overflow:hidden;border:5px solid #fff;box-shadow:0 8px 24px var(--c10)}
|
||
.rcard .ava img{width:100%;height:100%;object-fit:cover;object-position:center 30%}
|
||
.rcard .you{position:relative;margin-top:14px;font-size:13px;color:var(--sub);letter-spacing:2px}
|
||
.rcard h1{position:relative;font-size:28px;font-weight:800;line-height:1.3;color:var(--ink)}
|
||
.rcard .slo{position:relative;margin-top:6px;font-size:14.5px;color:var(--txt);line-height:1.6}
|
||
.rtags{position:relative;display:flex;justify-content:center;gap:8px;margin-top:14px}
|
||
.rtags span{height:30px;padding:0 12px;border-radius:99px;background:#fff;color:var(--c);font-size:13.5px;font-weight:700;line-height:30px;white-space:nowrap;box-shadow:0 2px 8px var(--c10)}
|
||
.dims{position:relative;display:flex;align-items:center;gap:12px;margin-top:18px;padding:14px 14px 14px 8px;border-radius:20px;background:rgba(255,255,255,.85);text-align:left}
|
||
.dims svg{flex:none;width:146px;height:128px}
|
||
.dl{flex:1;min-width:0;display:flex;flex-direction:column;gap:9px}
|
||
.dr{display:grid;grid-template-columns:1fr auto;align-items:center;row-gap:3px;font-size:12.5px;color:var(--txt);line-height:1.3}
|
||
.dr .p{font-weight:700;color:var(--ink)}
|
||
.dr .tr{grid-column:1/3;height:5px;border-radius:5px;background:#EFEAFF;overflow:hidden}
|
||
.dr .tr i{display:block;height:100%;width:0;border-radius:5px;background:#C7B9FE;transition:width .8s cubic-bezier(.3,.7,.2,1)}
|
||
.dr.me{color:var(--c);font-weight:700}
|
||
.dr.me .p{color:var(--c)}
|
||
.dr.me .tr i{background:var(--c)}
|
||
.rcard .brand{position:relative;margin-top:14px;font-size:11.5px;color:var(--sub);letter-spacing:.5px}
|
||
|
||
.racts{display:flex;gap:10px;margin-top:16px}
|
||
.racts .btn{flex:1;font-size:15px}
|
||
.blk{margin-top:36px}
|
||
.read{padding:18px;border-radius:24px;background:var(--soft)}
|
||
.read p{font-size:15px;line-height:1.8;color:var(--txt)}
|
||
.read p+p{margin-top:10px}
|
||
.read b{color:var(--ink)}
|
||
.read q{quotes:"「" "」";color:var(--c);font-weight:700}
|
||
.tips{display:flex;flex-direction:column;gap:10px}
|
||
.tp{display:flex;gap:14px;align-items:flex-start;padding:14px 16px;border-radius:18px;background:#fff;border:1px solid var(--line)}
|
||
.tp .n{flex:none;width:30px;font-size:30px;font-weight:800;line-height:1;color:transparent;-webkit-text-stroke:1.4px var(--c);font-variant-numeric:tabular-nums}
|
||
.tp p{font-size:14.5px;line-height:1.65;color:var(--ink)}
|
||
.mate{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:24px;background:linear-gradient(110deg,var(--cbg),#fff 80%)}
|
||
.mate img{flex:none;width:60px;height:60px;border-radius:50%;object-fit:cover;object-position:center 22%;border:3px solid #fff;box-shadow:0 4px 12px var(--c10)}
|
||
.mate small{display:block;font-size:12px;color:var(--sub);line-height:1.5}
|
||
.mate b{display:block;font-size:16px;color:var(--ink);line-height:1.4}
|
||
.mate p{margin-top:2px;font-size:13.5px;color:var(--txt);line-height:1.55}
|
||
#tools{margin-top:36px !important}
|
||
.again{margin-top:24px}
|
||
|
||
.foot{margin:28px 20px 0;font-size:12px;color:var(--sub);text-align:center}
|
||
.toast{position:fixed;left:50%;bottom:calc(80px + env(safe-area-inset-bottom));transform:translate(-50%,8px);max-width:300px;padding:10px 16px;border-radius:12px;background:rgba(31,35,41,.88);color:#fff;font-size:13.5px;line-height:1.6;text-align:center;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;z-index:60}
|
||
.toast.on{opacity:1;transform:translate(-50%,0)}
|
||
|
||
/* 保存结果卡弹层 */
|
||
.mask{position:fixed;inset:0;z-index:50;display:none;flex-direction:column;align-items:center;justify-content:center;padding:24px 28px calc(24px + env(safe-area-inset-bottom));background:rgba(20,16,40,.82)}
|
||
.mask.on{display:flex;animation:vin .25s ease both}
|
||
.mask img{max-width:100%;max-height:calc(100% - 96px);border-radius:16px;box-shadow:0 12px 32px rgba(0,0,0,.25);-webkit-touch-callout:default;user-select:auto}
|
||
.mask p{margin-top:14px;color:#fff;font-size:14.5px;font-weight:600;display:flex;align-items:center;gap:6px}
|
||
.mask .row{display:flex;gap:16px;margin-top:10px}
|
||
.mask .row button,.mask .row a{height:34px;padding:0 18px;border-radius:99px;border:1px solid rgba(255,255,255,.6);color:#fff;font-size:13.5px;line-height:32px;text-decoration:none}
|
||
|
||
.fade{opacity:0;transform:translateY(12px);transition:opacity .45s ease,transform .45s ease}
|
||
.fade.in{opacity:1;transform:none}
|
||
@media (prefers-reduced-motion:reduce){.fade,.stage,.view.on,.mask.on{opacity:1;transform:none;transition:none;animation:none}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- 单色线性图标(每题一个场景图标 q-*) -->
|
||
<svg class="hide" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
||
<symbol id="i-back" viewBox="0 0 24 24"><path d="M15 5l-7 7 7 7"/></symbol>
|
||
<symbol id="i-arrow" viewBox="0 0 24 24"><path d="M5 12h13M13 6.5l5.5 5.5-5.5 5.5"/></symbol>
|
||
<symbol id="i-check" viewBox="0 0 24 24"><path d="M5 12.5l4.5 4.5L19 7.5"/></symbol>
|
||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="M12 7.5V12l3 2"/></symbol>
|
||
<symbol id="i-list" viewBox="0 0 24 24"><path d="M9 6.5h10M9 12h10M9 17.5h10M4.5 6.5h.01M4.5 12h.01M4.5 17.5h.01"/></symbol>
|
||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="5" y="10.5" width="14" height="10" rx="3"/><path d="M8.5 10.5V8a3.5 3.5 0 0 1 7 0v2.5"/></symbol>
|
||
<symbol id="i-down" viewBox="0 0 24 24"><path d="M12 4v11M7.5 11l4.5 4.5 4.5-4.5M5 19.5h14"/></symbol>
|
||
<symbol id="i-copy" viewBox="0 0 24 24"><rect x="8.5" y="8.5" width="11.5" height="11.5" rx="2.5"/><path d="M15.5 8.5V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7.5a2 2 0 0 0 2 2h2.5"/></symbol>
|
||
<symbol id="i-refresh" viewBox="0 0 24 24"><path d="M20 12a8 8 0 1 1-2.4-5.7M20 4v4.5h-4.5"/></symbol>
|
||
<symbol id="i-hand" viewBox="0 0 24 24"><path d="M9 11V5.5a1.5 1.5 0 0 1 3 0V10M12 9.5V4.5a1.5 1.5 0 0 1 3 0V10M15 9.5V6a1.5 1.5 0 0 1 3 0v8a6.5 6.5 0 0 1-6.5 6.5h-.6a6 6 0 0 1-4.6-2.2L4 15.5a1.6 1.6 0 0 1 2.4-2.1L9 15.5V11"/></symbol>
|
||
<symbol id="i-foot" viewBox="0 0 24 24"><path d="M12 9c3 0 4.6 2.7 4.6 6.3S14.8 22 12 22s-4.6-3.1-4.6-6.7S9 9 12 9z"/><circle cx="7.6" cy="6.6" r="1.6"/><circle cx="10.6" cy="4.4" r="1.75"/><circle cx="14" cy="4.6" r="1.6"/><circle cx="16.8" cy="6.8" r="1.35"/></symbol>
|
||
<!-- 题目场景 -->
|
||
<symbol id="q-test" viewBox="0 0 24 24"><rect x="9" y="2.5" width="6" height="19" rx="3"/><path d="M9 9h6M9 15.5h6M11 11.5v2M13 11.5v2"/></symbol>
|
||
<symbol id="q-board" viewBox="0 0 24 24"><rect x="5" y="4.5" width="14" height="17" rx="2.5"/><path d="M9 3h6v3H9zM8.5 11l1.5 1.5 3-3M8.5 16.5h7"/></symbol>
|
||
<symbol id="q-wait" viewBox="0 0 24 24"><path d="M7 3h10M7 21h10M8 3c0 4.5 4 5.5 4 9s-4 4.5-4 9M16 3c0 4.5-4 5.5-4 9s4 4.5 4 9M10 18.5h4"/></symbol>
|
||
<symbol id="q-moon" viewBox="0 0 24 24"><path d="M19.5 14.5A8 8 0 1 1 9.5 4.5a6.5 6.5 0 0 0 10 10z"/><path d="M16 4v3M14.5 5.5h3"/></symbol>
|
||
<symbol id="q-scale" viewBox="0 0 24 24"><rect x="3.5" y="4" width="17" height="16" rx="4"/><path d="M8 11a4 4 0 0 1 8 0M12 11l2-2.2"/></symbol>
|
||
<symbol id="q-phone" viewBox="0 0 24 24"><rect x="6" y="2.5" width="12" height="19" rx="3"/><path d="M10.5 18.5h3M12 7v4.5M12 14h.01"/></symbol>
|
||
<symbol id="q-bowl" viewBox="0 0 24 24"><path d="M3.5 11.5h17a8.5 8.5 0 0 1-17 0zM9 20h6M14 8.5l5-5M17 8.5l3-3"/></symbol>
|
||
<symbol id="q-pot" viewBox="0 0 24 24"><path d="M4.5 10h15v6a4.5 4.5 0 0 1-4.5 4.5H9A4.5 4.5 0 0 1 4.5 16zM2.5 12h2M19.5 12h2M9 3.5c-.8 1 .8 2 0 3M12 3c-.8 1 .8 2 0 3M15 3.5c-.8 1 .8 2 0 3"/></symbol>
|
||
<symbol id="q-rain" viewBox="0 0 24 24"><path d="M7 15.5a4 4 0 0 1-.4-8A5.5 5.5 0 0 1 17.2 8a3.8 3.8 0 0 1-.2 7.5z"/><path d="M8.5 18.5l-.8 2M12.5 18.5l-.8 2M16.5 18.5l-.8 2"/></symbol>
|
||
<symbol id="q-chat" viewBox="0 0 24 24"><path d="M4 5.5h11a2 2 0 0 1 2 2V13a2 2 0 0 1-2 2H9l-4 3.5V15H4a2 2 0 0 1-2-2V7.5a2 2 0 0 1 2-2z"/><path d="M17 9h3a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-1v2.5L16 18h-2"/></symbol>
|
||
<symbol id="q-heart" viewBox="0 0 24 24"><path d="M12 20s-7.5-4.6-7.5-10A4.3 4.3 0 0 1 12 7.5 4.3 4.3 0 0 1 19.5 10c0 5.4-7.5 10-7.5 10z"/></symbol>
|
||
<symbol id="q-family" viewBox="0 0 24 24"><circle cx="8" cy="7" r="2.8"/><circle cx="16.5" cy="8" r="2.3"/><path d="M3 20v-1.5A5 5 0 0 1 8 13.5a5 5 0 0 1 5 5V20M13.5 14.2a4.2 4.2 0 0 1 7 3.1V20"/></symbol>
|
||
<symbol id="q-bag" viewBox="0 0 24 24"><rect x="3.5" y="8" width="17" height="12.5" rx="3"/><path d="M8.5 8V6a3.5 3.5 0 0 1 7 0v2M3.5 13h17M11 13v2h2v-2"/></symbol>
|
||
<symbol id="q-cal" viewBox="0 0 24 24"><rect x="3.5" y="5" width="17" height="15.5" rx="3"/><path d="M3.5 10h17M8 3v4M16 3v4M14 15.2l1.4 1.4 2.6-2.6"/></symbol>
|
||
<symbol id="q-camera" viewBox="0 0 24 24"><path d="M4.5 7.5h3l1.5-2.5h6l1.5 2.5h3a2 2 0 0 1 2 2V18a2 2 0 0 1-2 2h-15a2 2 0 0 1-2-2V9.5a2 2 0 0 1 2-2z"/><circle cx="12" cy="13.5" r="3.5"/></symbol>
|
||
<symbol id="q-baby" viewBox="0 0 24 24"><circle cx="12" cy="12.5" r="8.5"/><path d="M9.2 11.2h.01M14.8 11.2h.01M10 16a2.6 2.6 0 0 1 4 0M12 4c-1.2 0-1.6 1.2-.8 2"/></symbol>
|
||
</svg>
|
||
|
||
<div id="scroll">
|
||
<header class="bar" id="bar">
|
||
<button class="back" id="back" aria-label="返回"><svg class="ic"><use href="#i-back" xlink:href="#i-back"/></svg></button>
|
||
<span class="t">孕期专题</span>
|
||
</header>
|
||
|
||
<!-- ① 开始 -->
|
||
<main class="view" id="vStart">
|
||
<section class="hero">
|
||
<i class="o1"></i><i class="o2"></i>
|
||
<span class="eb">孕期趣味测试 · MAMA TYPE</span>
|
||
<h1>测一测<br>你是<mark>什么样</mark>的妈妈?</h1>
|
||
<div class="meta">
|
||
<span><svg class="ic"><use href="#i-list" xlink:href="#i-list"/></svg><b class="num">16</b>题 · 约<b class="num">2</b>分钟</span>
|
||
<span><svg class="ic"><use href="#i-lock" xlink:href="#i-lock"/></svg>只在本机算,不上传</span>
|
||
<span id="tested" hidden><svg class="ic"><use href="#q-heart" xlink:href="#q-heart"/></svg>已有<b class="num" id="testedN"></b>位妈妈测过</span>
|
||
</div>
|
||
<img class="pic" src="img/hero.webp" alt="孕妈拿着小测试卡片微笑">
|
||
</section>
|
||
|
||
<div class="wrap">
|
||
<section class="types fade">
|
||
<div class="sh2"><i>4 TYPES</i><b>4 种妈妈,你是哪一种?</b></div>
|
||
<div class="tgrid" id="tgrid"></div>
|
||
</section>
|
||
<div class="startbox fade">
|
||
<button class="btn pri" id="startBtn">开始测试<svg class="ic"><use href="#i-arrow" xlink:href="#i-arrow"/></svg></button>
|
||
<p class="note">没有对错,凭第一感觉选就好</p>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- ② 答题 -->
|
||
<main class="view wrap" id="vQuiz">
|
||
<div class="qtop">
|
||
<button id="prevBtn"><svg class="ic"><use href="#i-back" xlink:href="#i-back"/></svg>上一题</button>
|
||
<span class="no num"><b id="qNo">1</b> / <span id="qTotal">16</span></span>
|
||
</div>
|
||
<div class="feet" id="feet" aria-hidden="true"></div>
|
||
<div class="stage" id="stage">
|
||
<div class="qcard">
|
||
<div class="hd">
|
||
<span class="qi"><svg class="ic"><use id="qIc" href="#q-test" xlink:href="#q-test"/></svg></span>
|
||
<span class="cat" id="qCat"></span>
|
||
</div>
|
||
<h2 id="qTitle"></h2>
|
||
</div>
|
||
<div class="opts" id="qOpts"></div>
|
||
</div>
|
||
<p class="qtip">选完自动进入下一题</p>
|
||
</main>
|
||
|
||
<!-- ③ 结果 -->
|
||
<main class="view wrap" id="vResult">
|
||
<article class="rcard" id="rCard">
|
||
<i class="o1"></i><i class="o2"></i>
|
||
<div class="top"><b>我的妈妈类型卡</b><span id="rLast"></span></div>
|
||
<div class="ava"><img id="rImg" src="" alt=""></div>
|
||
<p class="you">你是</p>
|
||
<h1><mark id="rName"></mark></h1>
|
||
<p class="slo" id="rLine"></p>
|
||
<div class="rtags" id="rTags"></div>
|
||
<div class="dims">
|
||
<svg id="rRadar" viewBox="-16 -2 168 146" role="img" aria-label="4 个维度占比雷达图"></svg>
|
||
<div class="dl" id="rDims"></div>
|
||
</div>
|
||
<p class="brand">兜爸心选 · 孕期专题 · 测一测你是什么样的妈妈</p>
|
||
</article>
|
||
|
||
<div class="racts">
|
||
<button class="btn pri" id="saveBtn"><svg class="ic"><use href="#i-down" xlink:href="#i-down"/></svg>保存结果卡</button>
|
||
<button class="btn sec" id="shareBtn"><svg class="ic"><use href="#i-copy" xlink:href="#i-copy"/></svg>写给未来宝宝</button>
|
||
</div>
|
||
|
||
<section class="blk fade">
|
||
<div class="sh2"><i>01</i><b>你是这样的妈妈</b></div>
|
||
<div class="read" id="rRead"></div>
|
||
</section>
|
||
|
||
<section class="blk fade">
|
||
<div class="sh2"><i>02</i><b>给你的小建议</b></div>
|
||
<div class="tips" id="rTips"></div>
|
||
</section>
|
||
|
||
<section class="blk fade">
|
||
<div class="sh2"><i>03</i><b>和你最搭的队友</b></div>
|
||
<div class="mate" id="rMate"></div>
|
||
</section>
|
||
|
||
<div id="tools" class="fade"></div>
|
||
|
||
<button class="btn sec again" id="againBtn"><svg class="ic"><use href="#i-refresh" xlink:href="#i-refresh"/></svg>重新测试</button>
|
||
</main>
|
||
|
||
<p class="foot">趣味测试,仅供娱乐;身体相关问题以产检医生意见为准</p>
|
||
</div>
|
||
|
||
<div class="mask" id="mask">
|
||
<img id="maskImg" alt="我的妈妈类型卡">
|
||
<p><svg class="ic"><use href="#i-hand" xlink:href="#i-hand"/></svg>长按图片,保存到相册</p>
|
||
<div class="row"><a id="dlBtn" download="妈妈类型卡.png" hidden>下载图片</a><button id="maskClose">关闭</button></div>
|
||
</div>
|
||
<div class="toast" id="toast"></div>
|
||
|
||
<script src="../_shared/tools.js"></script>
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
var $ = function (s) { return document.querySelector(s); };
|
||
var sc = $('#scroll');
|
||
var KEY = 'mmbox.ceshi.v3';
|
||
var TESTED_COUNT = 0; /* 「已有 N 位妈妈测过」:只有接上真实统计后才填,0 = 不显示(不造数字) */
|
||
var XL = 'http://www.w3.org/1999/xlink';
|
||
function useRef(el, id) { el.setAttribute('href', '#' + id); el.setAttributeNS(XL, 'xlink:href', '#' + id); }
|
||
function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); }
|
||
var openid = (function () {
|
||
var m = (location.hash + '&' + location.search).match(/[#?&]openid=([^&#]+)/);
|
||
return m ? decodeURIComponent(m[1]) : '';
|
||
})();
|
||
|
||
/* 返回:从首页点进来就 back;直接打开(分享 / 刷新)就回同目录的首页,身份 hash 原样带回 */
|
||
$('#back').addEventListener('click', function () {
|
||
if (document.referrer && document.referrer.indexOf(location.host) >= 0 && history.length > 1) history.back();
|
||
else location.href = '../../' + location.search + location.hash;
|
||
});
|
||
sc.addEventListener('scroll', function () { $('#bar').classList.toggle('sh', sc.scrollTop > 4); }, { passive: true });
|
||
|
||
/* ================= 4 个维度 = 4 种类型 =================
|
||
* ORDER 顺序 = 雷达图顺时针(上/右/下/左)。
|
||
* dim:维度名;tools:按类型推荐的工具(理由贴合性格,≤18 字);mate:最搭的队友类型。 */
|
||
var TYPES = {
|
||
nuan: { name: '温柔守护型', dim: '细心守护', ax: '守护', img: 'img/nuan.webp', alt: '妈妈温柔地抱着宝宝',
|
||
line: '你的爱细腻又安稳,是宝宝最软的依靠', tags: ['共情力强', '细心周到', '安全感满满'],
|
||
desc: '你把宝宝的每一点动静都放在心上,爱得细腻,也容易替他多操一份心。',
|
||
side: '那份柔软一直都在。',
|
||
tips: ['担心的事随手记下来,产检时一次问清,别一个人反复琢磨。', '胎动、血压这些交给工具记,看得见数据,心里更踏实。'],
|
||
low: '偶尔停下来摸摸肚子、跟宝宝说说话,这份连接很珍贵。',
|
||
mate: 'song', mateWhy: '你替宝宝想得多,TA 帮你把担心放一放,一起把日子过得轻松些。',
|
||
tools: [
|
||
{ id: 'taidong', why: '每天数一数,宝宝动静看得见' },
|
||
{ id: 'taierguzhong', why: '对照 B 超看宝宝长得好不好' },
|
||
{ id: 'yun', why: '血压记下来,心里更有底' } ] },
|
||
xue: { name: '理性计划型', dim: '规划研究', ax: '规划', img: 'img/xue.webp', alt: '孕妈认真看书做笔记',
|
||
line: '知识是你的底气,每一步都提前想好', tags: ['计划周全', '会甄别信息', '遇事冷静'],
|
||
desc: '遇到事情你先查、先记、先排计划,什么都要心里有数才安心。',
|
||
side: '遇事先想清楚,是你的底气。',
|
||
tips: ['网上说法真假混杂,吓人的先打个问号,以产检医生意见为准。', '计划赶不上变化很正常,给自己和宝宝都留一点弹性。'],
|
||
low: '关键节点提前排一排:产检、待产包、入院路线,到时就不慌。',
|
||
mate: 're', mateWhy: '你负责把计划排好,TA 负责把气氛带热,全家都愿意跟着你行动。',
|
||
tools: [
|
||
{ id: 'chanjianrili', why: '产检时间一次排好,提前准备' },
|
||
{ id: 'yunqitizhong', why: '体重画成曲线,涨多涨少一目了然' },
|
||
{ id: 'yunqixuetang', why: '按餐记血糖,数据控最安心' } ] },
|
||
song: { name: '松弛自在型', dim: '松弛乐观', ax: '松弛', img: 'img/song.webp', alt: '孕妈靠在软垫上悠闲喝茶',
|
||
line: '情绪稳定心态好,好心情就是最好的胎教', tags: ['情绪稳定', '抓大放小', '快乐能量'],
|
||
desc: '你抓大放小、不内耗,身边的人跟你待在一起都会放松下来。',
|
||
side: '该放下时你也放得下。',
|
||
tips: ['松弛也别错过关键产检:唐筛、大排畸、糖耐提前约好。', '拿不准能不能吃的,花 10 秒查一下,再放心大口吃。'],
|
||
low: '给自己留点「什么都不做」的时间,妈妈放松,宝宝也舒服。',
|
||
mate: 'nuan', mateWhy: '你心大不内耗,TA 细心会提醒,大事小事都不落下。',
|
||
tools: [
|
||
{ id: 'yunqinengbuchi', why: '想吃先查 10 秒,吃得更放心' },
|
||
{ id: 'daichanqingdan', why: '照清单买齐必需品,不费心' },
|
||
{ id: 'chanjianrili', why: '关键产检到点提醒,不怕忘' } ] },
|
||
re: { name: '元气分享型', dim: '分享连接', ax: '分享', img: 'img/re.webp', alt: '孕妈和朋友们开心聊天',
|
||
line: '热情开朗爱连接,总有人陪你期待宝宝', tags: ['社交满分', '乐于分享', '行动力强'],
|
||
desc: '开心和担心你都愿意说出来,身边总围着一群陪你期待宝宝的人。',
|
||
side: '有人陪着,你会更有力量。',
|
||
tips: ['群里的经验只作参考,涉及用药和检查,以医生意见为准。', '孕肚照、胎动瞬间都存下来,以后都是全家的宝贵回忆。'],
|
||
low: '心里的事别憋着,说给老公或闺蜜听,有人分担会轻松很多。',
|
||
mate: 'xue', mateWhy: '你消息多、朋友多,TA 帮你把信息筛一筛,靠谱的留下来。',
|
||
tools: [
|
||
{ id: 'yundujinian', why: '孕肚照、B 超照存一起,随时分享' },
|
||
{ id: 'taidong', why: '叫上老公一起数,感受宝宝在动' },
|
||
{ id: 'daichanqingdan', why: '清单发给家人,分工一起准备' } ] }
|
||
};
|
||
var ORDER = ['nuan', 'xue', 'song', 're'];
|
||
|
||
/* ================= 16 道题 · 计分表 =================
|
||
* 每个选项 = [维度, 文案],选中即该维度 +1,共 16 分;选项顺序已人工打散。
|
||
* c:题目所属场景(解读里引用);s:场景短语(「X 时,你选了…」);ic:题目场景图标。 */
|
||
var QS = [
|
||
{ c: '情绪时刻', ic: 'q-test', s: '看到验孕棒两道杠', q: '验孕棒出现两道杠的那一刻,你的第一反应是?', o: [
|
||
['nuan', '手不自觉放到肚子上,眼眶有点热'], ['xue', '马上算预产期,开始列待办清单'], ['re', '立刻拍照发给老公'], ['song', '先淡定,去医院确认了再说'] ] },
|
||
{ c: '身体与产检', ic: 'q-board', s: '大排畸前一晚', q: '明天要做大排畸了,今晚的你?', o: [
|
||
['xue', '把想问医生的问题一条条写下来'], ['song', '照常追剧,早点睡就好'], ['nuan', '有点睡不着,一遍遍摸肚子'], ['re', '去孕妈群看看大家都怎么准备'] ] },
|
||
{ c: '身体与产检', ic: 'q-wait', s: '产检排长队', q: '产检排队等了一个多小时,你在?', o: [
|
||
['re', '和旁边的孕妈聊成了朋友'], ['xue', '翻看上次报告,对比各项数值'], ['nuan', '悄悄跟宝宝说「快轮到我们啦」'], ['song', '刷刷手机打个盹,不着急'] ] },
|
||
{ c: '身体与产检', ic: 'q-moon', s: '半夜宝宝拳打脚踢', q: '半夜宝宝在肚子里拳打脚踢,你会?', o: [
|
||
['song', '翻个身,跟着节奏又睡着了'], ['nuan', '轻轻拍拍肚子:妈妈在呢'], ['re', '推醒老公:快来摸,他在踢'], ['xue', '看看时间,顺手记一笔胎动'] ] },
|
||
{ c: '身体与产检', ic: 'q-scale', s: '体重涨得有点快', q: '这个月体重涨得有点快,你会?', o: [
|
||
['xue', '开始每天称重,画条曲线看看'], ['re', '拉上姐妹一起饭后散步'], ['song', '下顿少吃点主食,不焦虑'], ['nuan', '担心影响宝宝,赶紧问问医生'] ] },
|
||
{ c: '吃喝日常', ic: 'q-phone', s: '刷到「孕期千万别吃」', q: '刷到一条「孕期千万别吃 XX」,你会?', o: [
|
||
['nuan', '宁可信其有,先不吃了'], ['re', '转给姐妹:你们看到这个没'], ['xue', '先查权威说法,再决定'], ['song', '适量就好,不太往心里去'] ] },
|
||
{ c: '吃喝日常', ic: 'q-bowl', s: '半夜嘴馋', q: '半夜突然特别想吃酸辣粉,你会?', o: [
|
||
['song', '想吃就吃,开心最重要'], ['xue', '先查查孕妇能不能吃、吃多少'], ['nuan', '忍一忍,明天自己做份干净的'], ['re', '发条朋友圈:谁懂这种馋'] ] },
|
||
{ c: '家人相处', ic: 'q-pot', s: '婆婆端来补汤', q: '婆婆端来一大锅补汤,你会?', o: [
|
||
['re', '拍照发群:被宠到了'], ['nuan', '笑着喝两口,谢谢婆婆的心意'], ['song', '喝一碗,剩下全家分着喝'], ['xue', '先问问汤里放了什么药材'] ] },
|
||
{ c: '情绪时刻', ic: 'q-rain', s: '没来由想哭', q: '没来由地想哭的时候,你会?', o: [
|
||
['xue', '想到是激素在作怪,就释然了'], ['nuan', '抱抱自己,允许情绪来一会儿'], ['re', '打给闺蜜,聊完就好了'], ['song', '睡一觉,醒来又是好心情'] ] },
|
||
{ c: '情绪时刻', ic: 'q-chat', s: '被问「怀孕辛苦吗」', q: '朋友问你「怀孕辛苦吗」,你的回答是?', o: [
|
||
['song', '还好呀,能吃能睡挺快乐'], ['re', '辛苦!来,听我细细说'], ['nuan', '辛苦,但每次胎动都觉得值'], ['xue', '还行,每个阶段我都提前了解过'] ] },
|
||
{ c: '家人相处', ic: 'q-heart', s: '老公想多参与', q: '老公说「我也想多参与孕期」,你会让他?', o: [
|
||
['nuan', '每晚给宝宝讲个睡前故事'], ['xue', '学会看懂产检报告'], ['re', '陪你去上孕妈课,认识新朋友'], ['song', '负责每天逗你开心就够了'] ] },
|
||
{ c: '家人相处', ic: 'q-family', s: '家里带娃意见不一', q: '家里人对以后怎么带娃意见不一,你会?', o: [
|
||
['song', '大方向对就行,细节不纠结'], ['re', '全家开个小会,摊开来聊'], ['xue', '找资料,用科学依据说话'], ['nuan', '先照顾大家情绪,再慢慢沟通'] ] },
|
||
{ c: '待产准备', ic: 'q-bag', s: '收拾待产包', q: '准备待产包,你的风格更像?', o: [
|
||
['xue', '按清单逐项打勾,一样不落'], ['re', '拉闺蜜一起逛,顺手分享心得'], ['nuan', '小衣服洗好晒好,叠得整整齐齐'], ['song', '买齐必需品,缺啥再补'] ] },
|
||
{ c: '待产准备', ic: 'q-cal', s: '离预产期还剩一个月', q: '离预产期还剩一个月,你在?', o: [
|
||
['re', '和同月孕妈约好互报喜讯'], ['song', '该吃吃该睡睡,等着发动'], ['xue', '把去医院的路线和流程走一遍'], ['nuan', '每天跟宝宝说:慢慢来,不着急'] ] },
|
||
{ c: '想象宝宝', ic: 'q-camera', s: '想象宝宝第一张照片', q: '想象宝宝的第一张照片,你希望是?', o: [
|
||
['nuan', '小手紧紧攥着你的手指'], ['song', '宝宝睡得四仰八叉'], ['xue', '配上身长体重的出生卡'], ['re', '全家围着宝宝笑成一团'] ] },
|
||
{ c: '想象宝宝', ic: 'q-baby', s: '想象宝宝哭个不停', q: '想象宝宝第一次哭个不停,你会?', o: [
|
||
['xue', '逐项排查:饿了、尿了还是困了'], ['nuan', '抱在怀里,轻轻哼歌'], ['song', '先稳住自己,深呼吸'], ['re', '视频问问有经验的妈妈'] ] }
|
||
];
|
||
$('#qTotal').textContent = QS.length;
|
||
|
||
/* 开始页:4 种类型小卡 + 测过人数(仅真实数据) */
|
||
$('#tgrid').innerHTML = ORDER.map(function (k) {
|
||
var t = TYPES[k];
|
||
return '<div class="tcard"><img src="' + t.img + '" alt=""><span><b>' + t.name + '</b><small>' + t.tags[0] + '</small></span></div>';
|
||
}).join('');
|
||
if (TESTED_COUNT > 0) { $('#testedN').textContent = TESTED_COUNT.toLocaleString('zh-CN'); $('#tested').hidden = false; }
|
||
|
||
/* 进场动画:按顺序 60ms 错开 */
|
||
var views = { start: $('#vStart'), quiz: $('#vQuiz'), result: $('#vResult') };
|
||
var io = 'IntersectionObserver' in window ? new IntersectionObserver(function (es) {
|
||
var n = 0;
|
||
es.forEach(function (e) {
|
||
if (!e.isIntersecting) return;
|
||
var el = e.target; io.unobserve(el);
|
||
setTimeout(function () { el.classList.add('in'); }, 60 * n++);
|
||
});
|
||
}, { root: sc, threshold: .08 }) : null;
|
||
/* 11-03 用户:「重新测试后退回首页,再进来还是结果页」→ 记住最后停在哪(开始 / 第几题 / 结果),再进来回到那里 */
|
||
function pos(v) {
|
||
if (v) pos.v = v;
|
||
try { localStorage.setItem(KEY + '.pos', JSON.stringify({ v: pos.v, cur: cur, ans: ans })); } catch (e) {}
|
||
}
|
||
function resume() {
|
||
var p = null; try { p = JSON.parse(localStorage.getItem(KEY + '.pos') || 'null'); } catch (e) {}
|
||
if (!p) return false; /* 旧用户没有记录:照原来的(有结果看结果) */
|
||
if (p.v === 'start') { show('start'); return true; }
|
||
if (p.v === 'quiz' && Array.isArray(p.ans)) { cur = Math.max(0, Math.min(+p.cur || 0, QS.length - 1)); ans = p.ans.slice(0, QS.length); paint(); show('quiz'); return true; }
|
||
return false;
|
||
}
|
||
function show(name) {
|
||
pos(name);
|
||
Object.keys(views).forEach(function (k) { views[k].classList.toggle('on', k === name); });
|
||
sc.scrollTop = 0;
|
||
[].forEach.call(views[name].querySelectorAll('.fade'), function (el) {
|
||
el.classList.remove('in');
|
||
if (io) { io.unobserve(el); io.observe(el); } else el.classList.add('in');
|
||
});
|
||
}
|
||
|
||
/* ================= 答题 ================= */
|
||
var cur = 0, ans = [], busy = false;
|
||
var stage = $('#stage');
|
||
$('#feet').innerHTML = QS.map(function () { return '<svg viewBox="0 0 24 24"><use href="#i-foot" xlink:href="#i-foot"/></svg>'; }).join('');
|
||
var feet = document.querySelectorAll('#feet svg');
|
||
|
||
function paint() {
|
||
var q = QS[cur];
|
||
$('#qNo').textContent = cur + 1;
|
||
[].forEach.call(feet, function (f, i) { f.setAttribute('class', i < cur ? 'done' : i === cur ? 'cur' : ''); });
|
||
useRef($('#qIc'), q.ic);
|
||
$('#qCat').textContent = q.c;
|
||
$('#qTitle').textContent = q.q;
|
||
$('#qOpts').innerHTML = q.o.map(function (o, i) {
|
||
return '<button class="opt' + (ans[cur] === i ? ' sel' : '') + '" data-i="' + i + '"><span class="l">' + 'ABCD'[i] + '</span><span>' + esc(o[1]) +
|
||
'</span><span class="ck"><svg class="ic"><use href="#i-check" xlink:href="#i-check"/></svg></span></button>';
|
||
}).join('');
|
||
$('#prevBtn').disabled = cur === 0;
|
||
if (pos.v === 'quiz') pos();
|
||
}
|
||
|
||
/* 左右滑动:前进 → 当前向左滑出、新题从右滑入;上一题反过来 */
|
||
function swap(dir, after) {
|
||
busy = true;
|
||
stage.classList.add(dir > 0 ? 'outL' : 'outR');
|
||
setTimeout(function () {
|
||
after();
|
||
stage.classList.remove('outL', 'outR');
|
||
stage.classList.add(dir > 0 ? 'inR' : 'inL');
|
||
void stage.offsetWidth;
|
||
stage.classList.remove('inR', 'inL');
|
||
setTimeout(function () { busy = false; }, 220);
|
||
}, 220);
|
||
}
|
||
|
||
$('#qOpts').addEventListener('click', function (e) {
|
||
var b = e.target.closest('.opt'); if (!b || busy) return;
|
||
busy = true;
|
||
ans[cur] = +b.dataset.i;
|
||
[].forEach.call(document.querySelectorAll('#qOpts .opt'), function (x) { x.classList.toggle('sel', x === b); });
|
||
setTimeout(function () {
|
||
if (cur < QS.length - 1) swap(1, function () { cur++; paint(); });
|
||
else { busy = false; finish(); }
|
||
}, 380);
|
||
});
|
||
$('#prevBtn').addEventListener('click', function () {
|
||
if (busy || cur === 0) return;
|
||
swap(-1, function () { cur--; paint(); });
|
||
});
|
||
|
||
function startQuiz() {
|
||
cur = 0; ans = []; busy = false;
|
||
stage.classList.remove('outL', 'outR', 'inL', 'inR');
|
||
paint();
|
||
show('quiz');
|
||
}
|
||
$('#startBtn').addEventListener('click', startQuiz);
|
||
$('#againBtn').addEventListener('click', startQuiz);
|
||
|
||
/* ================= 计分 ================= */
|
||
function score(answers) {
|
||
var s = { nuan: 0, xue: 0, song: 0, re: 0 };
|
||
answers.forEach(function (i, qi) { s[QS[qi].o[i][0]]++; });
|
||
/* 最高分为主类型;并列时取「最近一次选过」的那个(越靠后的题越接近真实状态) */
|
||
var max = Math.max.apply(null, ORDER.map(function (k) { return s[k]; }));
|
||
var tied = ORDER.filter(function (k) { return s[k] === max; });
|
||
var top = tied[0];
|
||
if (tied.length > 1) for (var qi = answers.length - 1; qi >= 0; qi--) {
|
||
var t = QS[qi].o[answers[qi]][0];
|
||
if (tied.indexOf(t) >= 0) { top = t; break; }
|
||
}
|
||
return { s: s, top: top };
|
||
}
|
||
function pcts(s, top) {
|
||
var total = 0; ORDER.forEach(function (k) { total += s[k]; }); total = total || 1;
|
||
var p = {}; ORDER.forEach(function (k) { p[k] = Math.round(s[k] / total * 100); });
|
||
var diff = 100; ORDER.forEach(function (k) { diff -= p[k]; });
|
||
p[top] += diff; /* 四舍五入补差,合计 100% */
|
||
return p;
|
||
}
|
||
|
||
function finish() {
|
||
var r = score(ans);
|
||
var rec = { type: r.top, scores: r.s, ans: ans.slice(), at: Date.now() };
|
||
try { localStorage.setItem(KEY, JSON.stringify(rec)); } catch (e) {}
|
||
render(rec, false);
|
||
}
|
||
|
||
/* ================= 解读:引用作答 ================= */
|
||
function reading(rec, p) {
|
||
var t = TYPES[rec.type], a = rec.ans;
|
||
var picks = function (k) { var r = []; a.forEach(function (i, qi) { if (QS[qi].o[i][0] === k) r.push(qi); }); return r; };
|
||
var mine = picks(rec.type);
|
||
/* 主类型最集中的场景 */
|
||
var byCat = {};
|
||
QS.forEach(function (q, qi) { var c = byCat[q.c] || (byCat[q.c] = { n: 0, hit: [] }); c.n++; if (QS[qi].o[a[qi]][0] === rec.type) c.hit.push(qi); });
|
||
var best = null;
|
||
Object.keys(byCat).forEach(function (c) {
|
||
var x = byCat[c]; if (!x.hit.length) return;
|
||
var sc_ = x.hit.length / x.n + x.hit.length * .01;
|
||
if (!best || sc_ > best.sc) best = { c: c, sc: sc_, x: x };
|
||
});
|
||
var ex = QS[best.x.hit[best.x.hit.length - 1]];
|
||
var exOpt = ex.o[a[QS.indexOf(ex)]][1];
|
||
var html = '<p>16 道题里,你有 <b class="num">' + mine.length + '</b> 次选了「' + t.dim + '」的答案。' + esc(t.desc) + '</p>';
|
||
html += '<p>' + (best.x.hit.length === best.x.n ? '在「' + best.c + '」的 ' + best.x.n + ' 道题里,你每次都这样选' : '尤其在「' + best.c + '」的题里,你 ' + best.x.n + ' 次有 ' + best.x.hit.length + ' 次这样选') +
|
||
':比如' + ex.s + ',你选了<q>' + esc(exOpt) + '</q>。</p>';
|
||
/* 第二维度 */
|
||
var rest = ORDER.filter(function (k) { return k !== rec.type; }).sort(function (x, y) { return rec.scores[y] - rec.scores[x]; });
|
||
var sec = rest[0];
|
||
if (rec.scores[sec] > 0) {
|
||
var sp = picks(sec), sq = QS[sp[sp.length - 1]];
|
||
html += '<p>你的另一面是「' + TYPES[sec].dim + '」(<span class="num">' + p[sec] + '%</span>):' + sq.s + '时,你选了<q>' + esc(sq.o[a[QS.indexOf(sq)]][1]) + '</q>,' + TYPES[sec].side + '</p>';
|
||
} else {
|
||
html += '<p>16 道题你全选了同一类,是非常纯粹的' + t.name + '妈妈。</p>';
|
||
}
|
||
return html;
|
||
}
|
||
function tips(rec, p) {
|
||
var t = TYPES[rec.type];
|
||
var low = ORDER.filter(function (k) { return k !== rec.type; }).sort(function (x, y) { return rec.scores[x] - rec.scores[y]; })[0];
|
||
return t.tips.concat(['你在「' + TYPES[low].dim + '」上只占 ' + p[low] + '%,' + TYPES[low].low]);
|
||
}
|
||
|
||
/* ================= 雷达图(SVG 手写,单系列) ================= */
|
||
function radarPts(p, cx, cy, R, M) {
|
||
/* 上、右、下、左 */
|
||
var d = [[0, -1], [1, 0], [0, 1], [-1, 0]];
|
||
return ORDER.map(function (k, i) { var r = Math.max(p[k] / M, .06) * R; return [cx + d[i][0] * r, cy + d[i][1] * r]; });
|
||
}
|
||
function radarScale(p) { var m = 0; ORDER.forEach(function (k) { m = Math.max(m, p[k]); }); return Math.max(50, Math.ceil(m / 10) * 10); }
|
||
function radarSVG(p, top) {
|
||
var cx = 68, cy = 68, R = 44, M = radarScale(p), g = '';
|
||
[1 / 3, 2 / 3, 1].forEach(function (f) {
|
||
var r = R * f; g += '<polygon points="' + [cx, cy - r, cx + r, cy, cx, cy + r, cx - r, cy].join(',') + '" fill="none" stroke="#E4DDFD" stroke-width="1"/>';
|
||
});
|
||
g += '<path d="M' + cx + ' ' + (cy - R) + 'V' + (cy + R) + 'M' + (cx - R) + ' ' + cy + 'H' + (cx + R) + '" stroke="#E4DDFD" stroke-width="1"/>';
|
||
var pts = radarPts(p, cx, cy, R, M);
|
||
g += '<polygon points="' + pts.map(function (x) { return x.join(','); }).join(' ') + '" fill="rgba(124,92,252,.18)" stroke="#7C5CFC" stroke-width="2" stroke-linejoin="round"/>';
|
||
pts.forEach(function (x, i) { g += '<circle cx="' + x[0] + '" cy="' + x[1] + '" r="' + (ORDER[i] === top ? 4.5 : 3.2) + '" fill="#7C5CFC" stroke="#fff" stroke-width="1.5"/>'; });
|
||
var L = [[cx, 12, 'middle'], [cx + R + 6, cy + 4, 'start'], [cx, cy + R + 18, 'middle'], [cx - R - 6, cy + 4, 'end']];
|
||
ORDER.forEach(function (k, i) {
|
||
g += '<text x="' + L[i][0] + '" y="' + L[i][1] + '" text-anchor="' + L[i][2] + '" font-size="11" font-weight="' + (k === top ? 800 : 500) + '" fill="' + (k === top ? '#7C5CFC' : '#86909C') + '">' + TYPES[k].ax + '</text>';
|
||
});
|
||
return g;
|
||
}
|
||
|
||
/* ================= 渲染结果 ================= */
|
||
var curRec = null, curP = null, wk = 0;
|
||
function render(rec, fromCache) {
|
||
var t = TYPES[rec.type], p = pcts(rec.scores, rec.type);
|
||
curRec = rec; curP = p;
|
||
$('#rImg').src = t.img; $('#rImg').alt = t.alt;
|
||
$('#rName').textContent = t.name + '妈妈';
|
||
$('#rLine').textContent = t.line;
|
||
var d = new Date(rec.at || Date.now());
|
||
$('#rLast').textContent = (fromCache ? '上次测试 · ' : '') + (d.getMonth() + 1) + '月' + d.getDate() + '日';
|
||
$('#rTags').innerHTML = t.tags.map(function (a) { return '<span>' + esc(a) + '</span>'; }).join('');
|
||
$('#rRadar').innerHTML = radarSVG(p, rec.type);
|
||
var sorted = ORDER.slice().sort(function (x, y) { return (y === rec.type) - (x === rec.type) || p[y] - p[x]; });
|
||
$('#rDims').innerHTML = sorted.map(function (k) {
|
||
return '<div class="dr' + (k === rec.type ? ' me' : '') + '"><span>' + TYPES[k].dim + '</span><span class="p num">' + p[k] + '%</span><span class="tr"><i data-w="' + p[k] + '"></i></span></div>';
|
||
}).join('');
|
||
$('#rRead').innerHTML = reading(rec, p);
|
||
$('#rTips').innerHTML = tips(rec, p).map(function (x, i) { return '<div class="tp"><span class="n">' + (i + 1) + '</span><p>' + esc(x) + '</p></div>'; }).join('');
|
||
var m = TYPES[t.mate];
|
||
$('#rMate').innerHTML = '<img src="' + m.img + '" alt=""><span><small>队友(老公 / 家人)是这一型最合拍</small><b>' + m.name + '</b><p>' + esc(t.mateWhy) + '</p></span>';
|
||
renderTools();
|
||
show('result');
|
||
setTimeout(function () { [].forEach.call(document.querySelectorAll('#rDims i'), function (b) { b.style.width = b.dataset.w + '%'; }); }, 250);
|
||
}
|
||
function renderTools() {
|
||
if (!curRec || !window.TopicTools) return;
|
||
var el = $('#tools'); el.className = 'fade in';
|
||
TopicTools.render(el, TYPES[curRec.type].tools, { title: TYPES[curRec.type].name + '妈妈用得上', color: '#7C5CFC', bg: '#F1EDFF', wk: wk });
|
||
}
|
||
|
||
/* 孕周:只用来给推荐工具打「孕N周开放」标签 */
|
||
if (openid) {
|
||
fetch('/api/mp/public/mama-box/pregnancy?openid=' + encodeURIComponent(openid))
|
||
.then(function (r) { return r.ok ? r.json() : null; })
|
||
.then(function (j) {
|
||
var p = j && j.code === 200 && j.result;
|
||
if (p && !p.postpartum && !p.empty && p.week != null) { wk = +p.week || 0; renderTools(); }
|
||
}).catch(function () {});
|
||
}
|
||
|
||
/* ================= 分享:复制文案 ================= */
|
||
var tt;
|
||
function toast(msg) {
|
||
var el = $('#toast'); el.textContent = msg; el.classList.add('on');
|
||
clearTimeout(tt); tt = setTimeout(function () { el.classList.remove('on'); }, 2400);
|
||
}
|
||
function copy(text) {
|
||
function legacy() { return new Promise(function (ok, no) {
|
||
var ta = document.createElement('textarea');
|
||
ta.value = text; ta.setAttribute('readonly', ''); ta.style.cssText = 'position:fixed;top:-999px;opacity:0';
|
||
document.body.appendChild(ta); ta.select();
|
||
var r = false; try { r = document.execCommand('copy'); } catch (e) {}
|
||
document.body.removeChild(ta);
|
||
r ? ok() : no();
|
||
}); }
|
||
if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(text).catch(legacy);
|
||
return legacy();
|
||
}
|
||
$('#shareBtn').addEventListener('click', function () {
|
||
if (!curRec) return;
|
||
var t = TYPES[curRec.type];
|
||
var BABY = {
|
||
nuan: '等你来了,妈妈会把你抱得稳稳的,你哭的时候、怕的时候,妈妈都在。',
|
||
xue: '你要用的东西、要打的疫苗,妈妈都提前排好了,你只管安心长大。',
|
||
song: '妈妈不求你样样第一,只希望你健康、快乐,慢慢长大也没关系。',
|
||
re: '好多人都在等你呢,等你来了,妈妈带你去看这个热热闹闹的世界。'
|
||
};
|
||
var text = '宝宝,妈妈今天测出来是「' + t.name + '妈妈」——' + t.line + '。' + BABY[curRec.type] + '我们很快就见面啦。';
|
||
copy(text).then(function () { toast('已复制,存进备忘录,等宝宝长大念给宝宝听'); }, function () { toast('点「保存结果卡」,把这一刻存下来吧'); });
|
||
});
|
||
|
||
/* ================= 保存结果卡:canvas 画图 → <img> 长按保存 ================= */
|
||
var FONT = '-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif';
|
||
function rr(ctx, x, y, w, h, r) {
|
||
ctx.beginPath(); ctx.moveTo(x + r, y); ctx.arcTo(x + w, y, x + w, y + h, r); ctx.arcTo(x + w, y + h, x, y + h, r);
|
||
ctx.arcTo(x, y + h, x, y, r); ctx.arcTo(x, y, x + w, y, r); ctx.closePath();
|
||
}
|
||
function loadImg(src) { return new Promise(function (ok, no) { var im = new Image(); im.onload = function () { ok(im); }; im.onerror = no; im.src = src; }); }
|
||
function drawCard(im) {
|
||
var t = TYPES[curRec.type], p = curP, W = 750, H = 1200;
|
||
var cv = document.createElement('canvas'); cv.width = W; cv.height = H;
|
||
var ctx = cv.getContext('2d');
|
||
var g = ctx.createLinearGradient(0, 0, W * .3, H);
|
||
g.addColorStop(0, '#E9E2FF'); g.addColorStop(.45, '#F6F3FF'); g.addColorStop(1, '#FFFFFF');
|
||
ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
|
||
ctx.fillStyle = 'rgba(255,255,255,.55)'; ctx.beginPath(); ctx.arc(660, 90, 230, 0, 7); ctx.fill();
|
||
ctx.fillStyle = 'rgba(124,92,252,.06)'; ctx.beginPath(); ctx.arc(40, 470, 150, 0, 7); ctx.fill();
|
||
ctx.textAlign = 'center'; ctx.textBaseline = 'alphabetic';
|
||
/* 顶部胶囊 */
|
||
ctx.font = '700 24px ' + FONT;
|
||
var lb = '我的妈妈类型卡', lw = ctx.measureText(lb).width + 44;
|
||
ctx.fillStyle = '#fff'; rr(ctx, (W - lw) / 2, 52, lw, 48, 24); ctx.fill();
|
||
ctx.fillStyle = '#7C5CFC'; ctx.fillText(lb, W / 2, 84);
|
||
/* 插画 */
|
||
var S = 320, ix = (W - S) / 2, iy = 132;
|
||
ctx.save(); ctx.shadowColor = 'rgba(124,92,252,.18)'; ctx.shadowBlur = 36; ctx.shadowOffsetY = 12;
|
||
ctx.fillStyle = '#fff'; rr(ctx, ix - 10, iy - 10, S + 20, S + 20, 60); ctx.fill(); ctx.restore();
|
||
ctx.save(); rr(ctx, ix, iy, S, S, 52); ctx.clip();
|
||
var sw = im.naturalWidth, sh = im.naturalHeight, side = Math.min(sw, sh);
|
||
ctx.drawImage(im, (sw - side) / 2, (sh - side) * .3, side, side, ix, iy, S, S); ctx.restore();
|
||
/* 类型名 */
|
||
ctx.fillStyle = '#86909C'; ctx.font = '400 26px ' + FONT; ctx.fillText('你 是', W / 2, 520);
|
||
ctx.font = '800 60px ' + FONT;
|
||
var nm = t.name + '妈妈', nw = ctx.measureText(nm).width;
|
||
ctx.fillStyle = 'rgba(124,92,252,.20)'; ctx.fillRect((W - nw) / 2 - 4, 566, nw + 8, 24);
|
||
ctx.fillStyle = '#1F2329'; ctx.fillText(nm, W / 2, 588);
|
||
ctx.fillStyle = '#4E5969'; ctx.font = '400 28px ' + FONT; ctx.fillText(t.line, W / 2, 640);
|
||
/* 关键词 */
|
||
ctx.font = '700 26px ' + FONT;
|
||
var ws = t.tags.map(function (s) { return ctx.measureText(s).width + 44; }), gap = 16;
|
||
var tx = (W - ws.reduce(function (a, b) { return a + b; }, 0) - gap * 2) / 2;
|
||
t.tags.forEach(function (s, i) {
|
||
ctx.save(); ctx.shadowColor = 'rgba(124,92,252,.12)'; ctx.shadowBlur = 14; ctx.shadowOffsetY = 4;
|
||
ctx.fillStyle = '#fff'; rr(ctx, tx, 680, ws[i], 56, 28); ctx.fill(); ctx.restore();
|
||
ctx.fillStyle = '#7C5CFC'; ctx.fillText(s, tx + ws[i] / 2, 717); tx += ws[i] + gap;
|
||
});
|
||
/* 维度面板 */
|
||
ctx.fillStyle = 'rgba(255,255,255,.9)'; rr(ctx, 40, 776, 670, 300, 36); ctx.fill();
|
||
var cx = 205, cy = 926, R = 88, M = radarScale(p);
|
||
ctx.strokeStyle = '#E4DDFD'; ctx.lineWidth = 2;
|
||
[1 / 3, 2 / 3, 1].forEach(function (f) { var r = R * f; ctx.beginPath(); ctx.moveTo(cx, cy - r); ctx.lineTo(cx + r, cy); ctx.lineTo(cx, cy + r); ctx.lineTo(cx - r, cy); ctx.closePath(); ctx.stroke(); });
|
||
ctx.beginPath(); ctx.moveTo(cx, cy - R); ctx.lineTo(cx, cy + R); ctx.moveTo(cx - R, cy); ctx.lineTo(cx + R, cy); ctx.stroke();
|
||
var pts = radarPts(p, cx, cy, R, M);
|
||
ctx.beginPath(); pts.forEach(function (x, i) { i ? ctx.lineTo(x[0], x[1]) : ctx.moveTo(x[0], x[1]); }); ctx.closePath();
|
||
ctx.fillStyle = 'rgba(124,92,252,.18)'; ctx.fill(); ctx.strokeStyle = '#7C5CFC'; ctx.lineWidth = 4; ctx.lineJoin = 'round'; ctx.stroke();
|
||
pts.forEach(function (x, i) { ctx.beginPath(); ctx.arc(x[0], x[1], ORDER[i] === curRec.type ? 9 : 6.5, 0, 7); ctx.fillStyle = '#7C5CFC'; ctx.fill(); ctx.lineWidth = 3; ctx.strokeStyle = '#fff'; ctx.stroke(); });
|
||
var L = [[cx, cy - R - 16, 'center'], [cx + R + 12, cy + 8, 'left'], [cx, cy + R + 34, 'center'], [cx - R - 12, cy + 8, 'right']];
|
||
ORDER.forEach(function (k, i) {
|
||
ctx.textAlign = L[i][2]; ctx.font = (k === curRec.type ? '800' : '500') + ' 22px ' + FONT;
|
||
ctx.fillStyle = k === curRec.type ? '#7C5CFC' : '#86909C'; ctx.fillText(TYPES[k].ax, L[i][0], L[i][1]);
|
||
});
|
||
var sorted = ORDER.slice().sort(function (x, y) { return (y === curRec.type) - (x === curRec.type) || p[y] - p[x]; });
|
||
sorted.forEach(function (k, i) {
|
||
var y = 838 + i * 64, me = k === curRec.type;
|
||
ctx.textAlign = 'left'; ctx.font = (me ? '700' : '400') + ' 25px ' + FONT; ctx.fillStyle = me ? '#7C5CFC' : '#4E5969'; ctx.fillText(TYPES[k].dim, 388, y + 10);
|
||
ctx.textAlign = 'right'; ctx.font = '700 25px ' + FONT; ctx.fillStyle = me ? '#7C5CFC' : '#1F2329'; ctx.fillText(p[k] + '%', 674, y + 10);
|
||
ctx.fillStyle = '#EFEAFF'; rr(ctx, 388, y + 24, 286, 10, 5); ctx.fill();
|
||
ctx.fillStyle = me ? '#7C5CFC' : '#C7B9FE'; rr(ctx, 388, y + 24, Math.max(10, 286 * p[k] / 100), 10, 5); ctx.fill();
|
||
});
|
||
/* 底部 */
|
||
ctx.textAlign = 'center';
|
||
ctx.fillStyle = '#1F2329'; ctx.font = '700 26px ' + FONT; ctx.fillText('测一测你是什么样的妈妈?', W / 2, 1128);
|
||
ctx.fillStyle = '#86909C'; ctx.font = '400 21px ' + FONT; ctx.fillText('兜爸心选 · 孕期专题 · 趣味测试,仅供娱乐', W / 2, 1164);
|
||
return cv.toDataURL('image/png');
|
||
}
|
||
var isWx = /MicroMessenger/i.test(navigator.userAgent);
|
||
$('#saveBtn').addEventListener('click', function () {
|
||
if (!curRec) return;
|
||
toast('正在生成结果卡…');
|
||
loadImg(TYPES[curRec.type].img).then(function (im) {
|
||
var url = drawCard(im);
|
||
$('#maskImg').src = url;
|
||
var dl = $('#dlBtn'); dl.href = url; dl.hidden = isWx;
|
||
$('#toast').classList.remove('on');
|
||
$('#mask').classList.add('on');
|
||
}).catch(function () { toast('生成失败,截个图保存也可以'); });
|
||
});
|
||
$('#maskClose').addEventListener('click', function () { $('#mask').classList.remove('on'); });
|
||
$('#mask').addEventListener('click', function (e) { if (e.target === this) this.classList.remove('on'); });
|
||
|
||
/* 入口:有上次结果直接看结果,否则开始页 */
|
||
var saved = null;
|
||
try { saved = JSON.parse(localStorage.getItem(KEY) || 'null'); } catch (e) {}
|
||
if (resume()) ;
|
||
else if (saved && TYPES[saved.type] && saved.scores && saved.ans && saved.ans.length === QS.length) render(saved, true);
|
||
else show('start');
|
||
|
||
/* 禁止下拉回弹:固定外壳 + 容器滚动 + 到顶/到底时拦 touchmove */
|
||
var y0 = 0;
|
||
sc.addEventListener('touchstart', function (e) { y0 = e.touches[0].clientY; }, { passive: true });
|
||
sc.addEventListener('touchmove', function (e) {
|
||
var dy = e.touches[0].clientY - y0;
|
||
if ((sc.scrollTop <= 0 && dy > 0) || (sc.scrollTop + sc.clientHeight >= sc.scrollHeight - 1 && dy < 0)) e.preventDefault();
|
||
}, { passive: false });
|
||
document.addEventListener('touchmove', function (e) { if (!sc.contains(e.target)) e.preventDefault(); }, { passive: false });
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|