• linmao
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>鹈鹕骑自行车 · SVG 2D 动画</title>
    <style>
      :root{
        --speed: 1;
        --spin-dur: 1s;
        --bounce-dur: .5s;
      }
      *{box-sizing:border-box}
      body{
        margin:0; min-height:100vh; display:flex; flex-direction:column; align-items:center;
        font-family: "PingFang SC","Microsoft YaHei",system-ui,sans-serif;
        background:#0f172a; color:#e2e8f0;
        background: radial-gradient(1200px 600px at 50% -10%, #334155 0%, #0f172a 60%, #020617 100%);
        padding:24px 16px 40px;
      }
      h1{margin:8px 0 4px; font-size:clamp(22px,3.5vw,34px); letter-spacing:.06em}
      h1 span{ background:linear-gradient(90deg,#fde68a,#fb923c,#f472b6); -webkit-background-clip:text; background-clip:text; color:transparent;}
      p.sub{margin:0 0 16px; opacity:.7}
      .stage{
        width:min(920px,96vw); border-radius:20px; overflow:hidden;
        box-shadow:0 20px 60px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.08) inset;
        background:#87ceeb; position:relative;
      }
      svg{display:block; width:100%; height:auto}
      .panel{
        width:min(920px,96vw); margin-top:14px; display:flex; flex-wrap:wrap; gap:12px; align-items:center; justify-content:space-between;
        background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.1); border-radius:14px; padding:12px 16px;
        backdrop-filter: blur(8px);
      }
      .controls{display:flex; gap:10px; align-items:center; flex-wrap:wrap}
      button{
        border:0; border-radius:999px; padding:9px 18px; cursor:pointer; font-weight:700;
        background:#fff; color:#0f172a; transition:.2s;
      }
      button:hover{transform:translateY(-1px)}
      button.secondary{background:rgba(255,255,255,.14); color:#fff; border:1px solid rgba(255,255,255,.2)}
      input[type=range]{accent-color:#fb923c; width:160px}
      label{font-size:14px; opacity:.9; display:flex; gap:8px; align-items:center}
      .hint{font-size:13px; opacity:.6}
    
      /* ===== SVG animations ===== */
      .wheel-spin{
        transform-box: fill-box; transform-origin:center;
        animation: spin var(--spin-dur) linear infinite;
      }
      @keyframes spin{ to{transform:rotate(360deg)} }
    
      #rider-bounce{
        animation: bounce var(--bounce-dur) ease-in-out infinite alternate;
      }
      @keyframes bounce{
        from{transform:translateY(0)}
        to{transform:translateY(-5px)}
      }
      #body-bob{ animation: bodyBob var(--bounce-dur) ease-in-out infinite alternate; }
      @keyframes bodyBob{ from{transform:translateY(0) rotate(-1deg)} to{transform:translateY(-4px) rotate(1deg)} }
    
      #wing{ transform-box:fill-box; transform-origin: 20% 20%; animation: flap .7s ease-in-out infinite alternate; }
      @keyframes flap{ from{transform:rotate(-8deg)} to{transform:rotate(28deg)} }
    
      #neck-head{ animation: headBob var(--bounce-dur) ease-in-out infinite alternate; transform-box:fill-box; transform-origin:0% 100%; }
      @keyframes headBob{ from{transform:translateY(0) rotate(0deg)} to{transform:translateY(-3px) rotate(-2.5deg)} }
    
      #pouch{ transform-box:fill-box; transform-origin: top center; animation: pouchWobble 1s ease-in-out infinite alternate; }
      @keyframes pouchWobble{ from{transform:scaleY(1) skewX(0deg)} to{transform:scaleY(1.07) skewX(2deg)} }
    
      #eye-lid{ transform-box:fill-box; transform-origin:center; animation: blink 4s infinite; }
      @keyframes blink{ 0%,92%,100%{transform:scaleY(1)} 95%{transform:scaleY(.08)} }
    
      #scarf-tail{ transform-box:fill-box; transform-origin:right center; animation: scarfWave .6s ease-in-out infinite alternate; }
      @keyframes scarfWave{ from{transform:rotate(-6deg) scaleX(1)} to{transform:rotate(8deg) scaleX(1.08)} }
      #scarf-tail2{ animation: wave2 .6s ease-in-out infinite alternate; }
      @keyframes wave2{ from{transform:translateY(0)} to{transform:translateY(-4px)} }
    
      .cloud{ animation: drift linear infinite; }
      .cloud.c1{ animation-duration:26s } .cloud.c2{ animation-duration:38s } .cloud.c3{ animation-duration:55s }
      @keyframes drift{ from{transform:translateX(-140px)} to{transform:translateX(940px)} }
    
      #road-dashes{ animation: roadMove .5s linear infinite; }
      @keyframes roadMove{ to{ stroke-dashoffset:-40; } }
    
      .bg-scroll{ animation: bgMove 3.2s linear infinite; }
      .bg-scroll-fast{ animation: bgMove 1.6s linear infinite; }
      @keyframes bgMove{ to{transform:translateX(-200px)} }
    
      .dust{ animation: dustPuff 1s ease-out infinite; opacity:0; transform-box:fill-box; transform-origin:center; }
      .dust.d2{ animation-delay:.33s } .dust.d3{ animation-delay:.66s }
      @keyframes dustPuff{
        0%{opacity:.7; transform:translate(0,0) scale(.5)}
        100%{opacity:0; transform:translate(-70px,-18px) scale(1.4)}
      }
      .speed-line{ animation: speedFlash .45s linear infinite; opacity:0 }
      .speed-line.s2{animation-delay:.15s} .speed-line.s3{animation-delay:.3s}
      @keyframes speedFlash{ 0%{opacity:0; transform:translateX(20px)} 30%{opacity:.7} 100%{opacity:0; transform:translateX(-60px)} }
    
      #front-basket{ animation: basketShake var(--bounce-dur) ease-in-out infinite alternate; transform-box:fill-box; transform-origin:top center;}
      @keyframes basketShake{ from{transform:rotate(-1.5deg)} to{transform:rotate(1.5deg)} }
    
      .pedal-crank{ transform-box:fill-box; transform-origin:center; animation: spin var(--spin-dur) linear infinite; }
      .paused *{ animation-play-state:paused !important; }
    
      /* night mode (toggle class on svg) */
      svg.night #sky{ fill:url(#nightGrad) }
      svg.night .stars{opacity:1} .stars{opacity:0; transition:.6s}
      svg.night #sun{opacity:0} svg.night #moon{opacity:1}
      #moon{opacity:0; transition:.6s}
      #sun{transition:.6s}
    </style>
    </head>
    <body>
    <h1>🚲 <span>鹈鹕骑自行车</span> · SVG 2D 动画</h1>
    <p class="sub">纯 SVG + CSS + 少量 JS(脚踏腿部 IK 跟随)· 车轮转动 / 脚踏 / 翅膀扇动 / 围巾飘动 / 眨眼 / 沙尘</p>
    
    <div class="stage">
    <svg id="scene" viewBox="0 0 900 520" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="鹈鹕骑自行车动画">
    <defs>
      <linearGradient id="skyGrad" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stop-color="#38bdf8"/><stop offset="55%" stop-color="#bae6fd"/><stop offset="100%" stop-color="#fef9c3"/>
      </linearGradient>
      <linearGradient id="nightGrad" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stop-color="#020617"/><stop offset="60%" stop-color="#1e1b4b"/><stop offset="100%" stop-color="#334155"/>
      </linearGradient>
      <linearGradient id="roadGrad" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stop-color="#64748b"/><stop offset="100%" stop-color="#334155"/>
      </linearGradient>
      <linearGradient id="bodyGrad" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stop-color="#ffffff"/><stop offset="100%" stop-color="#e2e8f0"/>
      </linearGradient>
      <linearGradient id="beakGrad" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stop-color="#fdba74"/><stop offset="100%" stop-color="#ea580c"/>
      </linearGradient>
      <linearGradient id="pouchGrad" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stop-color="#ffedd5"/><stop offset="100%" stop-color="#fb923c"/>
      </linearGradient>
      <radialGradient id="sunGrad" cx="50%" cy="50%" r="50%">
        <stop offset="0%" stop-color="#fefce8"/><stop offset="45%" stop-color="#fde047"/><stop offset="100%" stop-color="#f59e0b" stop-opacity=".2"/>
      </radialGradient>
    </defs>
    
    <!-- 天空 -->
    <rect id="sky" x="0" y="0" width="900" height="520" fill="url(#skyGrad)"/>
    <g class="stars" fill="white">
      <circle cx="80" cy="60" r="2"/><circle cx="200" cy="40" r="1.6"/><circle cx="340" cy="80" r="2"/>
      <circle cx="500" cy="35" r="1.5"/><circle cx="640" cy="70" r="2"/><circle cx="780" cy="50" r="1.8"/>
      <circle cx="860" cy="120" r="1.4"/><circle cx="120" cy="140" r="1.3"/><circle cx="420" cy="120" r="1.2"/>
    </g>
    
    <!-- 太阳 / 月亮 -->
    <g id="sun" transform="translate(750,90)">
      <circle r="58" fill="url(#sunGrad)"/>
      <circle r="36" fill="#fde047" stroke="#f59e0b" stroke-width="3"/>
    </g>
    <g id="moon" transform="translate(750,90)">
      <circle r="30" fill="#e2e8f0"/><circle cx="10" cy="-6" r="6" fill="#94a3b8" opacity=".6"/><circle cx="-8" cy="8" r="4" fill="#94a3b8" opacity=".5"/>
    </g>
    
    <!-- 云 -->
    <g class="cloud c1" transform="translate(0,70)">
      <g fill="white" opacity=".95"><ellipse cx="0" cy="0" rx="42" ry="22"/><ellipse cx="35" cy="-10" rx="30" ry="20"/><ellipse cx="-35" cy="-6" rx="26" ry="16"/></g>
    </g>
    <g class="cloud c2" transform="translate(0,130)">
      <g fill="white" opacity=".85"><ellipse cx="0" cy="0" rx="52" ry="20"/><ellipse cx="40" cy="-12" rx="28" ry="18"/></g>
    </g>
    <g class="cloud c3" transform="translate(0,45)">
      <g fill="white" opacity=".7"><ellipse cx="0" cy="0" rx="36" ry="16"/><ellipse cx="28" cy="-8" rx="22" ry="14"/></g>
    </g>
    
    <!-- 远山 -->
    <path d="M0 340 L120 220 L210 300 L320 200 L430 310 L540 230 L650 320 L760 240 L900 330 L900 420 L0 420 Z" fill="#7dd3fc" opacity=".55"/>
    <path d="M0 360 L150 270 L280 340 L420 260 L580 350 L720 280 L900 360 L900 430 L0 430 Z" fill="#0284c7" opacity=".35"/>
    <!-- 飞鸟 -->
    <g stroke="#334155" stroke-width="2.5" fill="none" stroke-linecap="round" opacity=".6">
      <path d="M200 120 q8 -8 16 0 q8 -8 16 0"><animate attributeName="d" dur="1.2s" repeatCount="indefinite"
        values="M200 120 q8 -8 16 0 q8 -8 16 0;M200 125 q8 -2 16 0 q8 -2 16 0;M200 120 q8 -8 16 0 q8 -8 16 0"/></path>
      <path d="M260 100 q6 -6 12 0 q6 -6 12 0"><animate attributeName="d" dur="1s" repeatCount="indefinite"
        values="M260 100 q6 -6 12 0 q6 -6 12 0;M260 105 q6 -1 12 0 q6 -1 12 0;M260 100 q6 -6 12 0 q6 -6 12 0"/></path>
    </g>
    
    <!-- 背景树(滚动) -->
    <g class="bg-scroll" opacity=".9">
      <g id="trees-pattern">
        <!-- repeat every 200px -->
        <g transform="translate(0,0)">
          <rect x="40" y="320" width="14" height="60" rx="4" fill="#92400e"/>
          <circle cx="47" cy="300" r="32" fill="#16a34a"/><circle cx="25" cy="315" r="20" fill="#22c55e"/>
        </g>
        <g transform="translate(200,0)">
          <rect x="40" y="320" width="14" height="60" rx="4" fill="#92400e"/>
          <circle cx="47" cy="300" r="32" fill="#15803d"/><circle cx="70" cy="315" r="18" fill="#22c55e"/>
        </g>
        <g transform="translate(400,0)">
          <rect x="40" y="320" width="14" height="60" rx="4" fill="#92400e"/>
          <circle cx="47" cy="300" r="32" fill="#16a34a"/><circle cx="25" cy="315" r="20" fill="#22c55e"/>
        </g>
        <g transform="translate(600,0)">
          <rect x="40" y="320" width="14" height="60" rx="4" fill="#92400e"/>
          <circle cx="47" cy="300" r="32" fill="#15803d"/><circle cx="70" cy="315" r="18" fill="#22c55e"/>
        </g>
        <g transform="translate(800,0)">
          <rect x="40" y="320" width="14" height="60" rx="4" fill="#92400e"/>
          <circle cx="47" cy="300" r="32" fill="#16a34a"/><circle cx="25" cy="315" r="20" fill="#22c55e"/>
        </g>
        <g transform="translate(1000,0)">
          <rect x="40" y="320" width="14" height="60" rx="4" fill="#92400e"/>
          <circle cx="47" cy="300" r="32" fill="#15803d"/>
        </g>
      </g>
    </g>
    
    <!-- 地面 + 公路 -->
    <rect x="0" y="380" width="900" height="140" fill="#86efac"/>
    <rect x="0" y="400" width="900" height="90" fill="url(#roadGrad)"/>
    <rect x="0" y="400" width="900" height="8" fill="#e2e8f0"/>
    <g class="bg-scroll-fast">
      <g fill="#22c55e">
        <rect x="0" y="382" width="80" height="10" rx="5" opacity=".6"/><rect x="200" y="382" width="80" height="10" rx="5" opacity=".6"/>
        <rect x="400" y="382" width="80" height="10" rx="5" opacity=".6"/><rect x="600" y="382" width="80" height="10" rx="5" opacity=".6"/>
        <rect x="800" y="382" width="80" height="10" rx="5" opacity=".6"/><rect x="1000" y="382" width="80" height="10" rx="5" opacity=".6"/>
      </g>
    </g>
    <line id="road-dashes" x1="0" y1="448" x2="900" y2="448" stroke="#fde047" stroke-width="8" stroke-dasharray="28 12" stroke-linecap="round"/>
    
    <!-- 速度线 -->
    <g stroke="white" stroke-width="5" stroke-linecap="round">
      <line class="speed-line" x1="220" y1="300" x2="150" y2="300"/>
      <line class="speed-line s2" x1="240" y1="340" x2="150" y2="340"/>
      <line class="speed-line s3" x1="220" y1="260" x2="160" y2="260"/>
    </g>
    
    <!-- ============ 鹈鹕 + 自行车 ============ -->
    <g id="rider-bounce">
      <!-- 阴影 -->
      <ellipse cx="410" cy="476" rx="140" ry="12" fill="black" opacity=".18"/>
    
      <!-- 后轮 -->
      <g transform="translate(320,420)">
        <circle r="52" fill="#1e293b" /><circle r="44" fill="#f8fafc"/>
        <g class="wheel-spin">
          <g stroke="#0f172a" stroke-width="3">
            <line x1="-40" y1="0" x2="40" y2="0"/><line x1="0" y1="-40" x2="0" y2="40"/>
            <line x1="-28" y1="-28" x2="28" y2="28"/><line x1="-28" y1="28" x2="28" y2="-28"/>
          </g>
          <circle r="8" fill="#fb923c" stroke="#0f172a" stroke-width="2"/>
        </g>
        <circle r="52" fill="none" stroke="#0f172a" stroke-width="6"/>
      </g>
      <!-- 前轮 -->
      <g transform="translate(520,420)">
        <circle r="52" fill="#1e293b"/><circle r="44" fill="#f8fafc"/>
        <g class="wheel-spin">
          <g stroke="#0f172a" stroke-width="3">
            <line x1="-40" y1="0" x2="40" y2="0"/><line x1="0" y1="-40" x2="0" y2="40"/>
            <line x1="-28" y1="-28" x2="28" y2="28"/><line x1="-28" y1="28" x2="28" y2="-28"/>
          </g>
          <circle r="8" fill="#fb923c" stroke="#0f172a" stroke-width="2"/>
        </g>
        <circle r="52" fill="none" stroke="#0f172a" stroke-width="6"/>
        <!-- 挡泥板 -->
        <path d="M-54 -8 A 56 56 0 0 1 30 -48" fill="none" stroke="#ef4444" stroke-width="7" stroke-linecap="round"/>
      </g>
    
      <!-- 车架 -->
      <g stroke-linecap="round" stroke-linejoin="round" fill="none">
        <line x1="320" y1="420" x2="405" y2="418" stroke="#ef4444" stroke-width="9"/> <!-- 后下叉 -->
        <line x1="320" y1="420" x2="375" y2="330" stroke="#ef4444" stroke-width="9"/> <!-- 立管 -->
        <line x1="375" y1="330" x2="405" y2="418" stroke="#ef4444" stroke-width="8"/>
        <line x1="405" y1="418" x2="505" y2="330" stroke="#dc2626" stroke-width="9"/> <!-- 下管 -->
        <line x1="375" y1="330" x2="505" y2="330" stroke="#ef4444" stroke-width="8"/> <!-- 上管 -->
        <line x1="505" y1="330" x2="520" y2="420" stroke="#dc2626" stroke-width="9"/> <!-- 前叉 -->
        <line x1="505" y1="330" x2="530" y2="305" stroke="#1e293b" stroke-width="8"/> <!-- 车把立 -->
      </g>
      <!-- 座垫 & 车把 -->
      <rect x="348" y="312" width="54" height="16" rx="8" fill="#1e293b"/>
      <rect x="368" y="326" width="10" height="12" fill="#94a3b8"/>
      <g transform="translate(530,305)">
        <rect x="-8" y="-8" width="36" height="12" rx="6" fill="#1e293b"/>
        <circle cx="26" cy="-2" r="4" fill="#fde047"/>
      </g>
      <!-- 车灯 -->
      <g transform="translate(534,332)"><circle r="9" fill="#fef08a" stroke="#1e293b" stroke-width="2.5"/><circle r="3.5" fill="#facc15"/></g>
    
      <!-- 前车篮 + 鱼! -->
      <g id="front-basket" transform="translate(545,340)">
        <path d="M0 0 L56 0 L50 36 L6 36 Z" fill="#d6a35c" stroke="#92400e" stroke-width="3" stroke-linejoin="round"/>
        <line x1="8" y1="12" x2="52" y2="12" stroke="#92400e" stroke-width="2" opacity=".6"/>
        <line x1="10" y1="24" x2="51" y2="24" stroke="#92400e" stroke-width="2" opacity=".6"/>
        <!-- 鱼尾巴露出 -->
        <g transform="translate(28,-6) rotate(-12)">
          <ellipse cx="0" cy="0" rx="16" ry="8" fill="#38bdf8" stroke="#075985" stroke-width="2"/>
          <path d="M14 0 L26 -9 L26 9 Z" fill="#0284c7"/>
          <circle cx="-7" cy="-1" r="2" fill="#0f172a"/>
        </g>
      </g>
    
      <!-- 中轴 & 脚踏曲柄 (JS 驱动旋转) -->
      <g transform="translate(405,418)">
        <circle r="10" fill="#1e293b"/>
        <g id="crank">
          <line id="crank-arm1" x1="0" y1="0" x2="0" y2="0" stroke="#1e293b" stroke-width="6" stroke-linecap="round"/>
          <line id="crank-arm2" x1="0" y1="0" x2="0" y2="0" stroke="#1e293b" stroke-width="6" stroke-linecap="round"/>
          <rect id="pedal1" x="-12" y="-5" width="24" height="10" rx="3" fill="#0f172a"/>
          <rect id="pedal2" x="-12" y="-5" width="24" height="10" rx="3" fill="#0f172a"/>
        </g>
      </g>
    
      <!-- 腿 (JS 更新 path d) -->
      <path id="leg-far" d="" fill="none" stroke="#f59e0b" stroke-width="10" stroke-linecap="round" stroke-linejoin="round" opacity=".7"/>
      <path id="leg-near" d="" fill="none" stroke="#ea580c" stroke-width="11" stroke-linecap="round" stroke-linejoin="round"/>
    
      <!-- ===== 鹈鹕身体 ===== -->
      <g id="body-bob">
        <!-- 尾巴 -->
        <path d="M300 300 L262 288 L268 306 L258 314 L300 320 Z" fill="#cbd5e1" stroke="#64748b" stroke-width="2" stroke-linejoin="round"/>
        <!-- 身体 -->
        <ellipse cx="365" cy="280" rx="72" ry="52" fill="url(#bodyGrad)" stroke="#0f172a" stroke-width="3.5"/>
        <ellipse cx="350" cy="300" rx="40" ry="26" fill="#e2e8f0" opacity=".8"/>
        <!-- 翅膀 -->
        <g id="wing" transform="translate(360,270)">
          <path d="M0 0 C -40 -18 -78 -12 -96 14 C -70 22 -38 22 0 12 Z" fill="#f1f5f9" stroke="#0f172a" stroke-width="3" stroke-linejoin="round"/>
          <path d="M-10 2 C -36 -6 -62 -4 -78 8" fill="none" stroke="#94a3b8" stroke-width="2.5" stroke-linecap="round"/>
          <path d="M-8 8 C -30 4 -52 6 -64 14" fill="none" stroke="#94a3b8" stroke-width="2" stroke-linecap="round"/>
        </g>
        <!-- 围巾 -->
        <g transform="translate(318,232)">
          <rect x="-26" y="-12" width="40" height="24" rx="10" fill="#ef4444"/>
          <rect x="-26" y="-12" width="12" height="24" fill="#b91c1c" opacity=".5"/>
          <g id="scarf-tail">
            <path id="scarf-tail2" d="M-26 0 C -60 -14 -84 -8 -108 6 C -86 12 -60 16 -26 12 Z" fill="#ef4444" stroke="#991b1b" stroke-width="2"/>
            <line x1="-92" y1="-2" x2="-92" y2="10" stroke="#fecaca" stroke-width="3"/>
            <line x1="-82" y1="-2" x2="-82" y2="11" stroke="#fecaca" stroke-width="3"/>
          </g>
        </g>
        <!-- 脖子 + 头 -->
        <g id="neck-head">
          <path d="M415 250 C 445 230 455 200 448 170" fill="none" stroke="white" stroke-width="30" stroke-linecap="round"/>
          <path d="M415 250 C 445 230 455 200 448 170" fill="none" stroke="#0f172a" stroke-width="33" stroke-linecap="round" opacity=".08"/>
          <path d="M415 250 C 445 230 455 200 448 170" fill="none" stroke="#cbd5e1" stroke-width="30" stroke-linecap="round" stroke-dasharray="0" opacity=".35"/>
          <!-- 头 -->
          <ellipse cx="452" cy="152" rx="34" ry="28" fill="white" stroke="#0f172a" stroke-width="3"/>
          <!-- 头顶毛 -->
          <path d="M428 132 q6 -14 12 0 q6 -14 12 0 q6 -12 12 -2" fill="none" stroke="#0f172a" stroke-width="3" stroke-linecap="round"/>
          <!-- 眼睛 -->
          <g transform="translate(462,146)">
            <circle r="10" fill="white" stroke="#0f172a" stroke-width="2.5"/>
            <circle cx="2.5" cy="1" r="5" fill="#0f172a"/>
            <circle cx="4" cy="-0.5" r="1.8" fill="white"/>
            <rect id="eye-lid" x="-11" y="-11" width="22" height="22" rx="11" fill="white"/>
          </g>
          <!-- 腮红 -->
          <ellipse cx="442" cy="162" rx="7" ry="4.5" fill="#fda4af" opacity=".8"/>
          <!-- 喙 -->
          <g transform="translate(480,150)">
            <path d="M0 -8 L110 -2 L0 8 Z" fill="url(#beakGrad)" stroke="#9a3412" stroke-width="2.5" stroke-linejoin="round"/>
            <line x1="6" y1="1" x2="102" y2="1" stroke="#9a3412" stroke-width="1.6" opacity=".7"/>
            <circle cx="104" cy="-1" r="3" fill="#7c2d12"/>
            <!-- 喉囊 -->
            <path id="pouch" d="M4 7 C 40 14 80 12 104 0 C 88 26 40 34 8 22 Z" fill="url(#pouchGrad)" stroke="#9a3412" stroke-width="2.5" stroke-linejoin="round"/>
          </g>
          <!-- 帽子? 小头盔 -->
          <g transform="translate(452,122)">
            <path d="M-24 0 A 24 16 0 0 1 24 0 Z" fill="#ef4444" stroke="#7f1d1d" stroke-width="2.5"/>
            <rect x="-26" y="-2" width="52" height="7" rx="3.5" fill="#7f1d1d"/>
            <circle cx="0" cy="-18" r="4" fill="#fde047" stroke="#7f1d1d" stroke-width="2"/>
          </g>
        </g>
      </g>
    
      <!-- 尘土 -->
      <g fill="#d6c7a8">
        <circle class="dust" cx="270" cy="440" r="9"/>
        <circle class="dust d2" cx="270" cy="450" r="7"/>
        <circle class="dust d3" cx="270" cy="435" r="6"/>
      </g>
    </g>
    </svg>
    </div>
    
    <div class="panel">
      <div class="controls">
        <button id="btn-pause">⏸ 暂停</button>
        <button id="btn-night" class="secondary">🌙 夜晚模式</button>
        <button id="btn-ring" class="secondary">🔔 按铃铛</button>
        <label>🚴 速度 <input id="speed" type="range" min="0.2" max="2.5" step="0.1" value="1" /> <span id="speed-val">1.0x</span></label>
      </div>
      <div class="hint">小技巧:拖动速度滑杆,车轮 / 脚踏 / 背景会一起变速 · 腿部是 JS 实时 IK 跟随脚踏</div>
    </div>
    
    <script>
    const svg = document.getElementById('scene');
    const speedInput = document.getElementById('speed');
    const speedVal = document.getElementById('speed-val');
    const btnPause = document.getElementById('btn-pause');
    const btnNight = document.getElementById('btn-night');
    const btnRing = document.getElementById('btn-ring');
    
    let speed = 1, paused = false, crankAngle = 0;
    
    // 速度 -> CSS 变量
    function applySpeed(){
      document.documentElement.style.setProperty('--spin-dur', (1/speed)+'s');
      document.documentElement.style.setProperty('--bounce-dur', (0.5/speed)+'s');
      document.querySelectorAll('.bg-scroll').forEach(e=>e.style.animationDuration=(3.2/speed)+'s');
      document.querySelectorAll('.bg-scroll-fast').forEach(e=>e.style.animationDuration=(1.6/speed)+'s');
      document.getElementById('road-dashes').style.animationDuration=(0.5/speed)+'s';
      speedVal.textContent = speed.toFixed(1)+'x';
    }
    speedInput.addEventListener('input', e=>{ speed=parseFloat(e.target.value); applySpeed(); });
    applySpeed();
    
    btnPause.addEventListener('click', ()=>{
      paused=!paused;
      svg.classList.toggle('paused', paused);
      btnPause.textContent = paused ? '▶ 继续' : '⏸ 暂停';
    });
    btnNight.addEventListener('click', ()=>{
      const night = svg.classList.toggle('night');
      btnNight.textContent = night ? '☀️ 白天模式' : '🌙 夜晚模式';
    });
    btnRing.addEventListener('click', ()=>{
      // 铃铛:车把小黄点跳一下 + 响声(WebAudio)
      try{
        const ctx = new (window.AudioContext||window.webkitAudioContext)();
        [880,1174].forEach((f,i)=>{
          const o=ctx.createOscillator(), g=ctx.createGain();
          o.type='sine'; o.frequency.value=f;
          g.gain.setValueAtTime(0.25, ctx.currentTime+i*0.12);
          g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime+i*0.12+0.4);
          o.connect(g).connect(ctx.destination); o.start(ctx.currentTime+i*0.12); o.stop(ctx.currentTime+i*0.12+0.45);
        });
      }catch(e){}
      btnRing.textContent='🔔 叮铃铃~';
      setTimeout(()=>btnRing.textContent='🔔 按铃铛',900);
    });
    
    // ---- 腿部跟随脚踏 (每帧更新) ----
    const BB = {x:405, y:418};       // 五通中轴 (SVG坐标)
    const CR = 22;                    // 曲柄半径
    const hipNear = {x:385, y:280};   // 近侧髋
    const hipFar  = {x:368, y:282};   // 远侧髋
    const crank = document.getElementById('crank');
    const arm1 = document.getElementById('crank-arm1');
    const arm2 = document.getElementById('crank-arm2');
    const ped1 = document.getElementById('pedal1');
    const ped2 = document.getElementById('pedal2');
    const legNear = document.getElementById('leg-near');
    const legFar = document.getElementById('leg-far');
    
    function kneePos(hip, foot, bend){
      const mx=(hip.x+foot.x)/2, my=(hip.y+foot.y)/2;
      // 膝盖向前凸
      const dx=foot.x-hip.x, dy=foot.y-hip.y;
      const len=Math.hypot(dx,dy)||1;
      const nx=-dy/len, ny=dx/len;
      return {x:mx+nx*bend, y:my+ny*bend};
    }
    let last=performance.now();
    function tick(now){
      const dt=Math.min(0.05,(now-last)/1000); last=now;
      if(!paused){
        crankAngle += dt * Math.PI*2 * speed; // 1圈/秒 * speed
        const a1=crankAngle, a2=crankAngle+Math.PI;
        const f1={x:BB.x+Math.cos(a1)*CR, y:BB.y+Math.sin(a1)*CR};
        const f2={x:BB.x+Math.cos(a2)*CR, y:BB.y+Math.sin(a2)*CR};
        arm1.setAttribute('x2', (Math.cos(a1)*CR).toFixed(1));
        arm1.setAttribute('y2', (Math.sin(a1)*CR).toFixed(1));
        arm2.setAttribute('x2', (Math.cos(a2)*CR).toFixed(1));
        arm2.setAttribute('y2', (Math.sin(a2)*CR).toFixed(1));
        ped1.setAttribute('x', (Math.cos(a1)*CR-12).toFixed(1));
        ped1.setAttribute('y', (Math.sin(a1)*CR-5).toFixed(1));
        ped2.setAttribute('x', (Math.cos(a2)*CR-12).toFixed(1));
        ped2.setAttribute('y', (Math.sin(a2)*CR-5).toFixed(1));
        // 腿:髋 -> 膝 -> 脚
        const k1=kneePos(hipNear,f1,18), k2=kneePos(hipFar,f2,16);
        legNear.setAttribute('d', `M${hipNear.x} ${hipNear.y} L${k1.x.toFixed(1)} ${k1.y.toFixed(1)} L${f1.x.toFixed(1)} ${f1.y.toFixed(1)}`);
        legFar.setAttribute('d', `M${hipFar.x} ${hipFar.y} L${k2.x.toFixed(1)} ${k2.y.toFixed(1)} L${f2.x.toFixed(1)} ${f2.y.toFixed(1)}`);
        // 脚蹼
        // (用 pedal 本体 + 腿末端即脚,足够可爱)
      }
      requestAnimationFrame(tick);
    }
    requestAnimationFrame(tick);
    </script>
    </body>
    </html>
    ```提示词:
    
    `创建一个HTML,内容是SVG绘制一个鹈鹕骑自行车的2D动画`
    
    用的opencode里的免费的,思考强度xhigh
    
    ![图片](https://cdn3.ldstatic.com/optimized/4X/3/2/0/320c181a9342eae3be9fa3754dc46d45d42ecb4d_2_690x498.jpeg)
    主楼
  • heds

    怎么感觉一股gemini的味道呢

    #1
  • starless

    AA 61 分,就这水平?

    #2
  • xzcokw

    看起来感觉不错哦

    #3
  • MU

    opencode zen muse-spark-1.3-contributor-free 魔方:魔方纸上实验室 — RUBIK ATELIER

    #4
  • 第一个mt

    跑分没输过实测没赢过 ^-^

    #5
  • person

    还行吧,试了下糖果问题也能做对。至少是dsv4-0731,glm-5.3-flash这级别的,能用

    图片

    #6
  • sczerg

    好像很便宜,OPENROUTER有数据训练版,历史最低价,也是惊到我了。

    #7
  • kinda66

    讲道理,gemini的鹈鹕画的比他好看多了。

    #8

发表回复

登录后回复