<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<title>你适合在哪个城市居住?</title>

<style>

  * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

  body {

    margin: 0; min-height: 100vh;

    font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;

    background: linear-gradient(160deg, #f7f3ff 0%, #eef7ff 55%, #fff7ef 100%);

    color: #2b2b2b; display: flex; justify-content: center; padding: 18px;

  }

  .app {

    width: 100%; max-width: 480px; min-height: 90vh;

    background: rgba(255,255,255,0.82); backdrop-filter: blur(10px);

    border-radius: 28px; box-shadow: 0 18px 60px rgba(90, 80, 160, 0.14);

    padding: 28px 22px 24px; display: flex; flex-direction: column;

  }

  h1 { font-size: 24px; line-height: 1.35; margin: 12px 0 10px; }

  .sub { color: #777; font-size: 14px; line-height: 1.7; margin-bottom: 22px; }

  .badge {

    display: inline-block; font-size: 12px; color: #6b5bd2;

    background: #efecff; padding: 5px 10px; border-radius: 999px; width: fit-content;

  }

  .btn {

    border: none; width: 100%; padding: 15px; border-radius: 16px;

    font-size: 16px; font-weight: 600; color: white;

    background: linear-gradient(135deg, #7b6cf6, #5aa9ff);

    cursor: pointer; margin-top: auto;

  }

  .btn:active { transform: scale(0.98); }

  .progress-wrap { margin: 10px 0 18px; }

  .progress-text { font-size: 13px; color: #888; margin-bottom: 8px; }

  .progress-bar { height: 8px; background: #eceaf7; border-radius: 999px; overflow: hidden; }

  .progress-inner {

    height: 100%; width: 0%; border-radius: 999px;

    background: linear-gradient(90deg, #7b6cf6, #5aa9ff); transition: width 0.25s ease;

  }

  .question { font-size: 19px; line-height: 1.55; font-weight: 650; margin: 8px 0 18px; }

  .option {

    width: 100%; text-align: left; border: 1.5px solid #e5e2f2; background: white;

    border-radius: 16px; padding: 15px 16px; font-size: 15px; line-height: 1.5;

    color: #333; margin-bottom: 11px; cursor: pointer; transition: all 0.15s ease;

  }

  .option:active { background: #f6f4ff; border-color: #b9b0ff; }

  .result-card { text-align: center; padding: 8px 0 4px; }

  .result-emoji { font-size: 54px; margin: 6px 0 4px; }

  .result-city {

    font-size: 30px; font-weight: 800; letter-spacing: 1px; margin: 6px 0 6px;

    background: linear-gradient(135deg, #6f5cf1, #37a7ff);

    -webkit-background-clip: text; background-clip: text; color: transparent;

  }

  .result-tag {

    display: inline-block; background: #f1eeff; color: #6b5bd2;

    border-radius: 999px; padding: 7px 14px; font-size: 13px; margin-bottom: 16px;

  }

  .result-desc {

    text-align: left; font-size: 15px; line-height: 1.85; color: #555;

    background: #faf9ff; border-radius: 18px; padding: 18px; margin: 10px 0 16px;

  }

  .disclaimer {

    font-size: 11px; color: #aaa; line-height: 1.6; text-align: center; margin-top: 16px;

  }

  .hidden { display: none; }

  .restart { background: #fff; color: #6b5bd2; border: 1.5px solid #dcd6ff; margin-top: 12px; }

  .save-btn { margin-top: 12px; background: linear-gradient(135deg, #ff8a5c, #ff5f9e); }

 

  .overlay {

    position: fixed; inset: 0; background: rgba(20, 16, 40, 0.72);

    display: flex; flex-direction: column; align-items: center; justify-content: center;

    padding: 20px; z-index: 99; backdrop-filter: blur(4px);

  }

  .overlay img {

    width: 100%; max-width: 340px; border-radius: 18px;

    box-shadow: 0 20px 60px rgba(0,0,0,0.35);

  }

  .overlay-tip { color: #fff; font-size: 14px; margin-top: 16px; text-align: center; line-height: 1.6; }

  .overlay-close {

    margin-top: 18px; border: none; background: rgba(255,255,255,0.16);

    color: #fff; padding: 12px 28px; border-radius: 999px; font-size: 15px; cursor: pointer;

  }

</style>

</head>

<body>

<div class="app">

  <section id="startScreen">

    <span class="badge">趣味测试 · 仅供娱乐</span>

    <h1>你适合在哪个城市居住?</h1>

    <p class="sub">20道题,测测你的生活节奏、社交偏好和内心向往,看看哪座城市更像你的“精神老家”。</p>

    <button class="btn" onclick="startTest()">开始测试</button>

    <p class="disclaimer">本测试仅供娱乐参考,不构成任何专业评估或建议。</p>

  </section>

 

  <section id="quizScreen" class="hidden">

    <div class="progress-wrap">

      <div class="progress-text" id="progressText">第 1 / 20 题</div>

      <div class="progress-bar"><div class="progress-inner" id="progressInner"></div></div>

    </div>

    <div class="question" id="questionText"></div>

    <div id="optionsBox"></div>

    <p class="disclaimer">请凭第一感觉选择,结果会更贴近你。</p>

  </section>

 

  <section id="resultScreen" class="hidden">

    <div class="result-card">

      <div class="result-emoji" id="resultEmoji">🏙️</div>

      <div class="result-city" id="resultCity"></div>

      <div class="result-tag" id="resultTag"></div>

      <div class="result-desc" id="resultDesc"></div>

    </div>

    <button class="btn save-btn" onclick="generatePoster()">保存结果图片</button>

    <button class="btn restart" onclick="restart()">再测一次</button>

    <p class="disclaimer">本测试仅供娱乐参考,不构成任何专业评估或建议。</p>

  </section>

</div>

 

<div id="overlay" class="overlay hidden">

  <img id="posterImg" alt="测试结果海报" />

  <div class="overlay-tip">长按图片保存到相册<br>或点击下方按钮关闭</div>

  <button class="overlay-close" onclick="closeOverlay()">关闭</button>

</div>

 

<script>

  const questions = [

    { q: "如果突然多出三天假,你的第一反应是?", options: [

      { text: "先把积压的待办清单清掉,不然玩不踏实", city: "深圳" },

      { text: "约朋友吃顿好的,再睡到自然醒", city: "成都" },

      { text: "找个海边民宿,什么都不干,就发呆", city: "厦门" },

      { text: "立刻查机票,去哪都行,先离开再说", city: "大理" }

    ]},

    { q: "你手机里最舍不得删的 App 类型是?", options: [

      { text: "效率工具/课程学习类,感觉留着就能变强", city: "深圳" },

      { text: "拍照修图/看展购票类,审美不能丢", city: "杭州" },

      { text: "美食探店/外卖类,活着就是为了吃", city: "成都" },

      { text: "旅行户外/冥想白噪音类,随时准备逃离", city: "大理" }

    ]},

    { q: "朋友对你的第一印象通常是?", options: [

      { text: "“你看起来好忙,是不是又在搞钱”", city: "深圳" },

      { text: "“你有点文艺,但又不完全文艺”", city: "杭州" },

      { text: "“你好会生活,跟你玩肯定不亏”", city: "成都" },

      { text: "“你身上有种松弛感,像在海边长大”", city: "厦门" }

    ]},

    { q: "下面哪种“崩溃”最让你受不了?", options: [

      { text: "计划被打乱,效率直接归零", city: "深圳" },

      { text: "城市太糙,找不到一家像样的咖啡馆", city: "杭州" },

      { text: "连续一周看不到天,窗外全是墙", city: "厦门" },

      { text: "被拉进一个 99+ 的群,还要挨个回复", city: "大理" }

    ]},

    { q: "你理想中的周末早晨是?", options: [

      { text: "冲杯咖啡,坐在窗边看书,顺便拍张照", city: "杭州" },

      { text: "睡到自然醒,下楼吃碗面,再逛个菜市场", city: "成都" },

      { text: "早起去海边/公园散步,吹吹风", city: "厦门" },

      { text: "没有早晨,睡到几点算几点", city: "大理" }

    ]},

    { q: "如果只能保留一种“奢侈”,你选?", options: [

      { text: "事业上有上升空间,累点也认", city: "深圳" },

      { text: "随时能约到人吃饭,永远不孤单", city: "成都" },

      { text: "住在有海/有山的地方,出门就是风景", city: "厦门" },

      { text: "时间完全自由,想干嘛干嘛", city: "大理" }

    ]},

    { q: "你更愿意为哪种“无用之美”花钱?", options: [

      { text: "一个能提升效率的会员/工具", city: "深圳" },

      { text: "一束花/一个好看的杯子/一张展票", city: "杭州" },

      { text: "一顿环境很好但有点贵的饭", city: "成都" },

      { text: "一张去山里的车票,什么都不带", city: "大理" }

    ]},

    { q: "别人在群里争论时,你通常?", options: [

      { text: "默默整理逻辑,最后甩一段总结", city: "深圳" },

      { text: "发个表情包缓和气氛,然后撤", city: "杭州" },

      { text: "忍不住接话,越聊越嗨,最后约饭", city: "成都" },

      { text: "看完就走,内心毫无波澜", city: "厦门" }

    ]},

    { q: "你对“排队”的忍耐度取决于?", options: [

      { text: "前面的人是不是在浪费时间", city: "深圳" },

      { text: "排队的地方好不好看,能不能拍照", city: "杭州" },

      { text: "排队的地方有没有海风/树荫", city: "厦门" },

      { text: "我根本不会去需要排队的地方", city: "大理" }

    ]},

    { q: "如果让你选一个城市住三年,你最看重?", options: [

      { text: "城市审美和文化氛围,日子要好看", city: "杭州" },

      { text: "生活成本和松弛感,舒服最重要", city: "成都" },

      { text: "气候和自然环境,每天像度假", city: "厦门" },

      { text: "能不能按自己的节奏活,不被卷", city: "大理" }

    ]},

    { q: "你更接近哪种“社交电量”?", options: [

      { text: "只跟固定几个人玩,边界清晰,不浪费时间", city: "深圳" },

      { text: "越聊越有劲,人越多越嗨,散场就空虚", city: "成都" },

      { text: "喜欢一对一的深度聊天,最好在海边", city: "厦门" },

      { text: "见完人需要独处三天回血,别找我", city: "大理" }

    ]},

    { q: "下面哪句话最像你的内心 OS?", options: [

      { text: "“搞钱要紧,别的以后再说”", city: "深圳" },

      { text: "“我想把日子过得好看一点”", city: "杭州" },

      { text: "“人生苦短,先吃顿好的”", city: "成都" },

      { text: "“我想去一个有风的地方”", city: "大理" }

    ]},

    { q: "你手机相册里最多的是?", options: [

      { text: "工作截图/学习笔记/待办清单", city: "深圳" },

      { text: "展、咖啡、街景、穿搭、天空", city: "杭州" },

      { text: "美食和聚餐合照,九宫格根本不够", city: "成都" },

      { text: "海、晚霞、树、花、猫", city: "厦门" }

    ]},

    { q: "如果明天开始远程办公,你最想搬去?", options: [

      { text: "不搬,远程也要待在机会最多的地方", city: "深圳" },

      { text: "气候舒服、生活精致的城市", city: "杭州" },

      { text: "海边城市,每天能看海", city: "厦门" },

      { text: "有山有水、房租便宜的小城", city: "大理" }

    ]},

    { q: "你对“成功”的第一反应是?", options: [

      { text: "被看见、被认可,做出有审美的东西", city: "杭州" },

      { text: "过上舒服自在的日子,想吃什么吃什么", city: "成都" },

      { text: "有一间能看海的房子,和喜欢的人", city: "厦门" },

      { text: "按自己的节奏活着,不被任何人定义", city: "大理" }

    ]},

    { q: "下面哪种天气最让你想出门?", options: [

      { text: "阴天,不晒,适合办事", city: "深圳" },

      { text: "晚上,凉快,适合吃宵夜", city: "成都" },

      { text: "晴天,海边有风", city: "厦门" },

      { text: "下雨天,适合一个人待着", city: "大理" }

    ]},

    { q: "你更受不了哪种“浪费”?", options: [

      { text: "浪费时间在无效社交上", city: "深圳" },

      { text: "浪费一个好天气没出门拍照", city: "杭州" },

      { text: "浪费一顿好吃的没好好吃", city: "成都" },

      { text: "浪费一个可以独处的下午", city: "大理" }

    ]},

    { q: "朋友说“你变了”,你第一反应是?", options: [

      { text: "“变强了还是变秃了?”", city: "深圳" },

      { text: "“变好看了还是变胖了?”", city: "杭州" },

      { text: "“变开朗了还是变宅了?”", city: "成都" },

      { text: "“变松弛了还是变黑了?”", city: "厦门" }

    ]},

    { q: "你理想中的“家”窗外是?", options: [

      { text: "高楼和城市灯光,越晚越亮", city: "深圳" },

      { text: "梧桐树和街道,有烟火也有距离", city: "杭州" },

      { text: "海和晚霞,每天不重样", city: "厦门" },

      { text: "山、云、田野,最好还有一只猫", city: "大理" }

    ]},

    { q: "最后,你更相信哪种生活哲学?", options: [

      { text: "在现实和理想之间找平衡", city: "杭州" },

      { text: "把日子过舒服最重要", city: "成都" },

      { text: "慢慢来,比较快", city: "厦门" },

      { text: "自由比稳定更珍贵", city: "大理" }

    ]}

  ];

 

  const results = {

    "深圳": { emoji: "🌃", tag: "效率型野心家", desc: "你适合深圳,不是因为你喜欢加班,而是你喜欢“事情能成”的感觉。你需要快节奏、多机会、边界清晰的环境,把精力放在真正重要的事上。但别忘了,偶尔浪费时间,也是一种能力。" },

    "杭州": { emoji: "🌿", tag: "精致平衡派", desc: "你适合杭州,或者任何“既能搞事业、又能好好生活”的城市。你在意审美、细节和距离感,喜欢努力,但不想被努力吞掉。对你来说,最好的城市是能让你在效率和松弛之间来回切换的地方。" },

    "成都": { emoji: "🍲", tag: "烟火气生活家", desc: "你适合成都,或者任何“人味很重”的城市。你需要朋友、美食、热闹和随时能出门的夜晚。你相信生活不是用来赶路的,而是用来过的。对你来说,城市再大,不如楼下那家好吃的店和随叫随到的人。" },

    "厦门": { emoji: "🌊", tag: "海边治愈系", desc: "你适合厦门,或者任何能让你靠近海和风的地方。你需要空间呼吸,需要自然给你回血。你不排斥努力,但不愿意为了效率牺牲生活里的风景。对你来说,一座城市最好的样子,是傍晚散步时不用赶时间。" },

    "大理": { emoji: "⛰️", tag: "自由慢生活者", desc: "你适合大理,或者任何允许你“按自己节奏来”的地方。你讨厌被比较、被催促、被塞进统一模板。你需要山、云、田野和足够的独处时间。对你来说,城市不必很大,但一定要能让你喘口气。" }

  };

 

  let current = 0;

  let scores = {};

  let finalCity = "";

 

  function startTest() {

    current = 0;

    scores = { "深圳": 0, "杭州": 0, "成都": 0, "厦门": 0, "大理": 0 };

    document.getElementById("startScreen").classList.add("hidden");

    document.getElementById("resultScreen").classList.add("hidden");

    document.getElementById("quizScreen").classList.remove("hidden");

    renderQuestion();

  }

 

  function renderQuestion() {

    const q = questions[current];

    document.getElementById("progressText").textContent = `第 ${current + 1} / ${questions.length} 题`;

    document.getElementById("progressInner").style.width = `${(current / questions.length) * 100}%`;

    document.getElementById("questionText").textContent = q.q;

    const box = document.getElementById("optionsBox");

    box.innerHTML = "";

    q.options.forEach(opt => {

      const btn = document.createElement("button");

      btn.className = "option";

      btn.textContent = opt.text;

      btn.onclick = () => choose(opt.city);

      box.appendChild(btn);

    });

  }

 

  function choose(city) {

    scores[city] = (scores[city] || 0) + 1;

    current++;

    if (current < questions.length) renderQuestion();

    else showResult();

  }

 

  function showResult() {

    let topCity = "杭州", topScore = -1;

    Object.keys(scores).forEach(city => {

      if (scores[city] > topScore) { topScore = scores[city]; topCity = city; }

    });

    finalCity = topCity;

    const r = results[topCity];

    document.getElementById("resultEmoji").textContent = r.emoji;

    document.getElementById("resultCity").textContent = topCity;

    document.getElementById("resultTag").textContent = r.tag;

    document.getElementById("resultDesc").textContent = r.desc;

    document.getElementById("quizScreen").classList.add("hidden");

    document.getElementById("resultScreen").classList.remove("hidden");

  }

 

  function restart() {

    document.getElementById("resultScreen").classList.add("hidden");

    document.getElementById("startScreen").classList.remove("hidden");

  }

 

  function generatePoster() {

    const r = results[finalCity];

    const W = 750, H = 1000;

    const canvas = document.createElement("canvas");

    canvas.width = W;

    canvas.height = H;

    const ctx = canvas.getContext("2d");

 

    const bg = ctx.createLinearGradient(0, 0, W, H);

    bg.addColorStop(0, "#f5f1ff");

    bg.addColorStop(0.55, "#eaf5ff");

    bg.addColorStop(1, "#fff4ea");

    ctx.fillStyle = bg;

    ctx.fillRect(0, 0, W, H);

 

    roundRect(ctx, 45, 55, W - 90, H - 110, 42);

    ctx.fillStyle = "rgba(255,255,255,0.88)";

    ctx.fill();

 

    ctx.textAlign = "center";

    ctx.textBaseline = "middle";

 

    ctx.font = '96px "Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif';

    ctx.fillText(r.emoji, W / 2, 190);

 

    ctx.font = 'bold 76px "PingFang SC","Microsoft YaHei",sans-serif';

    const cityGrad = ctx.createLinearGradient(W/2 - 160, 0, W/2 + 160, 0);

    cityGrad.addColorStop(0, "#6f5cf1");

    cityGrad.addColorStop(1, "#37a7ff");

    ctx.fillStyle = cityGrad;

    ctx.fillText(finalCity, W / 2, 320);

 

    ctx.font = '30px "PingFang SC","Microsoft YaHei",sans-serif';

    const tagText = r.tag;

    const tagW = ctx.measureText(tagText).width + 56;

    const tagH = 58;

    const tagX = W / 2 - tagW / 2;

    const tagY = 385;

    roundRect(ctx, tagX, tagY, tagW, tagH, tagH / 2);

    ctx.fillStyle = "#f1eeff";

    ctx.fill();

    ctx.fillStyle = "#6b5bd2";

    ctx.fillText(tagText, W / 2, tagY + tagH / 2 + 1);

 

    ctx.font = '30px "PingFang SC","Microsoft YaHei",sans-serif';

    ctx.fillStyle = "#555";

    ctx.textAlign = "left";

    const maxWidth = W - 220;

    const startX = 110;

    let startY = 500;

    const lineHeight = 52;

    const lines = wrapText(ctx, r.desc, maxWidth);

    lines.forEach((line, i) => {

      ctx.fillText(line, startX, startY + i * lineHeight);

    });

 

    ctx.strokeStyle = "#eee";

    ctx.lineWidth = 1;

    ctx.beginPath();

    ctx.moveTo(110, 860);

    ctx.lineTo(W - 110, 860);

    ctx.stroke();

 

    ctx.textAlign = "center";

    ctx.font = '26px "PingFang SC","Microsoft YaHei",sans-serif';

    ctx.fillStyle = "#8a7cf0";

    ctx.fillText("截图分享,看看谁和你同城", W / 2, 900);

 

    ctx.font = '20px "PingFang SC","Microsoft YaHei",sans-serif';

    ctx.fillStyle = "#bbb";

    ctx.fillText("本测试仅供娱乐参考,不构成专业评估", W / 2, 945);

 

    const dataUrl = canvas.toDataURL("image/png");

    const img = document.getElementById("posterImg");

    img.src = dataUrl;

    document.getElementById("overlay").classList.remove("hidden");

  }

 

  function roundRect(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 wrapText(ctx, text, maxWidth) {

    const lines = [];

    let line = "";

    for (const ch of text) {

      const test = line + ch;

      if (ctx.measureText(test).width > maxWidth && line) {

        lines.push(line);

        line = ch;

      } else {

        line = test;

      }

    }

    if (line) lines.push(line);

    return lines;

  }

 

  function closeOverlay() {

    document.getElementById("overlay").classList.add("hidden");

  }

</script>

</body>

</html>