779 lines
54 KiB
HTML
779 lines
54 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=26110460" 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-11-02 新建)。
|
||
结构 / 交互 / 视觉完全照 ../ceshi/(妈妈类型卡 v3),只换内容与主色:主色暖橙 #F27B35、浅底 #FFF1E6(和 ceshi 的紫色区分)。
|
||
孕妈来答,描述准爸爸在孕期的表现;12 题,每题 4 个选项各对应一种队友类型。
|
||
一页三屏:开始 / 答题(一题一屏,左右滑动)/ 结果(类型卡 + 雷达 + 结合作答的解读 + 小盲区 + 沟通建议 + 转给他看的一句话 + 推荐工具 + 保存结果卡)。
|
||
按用户要求:结果页不放「复制发给 xx」类按钮,只保留「保存结果卡」。
|
||
结果存 localStorage「mmbox.duiyou.v1」(含每题作答)。插画 img/*.webp(hero + 4 种类型同一画风)。
|
||
自成一页:不引 app.js;返回走 history 或相对路径 ../../,推荐工具走 ../_shared/tools.js。
|
||
纯娱乐,不采集、不上报答题数据;不造「已有 N 人测过」数字(TESTED_COUNT=0 不显示)。 -->
|
||
<style>
|
||
:root{--c:#F27B35;--cbg:#FFF1E6;--c06:rgba(242,123,53,.06);--c10:rgba(242,123,53,.10);--c20:rgba(242,123,53,.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(242,123,53,.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:#FCD9C2;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:#FFFAF6;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,#FFE4D1 0%,#FFF4EB 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:#FFEDE1;overflow:hidden}
|
||
.dr .tr i{display:block;height:100%;width:0;border-radius:5px;background:#F9C29E;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(40,22,10,.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-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">孕期趣味测试 · DAD TYPE</span>
|
||
<h1>测一测<br>你家准爸爸是<br><mark>哪种队友</mark>?</h1>
|
||
<div class="meta">
|
||
<span><svg class="ic"><use href="#i-list" xlink:href="#i-list"/></svg><b class="num">12</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">12</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>
|
||
</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="read" id="rBlind"></div>
|
||
</section>
|
||
|
||
<section class="blk fade">
|
||
<div class="sh2"><i>03</i><b>给你的沟通小建议</b></div>
|
||
<div class="tips" id="rTips"></div>
|
||
</section>
|
||
|
||
<section class="blk fade">
|
||
<div class="sh2"><i>04</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.duiyou.v1';
|
||
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:维度名;good:闪光点;blind:可能的小盲区;low:他在某维度占比最低时给的一句(落在「小盲区」里);
|
||
* tips:给妈妈的沟通小建议(3 条);toHim:可以转给他看的一句话;tools:适合两人一起用的工具。
|
||
* 语气:温柔、有趣、不说教、不制造对立 —— 每一型都是「好队友」,只是方式不同。 */
|
||
var TYPES = {
|
||
guan: { name: '贴身管家型', dim: '生活照料', ax: '照料', img: 'img/guan.webp', alt: '准爸爸给孕妈垫靠枕、端来热汤',
|
||
line: '你刚皱眉,温水已经递到手边', tags: ['手脚勤快', '细节控', '行动派'],
|
||
desc: '他的爱都落在具体的事上:吃的、穿的、靠的、带的,样样提前替你想到。',
|
||
good: '靠谱、踏实、执行力强,有他在,生活上的小麻烦基本轮不到你操心。',
|
||
blind: '忙着把事情做好,偶尔会忘了停下来问一句「你心里怎么样」;也容易什么都自己揽,把自己累坏了还不说。',
|
||
side: '他也在用自己的方式靠近你。',
|
||
low: '可以拉他一起做做这件事,让他知道你同样需要。',
|
||
tips: ['他做了什么,具体夸出来:「今天那碗汤刚刚好」,比一句「辛苦了」更能让他开心。', '想被陪的时候直接说「今晚不用收拾,陪我坐会儿」,他会很乐意把手里的活放下。', '家务可以分一点出去,或者轮流来,别让他一个人扛成「全能管家」。'],
|
||
toHim: '谢谢你把日子照顾得这么妥帖。偶尔也停下来抱抱我,你不用什么都做完,我一样很安心。',
|
||
tools: [
|
||
{ id: 'daichanqingdan', why: '待产包交给他打勾,一样不落' },
|
||
{ id: 'yunqinengbuchi', why: '给你做饭前先查一查能不能吃' },
|
||
{ id: 'chanjianrili', why: '产检日子同步给他,提前请好假' } ] },
|
||
xue: { name: '学霸攻略型', dim: '做功课', ax: '功课', img: 'img/xue.webp', alt: '准爸爸戴着眼镜认真看孕育书做笔记',
|
||
line: '孕期知识他比你还熟,攻略做了一大本', tags: ['爱学习', '有规划', '遇事冷静'],
|
||
desc: '遇到新情况,他第一反应是查资料、问医生、排计划,把未知变成心里有数。',
|
||
good: '冷静、可靠、会找靠谱信息,关键时刻他是那个不慌的人。',
|
||
blind: '有时太讲道理:你只想被抱一下,他在给你讲激素原理;资料看多了,也可能自己偷偷焦虑。',
|
||
side: '他理性的外壳下,藏着不少柔软。',
|
||
low: '可以邀请他一起,他学得快,一点就通。',
|
||
tips: ['想被安慰时先说一句「现在不用分析,抱抱我就好」,他会立刻切换模式。', '把他做的功课变成两个人的事:一起看产检报告、一起上孕妇课,他会很有成就感。', '他转来的科普看到有用的就回个「学到了」,这是他最喜欢的反馈。'],
|
||
toHim: '你查的每一份资料我都看到了,有你在我很踏实。有时候我不需要答案,只需要你在旁边。',
|
||
tools: [
|
||
{ id: 'chanjianrili', why: '产检节点一次排好,他最爱' },
|
||
{ id: 'yunqitizhong', why: '体重曲线一起看,涨多涨少有数' },
|
||
{ id: 'taierguzhong', why: '对照 B 超数据,看宝宝长得好不好' } ] },
|
||
nuan: { name: '暖心陪伴型', dim: '情绪陪伴', ax: '陪伴', img: 'img/nuan.webp', alt: '准爸爸搂着孕妈,靠在窗边',
|
||
line: '他未必样样精通,但总在你身边', tags: ['会倾听', '情绪稳定', '有仪式感'],
|
||
desc: '你开心时他陪着笑,低落时他先抱抱你,情绪价值一直在线。',
|
||
good: '温柔、耐心、共情力强,跟他在一起,再难熬的孕期也有人一起扛。',
|
||
blind: '情绪上永远在线,具体事务偶尔要你提醒;遇到要拍板的事,他可能更习惯听你的。',
|
||
side: '温柔之外,他也有能干的一面。',
|
||
low: '可以交给他一两件具体的小任务,他会做得很用心。',
|
||
tips: ['具体的事直接点名:「周六你负责把待产包装好」,清楚的任务他会做得很好。', '他的陪伴别当成理所当然,偶尔说一句「有你在真好」,他能开心一整天。', '他也会累、也会紧张,找个晚上换你听他说说心里话。'],
|
||
toHim: '谢谢你一直陪着我,每次难受的时候有你在,就没那么难了。我们一起,慢慢等宝宝来。',
|
||
tools: [
|
||
{ id: 'taidong', why: '睡前一起数胎动,跟宝宝打招呼' },
|
||
{ id: 'yundujinian', why: '孕肚照存起来,以后给宝宝看' },
|
||
{ id: 'chanjianrili', why: '产检日子提醒他,一起去' } ] },
|
||
man: { name: '慢热成长型', dim: '慢慢成长', ax: '成长', img: 'img/man.webp', alt: '准爸爸坐在地上认真组装婴儿床',
|
||
line: '入戏慢一点,但每一步都在追上来', tags: ['潜力股', '肯学', '越来越好'],
|
||
desc: '他还在慢慢找「当爸爸」的感觉,但你说的每件事,他都放在心上、认真去做。',
|
||
good: '真诚、肯学、不装懂,教一次就会,而且一次比一次熟练。',
|
||
blind: '很多准爸爸的「爸爸感」要到看见宝宝才真正到来,所以他现在可能还没意识到你需要什么,不是不在乎。',
|
||
side: '他已经在悄悄进步了。',
|
||
low: '可以带着他做一次,他会记住的。',
|
||
tips: ['需要什么就说具体:「半夜我吐的时候,帮我倒杯温水」比「你多关心我」好接得多。', '带他去一次产检、摸一次胎动,让他亲眼看见宝宝,「爸爸感」会来得快很多。', '他每进步一点就夸一点,你的肯定是他最好的加速器。'],
|
||
toHim: '我知道你在认真学着当爸爸,慢一点没关系,我们都是第一次。你每一点进步我都看得见。',
|
||
tools: [
|
||
{ id: 'taidong', why: '让他摸一摸,亲身感受宝宝在动' },
|
||
{ id: 'daichanqingdan', why: '照着清单买,新手也不会漏' },
|
||
{ id: 'chanjianrili', why: '产检提醒同步给他,一起去' } ] }
|
||
};
|
||
var ORDER = ['guan', 'xue', 'nuan', 'man'];
|
||
|
||
/* ================= 12 道题 · 计分表 =================
|
||
* 孕妈来答,描述准爸爸的表现。每个选项 = [维度, 文案],选中即该维度 +1,共 12 分;选项顺序已人工打散。
|
||
* c:题目所属场景(解读里引用);s:场景短语(「说到 X,你选了…」);ic:题目场景图标。 */
|
||
var QS = [
|
||
{ c: '身体与产检', ic: 'q-board', s: '陪你产检', q: '要去做产检的那天,他通常是?', o: [
|
||
['guan', '提前排好号,水和小零食都备好'], ['xue', '带着问题清单,比你还认真听'], ['nuan', '一路牵着你,等结果时陪你聊天'], ['man', '请好假跟着去,边走流程边学'] ] },
|
||
{ c: '身体与产检', ic: 'q-moon', s: '半夜孕吐', q: '半夜你吐得难受,他会?', o: [
|
||
['nuan', '坐起来拍拍背,陪你到缓过来'], ['guan', '马上端温水、递纸巾、收拾干净'], ['man', '被你叫醒,赶紧问「我能做点啥」'], ['xue', '第二天查好缓解孕吐的办法发给你'] ] },
|
||
{ c: '待产准备', ic: 'q-bag', s: '准备待产包', q: '说到准备待产包,他的风格是?', o: [
|
||
['xue', '对比好几份清单,整理成表格'], ['man', '你列好清单,他照着一样样买齐'], ['nuan', '陪你逛母婴店,挑小衣服挑到傻笑'], ['guan', '默默打包好,连你的发圈都放了'] ] },
|
||
{ c: '情绪与家人', ic: 'q-family', s: '长辈意见和你不一样', q: '长辈坚持「孕妇不能 XX」,和你想法不一样时,他会?', o: [
|
||
['nuan', '先站你这边,再私下跟长辈聊'], ['xue', '翻出科普资料,耐心跟长辈解释'], ['guan', '两边照顾,把长辈心意换个方式办'], ['man', '一开始有点懵,你提一句就去沟通'] ] },
|
||
{ c: '感受宝宝', ic: 'q-baby', s: '第一次叫他摸胎动', q: '第一次感觉到胎动,叫他来摸,他?', o: [
|
||
['man', '摸了半天没感觉,下次还主动来等'], ['nuan', '把脸贴在肚子上,跟宝宝说悄悄话'], ['guan', '先扶你躺舒服,垫好靠枕一起等'], ['xue', '问你几点动的、动了几下,记下来'] ] },
|
||
{ c: '情绪与家人', ic: 'q-rain', s: '你莫名低落', q: '你莫名低落、想哭的时候,他会?', o: [
|
||
['guan', '出门买回你最想吃的那一口'], ['xue', '告诉你激素波动很正常,帮你理理'], ['nuan', '什么也不说,先抱抱你,听你讲'], ['man', '有点手足无措,但会笨笨地逗你笑'] ] },
|
||
{ c: '日常生活', ic: 'q-pot', s: '孕期的家务', q: '怀孕以后,家里的家务?', o: [
|
||
['guan', '基本被他包了,做饭拖地样样来'], ['nuan', '做完饭还会陪你散步消消食'], ['man', '你说一声就去做,越来越不用提醒'], ['xue', '列了张「孕妇别碰」家务清单'] ] },
|
||
{ c: '日常生活', ic: 'q-phone', s: '孕期知识', q: '关于孕期知识,他平时?', o: [
|
||
['xue', '关注好几个科普号,随时划重点'], ['man', '你转给他的文章,会点开认真看完'], ['guan', '研究孕妇餐,变着花样给你做饭'], ['nuan', '每晚睡前给宝宝讲故事、放音乐'] ] },
|
||
{ c: '身体与产检', ic: 'q-heart', s: '腰酸、半夜腿抽筋', q: '你腰酸背痛、半夜腿抽筋时,他?', o: [
|
||
['nuan', '边按边陪你聊天,直到你睡着'], ['man', '一开始不会按,看了视频学着来'], ['xue', '查清原因,提醒你补钙、睡前拉伸'], ['guan', '二话不说起来,帮你揉腿、热敷'] ] },
|
||
{ c: '感受宝宝', ic: 'q-chat', s: '给宝宝起名字', q: '聊到给宝宝起名字,他?', o: [
|
||
['xue', '查字典、看寓意,列了候选名单'], ['guan', '名字交给你,他先把月子安排好'], ['man', '嘴上说「还早」,偷偷想了好几个'], ['nuan', '起了一堆小名,每个都很有爱'] ] },
|
||
{ c: '待产准备', ic: 'q-cal', s: '离预产期还剩一个月', q: '离预产期还剩一个月,他在?', o: [
|
||
['man', '「爸爸感」上线,追着问要准备啥'], ['guan', '待产包放门口,车加满油随时出发'], ['nuan', '每天准时回家,说要多陪陪你们'], ['xue', '踩点去医院的路线,摸清入院流程'] ] },
|
||
{ c: '日常生活', ic: 'q-camera', s: '难得的周末', q: '难得的周末,他最可能?', o: [
|
||
['nuan', '陪你拍孕肚照,说要留给宝宝看'], ['xue', '拉你一起上孕妇学校的课'], ['man', '被喊去装婴儿床,装完超有成就感'], ['guan', '大扫除,再给你做一桌好菜'] ] }
|
||
];
|
||
$('#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 = { guan: 0, xue: 0, nuan: 0, man: 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 N = QS.length;
|
||
var html = '<p>' + N + ' 道题里,你有 <b class="num">' + mine.length + '</b> 次选了「' + t.dim + '」的答案。' + esc(t.desc) + '</p>';
|
||
html += '<p>' + (best.x.n === 1 ? '比如在「' + best.c + '」这道题里' : best.x.hit.length === best.x.n ? '在「' + best.c + '」的 ' + best.x.n + ' 道题里,你每次都这样选' : '尤其在「' + best.c + '」的题里,你 ' + best.x.n + ' 次有 ' + best.x.hit.length + ' 次这样选') +
|
||
(best.x.n === 1 ? ':说到' : ':比如说到') + ex.s + ',你选了<q>' + esc(exOpt) + '</q>。</p>';
|
||
html += '<p><b>他的闪光点:</b>' + esc(t.good) + '</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>' + N + ' 道题你全选了同一类,他是非常纯粹的' + t.name + '队友。</p>';
|
||
}
|
||
return html;
|
||
}
|
||
function blind(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 '<p>' + esc(t.blind) + '</p><p>「' + TYPES[low].dim + '」在他身上目前只占 <span class="num">' + p[low] + '%</span>,' + TYPES[low].low + '</p>';
|
||
}
|
||
|
||
/* ================= 雷达图(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="#FCD9C2" stroke-width="1"/>';
|
||
});
|
||
g += '<path d="M' + cx + ' ' + (cy - R) + 'V' + (cy + R) + 'M' + (cx - R) + ' ' + cy + 'H' + (cx + R) + '" stroke="#FCD9C2" stroke-width="1"/>';
|
||
var pts = radarPts(p, cx, cy, R, M);
|
||
g += '<polygon points="' + pts.map(function (x) { return x.join(','); }).join(' ') + '" fill="rgba(242,123,53,.18)" stroke="#F27B35" 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="#F27B35" 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 ? '#F27B35' : '#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);
|
||
$('#rBlind').innerHTML = blind(rec, p);
|
||
$('#rTips').innerHTML = t.tips.map(function (x, i) { return '<div class="tp"><span class="n">' + (i + 1) + '</span><p>' + esc(x) + '</p></div>'; }).join('');
|
||
$('#rMate').innerHTML = '<img src="' + t.img + '" alt=""><span><small>截图或念给他听,都可以</small><b>致' + t.name + '的你</b><p>' + esc(t.toHim) + '</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: '适合和他一起用', color: '#F27B35', bg: '#FFF1E6', 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 () {});
|
||
}
|
||
|
||
/* ================= 提示(用户要求结果页不放「复制发给 xx」类按钮) ================= */
|
||
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);
|
||
}
|
||
|
||
/* ================= 保存结果卡: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, '#FFE4D1'); g.addColorStop(.45, '#FFF4EB'); 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(242,123,53,.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 = '#F27B35'; ctx.fillText(lb, W / 2, 84);
|
||
/* 插画 */
|
||
var S = 320, ix = (W - S) / 2, iy = 132;
|
||
ctx.save(); ctx.shadowColor = 'rgba(242,123,53,.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(242,123,53,.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(242,123,53,.12)'; ctx.shadowBlur = 14; ctx.shadowOffsetY = 4;
|
||
ctx.fillStyle = '#fff'; rr(ctx, tx, 680, ws[i], 56, 28); ctx.fill(); ctx.restore();
|
||
ctx.fillStyle = '#F27B35'; 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 = '#FCD9C2'; 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(242,123,53,.18)'; ctx.fill(); ctx.strokeStyle = '#F27B35'; 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 = '#F27B35'; 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 ? '#F27B35' : '#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 ? '#F27B35' : '#4E5969'; ctx.fillText(TYPES[k].dim, 388, y + 10);
|
||
ctx.textAlign = 'right'; ctx.font = '700 25px ' + FONT; ctx.fillStyle = me ? '#F27B35' : '#1F2329'; ctx.fillText(p[k] + '%', 674, y + 10);
|
||
ctx.fillStyle = '#FFEDE1'; rr(ctx, 388, y + 24, 286, 10, 5); ctx.fill();
|
||
ctx.fillStyle = me ? '#F27B35' : '#F9C29E'; 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>
|