• 紫米

    图片

    图片

    gif

    https://r2.535888.xyz/2026/08/xG08pjk.gif(图片大于 4 MB)

    这是我测的最好的```
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>鹈鹕骑自行车 - Pelican On A Bicycle</title>
    <style>
    :root {
    --sky-top: #70c5ff;
    --sky-bottom: #e0f2fe;
    --sun-color: #fde047;
    --road-color: #475569;
    --road-line: #f8fafc;
    --grass-color: #86efac;
    --grass-dark: #22c55e;
    --hill-1: #93c5fd;
    --hill-2: #60a5fa;
    --sea-color: #38bdf8;
    }

    body.sunset {
    --sky-top: #f97316;
    --sky-bottom: #fed7aa;
    --sun-color: #fb923c;
    --road-color: #334155;
    --road-line: #fef08a;
    --grass-color: #ca8a04;
    --grass-dark: #854d0e;
    --hill-1: #db2777;
    --hill-2: #9d174d;
    --sea-color: #ea580c;
    }

    body.night {
    --sky-top: #0f172a;
    --sky-bottom: #1e1b4b;
    --sun-color: #fef08a;
    --road-color: #1e293b;
    --road-line: #94a3b8;
    --grass-color: #15803d;
    --grass-dark: #14532d;
    --hill-1: #312e81;
    --hill-2: #1e1b4b;
    --sea-color: #1e3a8a;
    }

    • {

    margin: 0;
    padding: 0;
    box-sizing: border-box;
    user-select: none;
    }

    body {
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: linear-gradient(180deg, var(--sky-top) 0%, var(--sky-bottom) 100%);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
    transition: background 1s ease;
    }

    #scene-container {
    position: relative;
    width: 100%;
    max-width: 1200px;
    height: 700px;
    max-height: 90vh;
    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
    border-radius: 20px;
    overflow: hidden;
    background: linear-gradient(180deg, var(--sky-top) 0%, var(--sky-bottom) 65%, var(--sea-color) 70%, var(--grass-dark) 78%, var(--road-color) 78%);
    border: 4px solid rgba(255, 255, 255, 0.3);
    }

    svg {
    width: 100%;
    height: 100%;
    display: block;
    }

    / UI Controls Overlay /
    .controls {
    position: absolute;
    top: 20px;
    right: 20px;
    display: flex;
    gap: 10px;
    z-index: 50;
    }

    .btn {
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.6);
    padding: 8px 16px;
    border-radius: 24px;
    font-size: 14px;
    font-weight: 600;
    color: #1e293b;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    }

    .btn:hover {
    background: rgba(255, 255, 255, 1);
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
    }

    .btn:active {
    transform: translateY(0);
    }

    .title-tag {
    position: absolute;
    top: 20px;
    left: 24px;
    z-index: 50;
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.6);
    padding: 8px 18px;
    border-radius: 24px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    }

    .title-tag h1 {
    font-size: 16px;
    font-weight: 700;
    color: #0f172a;
    letter-spacing: 0.5px;
    }

    .title-tag p {
    font-size: 11px;
    color: #64748b;
    margin-top: 1px;
    }

    / Speed indicator /
    .speed-gauge {
    position: absolute;
    bottom: 24px;
    right: 24px;
    background: rgba(15, 23, 42, 0.75);
    backdrop-filter: blur(8px);
    padding: 10px 18px;
    border-radius: 16px;
    color: #fff;
    display: flex;
    align-items: baseline;
    gap: 6px;
    z-index: 50;
    border: 1px solid rgba(255, 255, 255, 0.15);
    }
    .speed-gauge .val {
    font-size: 24px;
    font-weight: 800;
    color: #38bdf8;
    font-family: monospace;
    }
    .speed-gauge .unit {
    font-size: 12px;
    color: #94a3b8;
    }

    / Bell ripple animation on click /
    .bell-sound-wave {
    pointer-events: none;
    animation: sound-ping 0.8s ease-out forwards;
    transform-origin: center;
    }

    @keyframes sound-ping {
    0% { r: 10px; opacity: 0.9; stroke-width: 4px; }
    100% { r: 70px; opacity: 0; stroke-width: 1px; }
    }

    / Scarf wave animation /
    @keyframes scarf-flutter {
    0%, 100% { transform: rotate(0deg) skewY(0deg); }
    50% { transform: rotate(-5deg) skewY(-8deg); }
    }

    / Fish wiggle /
    @keyframes fish-wiggle {
    0%, 100% { transform: rotate(-4deg); }
    50% { transform: rotate(6deg); }
    }
    </style>
    </head>
    <body>
    <div id="scene-container">
    <div class="title-tag">
    <h1>🚴‍♂️ 快乐的骑行鹈鹕 (Pelican Ride)</h1>
    <p>按键盘 空格 或 点击加速 / 响铃</p>
    </div>

    <div class="controls">
    <button class="btn" id="btn-bell" title="按铃铛">🔔 叮叮叮</button>
    <button class="btn" id="btn-speed" title="加速/巡航">⚡ 加速</button>
    <button class="btn" id="btn-theme" title="切换时段">🌅 切换天空</button>
    </div>

    <div class="speed-gauge">
    <span class="val" id="speed-val">28</span>
    <span class="unit">km/h</span>
    </div>

    <svg id="bike-world" viewBox="0 0 1200 700" preserveAspectRatio="xMidYMid slice">
    <defs>
    <!-- Gradients -->
    <linearGradient id="sun-grad" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0%" stop-color="#fff" stop-opacity="0.9" />
    <stop offset="100%" stop-color="var(--sun-color)" />
    </linearGradient>

    <linearGradient id="sea-grad" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0%" stop-color="var(--sea-color)" stop-opacity="0.8" />
    <stop offset="100%" stop-color="#0284c7" />
    </linearGradient>

    <linearGradient id="pouch-grad" x1="0" y1="0" x2="1" y2="1">
    <stop offset="0%" stop-color="#fdba74" />
    <stop offset="60%" stop-color="#fb923c" />
    <stop offset="100%" stop-color="#ea580c" />
    </linearGradient>

    <linearGradient id="feather-grad" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0%" stop-color="#ffffff" />
    <stop offset="85%" stop-color="#f1f5f9" />
    <stop offset="100%" stop-color="#cbd5e1" />
    </linearGradient>

    <linearGradient id="frame-grad" x1="0" y1="0" x2="1" y2="1">
    <stop offset="0%" stop-color="#06b6d4" />
    <stop offset="100%" stop-color="#0e7490" />
    </linearGradient>

    <linearGradient id="metallic" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0%" stop-color="#f8fafc" />
    <stop offset="50%" stop-color="#94a3b8" />
    <stop offset="100%" stop-color="#64748b" />
    </linearGradient>

    <filter id="shadow" x="-10%" y="-10%" width="130%" height="130%">
    <feDropShadow dx="0" dy="4" stdDeviation="3" flood-opacity="0.2" />
    </filter>

    <filter id="bike-ground-shadow" x="-20%" y="-20%" width="140%" height="140%">
    <feGaussianBlur in="SourceGraphic" stdDeviation="6" />
    </filter>
    </defs>

    <!-- Celestial Body (Sun/Moon) -->
    <g id="celestial-group">
    <circle id="sun" cx="950" cy="140" r="48" fill="url(#sun-grad)" opacity="0.9" />
    <circle id="sun-glow" cx="950" cy="140" r="75" fill="var(--sun-color)" opacity="0.25" />
    </g>

    <!-- Parallax Layer 1: Distant Islands & Mountains -->
    <g id="mountains-far"></g>

    <!-- Parallax Layer 2: Sea / Lake Waves -->
    <rect x="0" y="470" width="1200" height="70" fill="url(#sea-grad)" />
    <g id="sea-ripples"></g>

    <!-- Parallax Layer 3: Hills & Vegetation -->
    <g id="hills-mid"></g>

    <!-- Clouds -->
    <g id="clouds-layer"></g>

    <!-- Road & Ground -->
    <g id="road-layer">
    <!-- Grass strip -->
    <rect x="0" y="520" width="1200" height="25" fill="var(--grass-dark)" />
    <rect x="0" y="522" width="1200" height="12" fill="var(--grass-color)" opacity="0.6" />
    <!-- Road Asphalt -->
    <rect x="0" y="545" width="1200" height="155" fill="var(--road-color)" />
    <rect x="0" y="545" width="1200" height="8" fill="#334155" opacity="0.5" />
    <!-- Moving Road Markings -->
    <g id="road-lines"></g>
    <!-- Moving roadside flowers/grass posts -->
    <g id="roadside-details"></g>
    </g>

    <!-- Speed Wind Particles -->
    <g id="wind-particles"></g>

    <!-- ================= MAIN CHARACTER & BIKE (Pelican on Bicycle) ================= -->
    <!-- Positioned around center: X: 520, Ground Level: Y: 575 -->
    <g id="pelican-cyclist" transform="translate(480, 260)">

    <!-- Ground Contact Shadow -->
    <ellipse id="ground-shadow" cx="120" cy="315" rx="140" ry="14" fill="#0f172a" opacity="0.4" filter="url(#bike-ground-shadow)" />

    <!-- BIKE REAR WHEEL -->
    <!-- Center at X: 0, Y: 250, Radius: 60 -->
    <g id="rear-wheel" transform="translate(0, 250)">
    <!-- Tire -->
    <circle cx="0" cy="0" r="60" fill="none" stroke="#1e293b" stroke-width="12" />
    <circle cx="0" cy="0" r="56" fill="none" stroke="#f1f5f9" stroke-width="3" />
    <circle cx="0" cy="0" r="53" fill="#0f172a" opacity="0.05" />
    <!-- Spokes (will be rotated via JS) -->
    <g id="rear-spokes">
    <line x1="-54" y1="0" x2="54" y2="0" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="0" y1="-54" x2="0" y2="54" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-38" y1="-38" x2="38" y2="38" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-38" y1="38" x2="38" y2="-38" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-50" y1="-20" x2="50" y2="20" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-20" y1="-50" x2="20" y2="50" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-50" y1="20" x2="50" y2="-20" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-20" y1="50" x2="20" y2="-50" stroke="#cbd5e1" stroke-width="1.5" />
    </g>
    <!-- Hub -->
    <circle cx="0" cy="0" r="8" fill="url(#metallic)" stroke="#475569" stroke-width="1.5" />
    </g>

    <!-- BIKE FRONT WHEEL -->
    <!-- Center at X: 240, Y: 250, Radius: 60 -->
    <g id="front-wheel" transform="translate(240, 250)">
    <!-- Tire -->
    <circle cx="0" cy="0" r="60" fill="none" stroke="#1e293b" stroke-width="12" />
    <circle cx="0" cy="0" r="56" fill="none" stroke="#f1f5f9" stroke-width="3" />
    <circle cx="0" cy="0" r="53" fill="#0f172a" opacity="0.05" />
    <!-- Spokes -->
    <g id="front-spokes">
    <line x1="-54" y1="0" x2="54" y2="0" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="0" y1="-54" x2="0" y2="54" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-38" y1="-38" x2="38" y2="38" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-38" y1="38" x2="38" y2="-38" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-50" y1="-20" x2="50" y2="20" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-20" y1="-50" x2="20" y2="50" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-50" y1="20" x2="50" y2="-20" stroke="#cbd5e1" stroke-width="1.5" />
    <line x1="-20" y1="50" x2="20" y2="-50" stroke="#cbd5e1" stroke-width="1.5" />
    </g>
    <!-- Hub -->
    <circle cx="0" cy="0" r="8" fill="url(#metallic)" stroke="#475569" stroke-width="1.5" />
    </g>

    <!-- BACK LEG & PEDAL (Behind Bike Frame) -->
    <g id="back-leg-group">
    <!-- Back pedal arm & pedal (drawn via JS IK) -->
    <line id="back-crank" x1="110" y1="250" x2="90" y2="225" stroke="#64748b" stroke-width="5" stroke-linecap="round" />
    <rect id="back-pedal-rect" x="80" y="220" width="20" height="8" rx="3" fill="#334155" />
    <!-- Back leg bones -->
    <path id="back-pelican-leg" d="M 85 140 Q 70 190 90 225" fill="none" stroke="#ea580c" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" opacity="0.65" />
    <!-- Back Webbed foot -->
    <path id="back-pelican-foot" d="M 80 220 L 105 220 L 98 226 L 82 226 Z" fill="#c2410c" opacity="0.65" />
    </g>

    <!-- BIKE FRAME (Charming Vintage Turquoise Cruiser) -->
    <g id="bike-frame" filter="url(#shadow)">
    <!-- Mudguards -->
    <path d="M -45 210 A 62 62 0 0 1 35 198" fill="none" stroke="#0891b2" stroke-width="7" stroke-linecap="round" />
    <path d="M 195 198 A 62 62 0 0 1 275 210" fill="none" stroke="#0891b2" stroke-width="7" stroke-linecap="round" />

    <!-- Rear stays -->
    <line x1="0" y1="250" x2="70" y2="160" stroke="url(#frame-grad)" stroke-width="8" stroke-linecap="round" />
    <line x1="0" y1="250" x2="110" y2="250" stroke="url(#frame-grad)" stroke-width="8" stroke-linecap="round" />

    <!-- Seat tube -->
    <line x1="70" y1="160" x2="110" y2="250" stroke="url(#frame-grad)" stroke-width="9" stroke-linecap="round" />
    <line x1="70" y1="160" x2="62" y2="135" stroke="url(#metallic)" stroke-width="7" stroke-linecap="round" />
    <!-- Saddle -->
    <path d="M 45 133 C 55 130, 85 130, 92 138 C 88 143, 60 142, 45 133 Z" fill="#78350f" stroke="#451a03" stroke-width="1.5" />
    <circle cx="53" cy="138" r="3" fill="#d97706" />

    <!-- Down tube and Top curved tube (Cruiser Style) -->
    <line x1="110" y1="250" x2="205" y2="145" stroke="url(#frame-grad)" stroke-width="9" stroke-linecap="round" />
    <path d="M 70 165 C 120 185, 170 155, 205 145" fill="none" stroke="url(#frame-grad)" stroke-width="8" stroke-linecap="round" />

    <!-- Head tube & Fork -->
    <line x1="205" y1="145" x2="240" y2="250" stroke="url(#frame-grad)" stroke-width="8" stroke-linecap="round" />
    <line x1="205" y1="145" x2="198" y2="115" stroke="url(#metallic)" stroke-width="7" stroke-linecap="round" />

    <!-- Handlebars (Cruiser swept back) -->
    <path d="M 198 115 Q 185 100, 160 108" fill="none" stroke="url(#metallic)" stroke-width="6" stroke-linecap="round" />
    <!-- Hand Grips -->
    <rect x="155" y="103" width="14" height="10" rx="3" fill="#78350f" transform="rotate(15 155 103)" />

    <!-- Front Bike Basket with a Fish! -->
    <g id="bike-basket" transform="translate(195, 115)">
    <rect x="0" y="0" width="38" height="28" rx="4" fill="#d97706" stroke="#92400e" stroke-width="1.5" />
    <!-- Basket weave lines -->
    <line x1="8" y1="0" x2="8" y2="28" stroke="#92400e" stroke-width="1" />
    <line x1="18" y1="0" x2="18" y2="28" stroke="#92400e" stroke-width="1" />
    <line x1="28" y1="0" x2="28" y2="28" stroke="#92400e" stroke-width="1" />
    <line x1="0" y1="10" x2="38" y2="10" stroke="#92400e" stroke-width="1" />
    <line x1="0" y1="20" x2="38" y2="20" stroke="#92400e" stroke-width="1" />

    <!-- Little happy fish in the basket -->
    <g id="basket-fish" transform="translate(18, -2)" style="animation: fish-wiggle 1.2s ease-in-out infinite;">
    <path d="M 0 0 C 8 -10, 18 -6, 16 6 C 14 14, 2 12, 0 0 Z" fill="#38bdf8" stroke="#0284c7" stroke-width="1" />
    <circle cx="10" cy="-1" r="2.5" fill="#fff" />
    <circle cx="11" cy="-1" r="1.2" fill="#0f172a" />
    <path d="M 16 6 L 24 2 L 22 10 Z" fill="#0284c7" />
    </g>
    </g>

    <!-- Bicycle Bell -->
    <g id="bike-bell-group" transform="translate(182, 104)" style="cursor: pointer;">
    <circle cx="0" cy="0" r="7" fill="#fbbf24" stroke="#d97706" stroke-width="1.5" />
    <circle cx="-2" cy="-2" r="2" fill="#fef08a" />
    <circle id="bell-wave" cx="0" cy="0" r="0" fill="none" stroke="#f59e0b" opacity="0" />
    </g>

    <!-- Chainwheel / Crankset -->
    <circle cx="110" cy="250" r="16" fill="url(#metallic)" stroke="#475569" stroke-width="2" />
    <circle cx="110" cy="250" r="8" fill="#1e293b" />
    <!-- Bike Chain -->
    <path d="M 0 250 L 110 236 A 16 16 0 0 1 110 264 L 0 250" fill="none" stroke="#475569" stroke-width="3" stroke-dasharray="3,2" />
    </g>

    <!-- PELICAN BODY & HEAD GROUP (Bobbing dynamically with pedal) -->
    <g id="pelican-body-group">

    <!-- Tail Feathers -->
    <path id="pelican-tail" d="M 40 135 C 10 130, -5 145, 8 160 C 25 155, 45 150, 50 145 Z" fill="#94a3b8" />

    <!-- Pelican Torso / Body -->
    <path id="pelican-torso" d="M 50 120 C 40 150, 60 190, 95 185 C 125 180, 140 145, 125 110 C 115 85, 80 80, 65 100 C 55 108, 52 114, 50 120 Z" fill="url(#feather-grad)" stroke="#cbd5e1" stroke-width="1.5" filter="url(#shadow)" />

    <!-- Pelican Neck & Head -->
    <g id="pelican-head-neck">
    <!-- Curved graceful S-shaped Neck -->
    <path d="M 115 115 C 130 90, 145 60, 135 30 C 130 15, 115 20, 120 40 C 122 55, 110 85, 95 105 Z" fill="url(#feather-grad)" stroke="#cbd5e1" stroke-width="1" />

    <!-- Head Base -->
    <circle cx="138" cy="24" r="16" fill="#ffffff" stroke="#e2e8f0" stroke-width="1" />

    <!-- Head Tuft / Feathers on top -->
    <path d="M 125 15 Q 115 8, 120 0 Q 130 10, 132 12" fill="#94a3b8" />
    <path d="M 128 12 Q 120 3, 128 -4 Q 134 6, 136 10" fill="#cbd5e1" />

    <!-- Huge Pelican Pouch (Gular Pouch) & Upper Bill -->
    <!-- Giant expressive beak with throat pouch! -->
    <g id="pelican-beak" filter="url(#shadow)">
    <!-- Throat Pouch (Big stretchy sac) -->
    <path id="throat-pouch" d="M 148 28 C 170 38, 205 60, 215 35 C 220 25, 175 25, 150 25 Z" fill="url(#pouch-grad)" stroke="#ea580c" stroke-width="1.5" />
    <!-- Pouch muscle texture lines -->
    <path d="M 160 30 Q 185 50, 205 32" fill="none" stroke="#f97316" stroke-width="1.2" opacity="0.6" />
    <path d="M 170 30 Q 190 44, 200 30" fill="none" stroke="#f97316" stroke-width="1" opacity="0.6" />

    <!-- Little Fish poking out of pouch (wiggling tail) -->
    <g id="pouch-fish" transform="translate(195, 20) rotate(-15)">
    <path d="M 0 0 C 6 -4, 14 -2, 18 4 C 14 8, 4 6, 0 0 Z" fill="#22d3ee" stroke="#0891b2" stroke-width="1" />
    <path d="M 18 4 L 25 0 L 23 8 Z" fill="#0891b2" />
    </g>

    <!-- Upper Long Hooked Bill -->
    <path d="M 138 16 L 225 18 C 228 18, 232 20, 230 25 C 228 27, 222 24, 218 22 L 142 24 Z" fill="#f59e0b" stroke="#d97706" stroke-width="1.5" />
    <!-- Beak hook tip -->
    <path d="M 225 18 Q 232 21, 228 26 Q 224 23, 220 22 Z" fill="#dc2626" />
    </g>

    <!-- Expressive Eye & Cheek -->
    <circle cx="140" cy="20" r="5.5" fill="#fef08a" stroke="#f59e0b" stroke-width="1" />
    <circle id="eye-pupil" cx="142" cy="19" r="2.8" fill="#0f172a" />
    <circle cx="143" cy="18" r="1" fill="#ffffff" />
    <!-- Eye lid (blinking) -->
    <ellipse id="eye-lid" cx="140" cy="20" rx="5.5" ry="0" fill="#f8fafc" stroke="#e2e8f0" stroke-width="0.5" />

    <!-- Cute Cycling Cap / Visor -->
    <g id="cycling-cap">
    <path d="M 125 15 C 128 6, 145 6, 150 14 Z" fill="#ef4444" />
    <path d="M 142 12 Q 165 8, 172 13 Q 155 16, 142 15 Z" fill="#ffffff" stroke="#e2e8f0" stroke-width="0.5" />
    <circle cx="137" cy="8" r="2" fill="#ffffff" />
    </g>

    <!-- Snazzy Wind Scarf (Fluttering behind) -->
    <g id="scarf-group" transform="translate(112, 55)">
    <path d="M 0 0 C 10 5, 20 0, 25 -5 L 20 12 C 10 15, 0 10, 0 0 Z" fill="#f43f5e" />
    <!-- Scarf trailing tails animated with CSS/JS -->
    <g id="scarf-tail" style="transform-origin: 0 0; animation: scarf-flutter 0.6s ease-in-out infinite alternate;">
    <path d="M 0 5 C -20 0, -45 -10, -65 0 C -45 10, -20 15, 0 12 Z" fill="#f43f5e" />
    <path d="M -10 6 C -25 2, -40 -4, -55 2 C -40 8, -20 12, -10 10 Z" fill="#fb7185" />
    <!-- Scarf fringes -->
    <line x1="-65" y1="0" x2="-72" y2="-2" stroke="#fda4af" stroke-width="2" />
    <line x1="-65" y1="5" x2="-73" y2="4" stroke="#fda4af" stroke-width="2" />
    </g>
    </g>

    </g>

    <!-- Pelican Wing (Arm holding handlebar) -->
    <g id="pelican-wing">
    <!-- Main wing folded on body with wing tip extending to handlebar -->
    <path d="M 65 110 C 60 140, 95 165, 120 135 C 130 120, 125 100, 100 100 C 80 100, 70 105, 65 110 Z" fill="#e2e8f0" stroke="#cbd5e1" stroke-width="1.5" />
    <!-- Wing feather lines -->
    <path d="M 75 125 C 85 145, 110 148, 122 132" fill="none" stroke="#94a3b8" stroke-width="1.2" stroke-dasharray="2,2" />
    <path d="M 85 115 C 95 135, 115 136, 125 122" fill="none" stroke="#94a3b8" stroke-width="1.2" stroke-dasharray="2,2" />

    <!-- Wing Arm grasping Handlebar -->
    <path id="wing-arm" d="M 105 115 Q 135 120, 160 108" fill="none" stroke="#f1f5f9" stroke-width="10" stroke-linecap="round" />
    <path d="M 105 115 Q 135 120, 160 108" fill="none" stroke="#cbd5e1" stroke-width="2" stroke-linecap="round" />
    <!-- Feather fingers gripping handlebar -->
    <ellipse cx="160" cy="108" rx="6" ry="4" fill="#e2e8f0" stroke="#cbd5e1" stroke-width="1" transform="rotate(-15 160 108)" />
    </g>

    </g>

    <!-- FRONT LEG & PEDAL (In Foreground, connected to Crank) -->
    <g id="front-leg-group">
    <!-- Front Crank Arm & Pedal (Position calculated dynamically by JS) -->
    <line id="front-crank" x1="110" y1="250" x2="130" y2="275" stroke="#475569" stroke-width="6" stroke-linecap="round" />
    <circle cx="110" cy="250" r="5" fill="#f8fafc" />
    <rect id="front-pedal-rect" x="120" y="270" width="22" height="9" rx="3" fill="#1e293b" stroke="#94a3b8" stroke-width="1" />

    <!-- Front Leg & Big Webbed Foot -->
    <!-- Pelican Thigh & Shin with IK / Joint curve -->
    <path id="front-pelican-leg" d="M 95 150 Q 115 210, 130 275" fill="none" stroke="#f97316" stroke-width="8" stroke-linecap="round" stroke-linejoin="round" />

    <!-- Big Orange Webbed Foot -->
    <g id="front-pelican-foot" transform="translate(130, 275)">
    <!-- Webbing -->
    <path d="M -12 -3 L 18 -3 L 12 7 L -8 7 Z" fill="#ea580c" stroke="#c2410c" stroke-width="1" />
    <!-- Claws / Toes -->
    <line x1="-10" y1="5" x2="-8" y2="8" stroke="#7c2d12" stroke-width="2" stroke-linecap="round" />
    <line x1="2" y1="5" x2="4" y2="9" stroke="#7c2d12" stroke-width="2" stroke-linecap="round" />
    <line x1="14" y1="5" x2="16" y2="8" stroke="#7c2d12" stroke-width="2" stroke-linecap="round" />
    </g>
    </g>

    </g>
    </svg>
    </div>

    <script>
    // ================= DYNAMIC ANIMATION & INTERACTION ENGINE =================

    // State
    let speed = 28; // km/h
    let targetSpeed = 28;
    let crankAngle = 0; // In radians
    let wheelAngle = 0; // In degrees
    let timeThemeIndex = 0; // 0: day, 1: sunset, 2: night
    const themes = ['', 'sunset', 'night'];

    // DOM Elements
    const rearSpokes = document.getElementById('rear-spokes');
    const frontSpokes = document.getElementById('front-spokes');
    const frontCrank = document.getElementById('front-crank');
    const backCrank = document.getElementById('back-crank');
    const frontPedalRect = document.getElementById('front-pedal-rect');
    const backPedalRect = document.getElementById('back-pedal-rect');
    const frontPelicanLeg = document.getElementById('front-pelican-leg');
    const backPelicanLeg = document.getElementById('back-pelican-leg');
    const frontPelicanFoot = document.getElementById('front-pelican-foot');
    const backPelicanFoot = document.getElementById('back-pelican-foot');
    const pelicanBodyGroup = document.getElementById('pelican-body-group');
    const throatPouch = document.getElementById('throat-pouch');
    const eyeLid = document.getElementById('eye-lid');
    const speedVal = document.getElementById('speed-val');
    const btnSpeed = document.getElementById('btn-speed');
    const btnBell = document.getElementById('btn-bell');
    const btnTheme = document.getElementById('btn-theme');
    const bikeBellGroup = document.getElementById('bike-bell-group');

    // Scenery container elements
    const mountainsFar = document.getElementById('mountains-far');
    const seaRipples = document.getElementById('sea-ripples');
    const hillsMid = document.getElementById('hills-mid');
    const cloudsLayer = document.getElementById('clouds-layer');
    const roadLines = document.getElementById('road-lines');
    const roadsideDetails = document.getElementById('roadside-details');
    const windParticles = document.getElementById('wind-particles');

    // Create Parallax Assets
    function initParallaxWorld() {
    // 1. Far Mountains
    let mountainSvg = '';
    for (let i = 0; i < 4; i++) {
    const x = i * 400;
    mountainSvg += <polygon points="${x-50},480 ${x+160},280 ${x+380},480" fill="var(--hill-1)" opacity="0.6"/>;
    mountainSvg += <polygon points="${x+120},480 ${x+280},320 ${x+450},480" fill="var(--hill-2)" opacity="0.5"/>;
    }
    mountainsFar.innerHTML = mountainSvg;

    // 2. Mid Hills with trees
    let hillSvg = '';
    for (let i = 0; i < 6; i++) {
    const x = i * 260;
    hillSvg += <path d="M ${x-40} 490 Q ${x+100} 410 ${x+240} 490 Z" fill="var(--grass-dark)" opacity="0.75"/>;
    // Tree
    hillSvg += <circle cx="${x+80}" cy="425" r="18" fill="#15803d" opacity="0.9"/>;
    hillSvg += <circle cx="${x+95}" cy="420" r="14" fill="#22c55e" opacity="0.8"/>;
    }
    hillsMid.innerHTML = hillSvg;

    // 3. Clouds
    let cloudSvg = '';
    const cloudData = [
    { x: 100, y: 70, s: 1 },
    { x: 450, y: 110, s: 0.75 },
    { x: 800, y: 60, s: 1.2 },
    { x: 1150, y: 95, s: 0.85 }
    ];
    cloudData.forEach(c => {
    cloudSvg += `
    <g class="cloud-item" data-speed="0.3" transform="translate(${c.x}, ${c.y}) scale(${c.s})">
    <path d="M 0 20 C -10 20 -20 10 -15 0 C -10 -12 10 -15 20 -5 C 28 -20 52 -18 58 -2 C 70 -5 80 8 75 20 Z" fill="#ffffff" opacity="0.85" />
    </g>
    `;
    });
    cloudsLayer.innerHTML = cloudSvg;

    // 4. Road dashed lines
    let linesSvg = '';
    for (let i = 0; i < 15; i++) {
    linesSvg += <rect class="road-dash" x="${i * 100}" y="615" width="55" height="8" rx="4" fill="var(--road-line)" opacity="0.85"/>;
    }
    roadLines.innerHTML = linesSvg;

    // 5. Roadside bushes and flowers
    let detailsSvg = '';
    for (let i = 0; i < 10; i++) {
    const x = i * 140;
    detailsSvg += `
    <g class="road-item" data-x="${x}">
    <circle cx="${x}" cy="535" r="10" fill="#4ade80" />
    <circle cx="${x+12}" cy="532" r="8" fill="#22c55e" />
    <circle cx="${x+6}" cy="528" r="4" fill="#f43f5e" />
    </g>
    `;
    }
    roadsideDetails.innerHTML = detailsSvg;

    // 6. Wind particles
    let windSvg = '';
    for (let i = 0; i < 8; i++) {
    windSvg += <line class="wind-line" x1="0" y1="0" x2="50" y2="0" stroke="#ffffff" stroke-width="2" stroke-linecap="round" opacity="0.4"/>;
    }
    windParticles.innerHTML = windSvg;
    }

    initParallaxWorld();

    // Wind particles animation state
    const winds = Array.from({ length: 8 }, () => ({
    x: Math.random() * 1200,
    y: 100 + Math.random() * 450,
    len: 30 + Math.random() * 60,
    speed: 1.5 + Math.random() * 1.5
    }));

    // Audio synthesizer for Bicycle Bell chime (Web Audio API)
    let audioCtx = null;
    function playBellSound() {
    try {
    if (!audioCtx) {
    audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    }
    if (audioCtx.state === 'suspended') {
    audioCtx.resume();
    }

    const now = audioCtx.currentTime;
    const freqs = [2093, 2500, 3135]; // High crisp bell tones

    freqs.forEach((freq, idx) => {
    const osc = audioCtx.createOscillator();
    const gain = audioCtx.createGain();
    osc.type = 'sine';
    osc.frequency.setValueAtTime(freq, now + idx * 0.08);

    gain.gain.setValueAtTime(0.25, now + idx * 0.08);
    gain.gain.exponentialRampToValueAtTime(0.001, now + idx * 0.08 + 0.6);

    osc.connect(gain);
    gain.connect(audioCtx.destination);

    osc.start(now + idx * 0.08);
    osc.stop(now + idx * 0.08 + 0.65);
    });

    // Trigger visual ripple
    triggerBellVisual();
    } catch (e) {
    triggerBellVisual();
    }
    }

    function triggerBellVisual() {
    const bellGroup = document.getElementById('pelican-cyclist');
    const wave = document.createElementNS('http://www.w3.org/2000/svg&#039;, 'circle');
    wave.setAttribute('cx', '182');
    wave.setAttribute('cy', '104');
    wave.setAttribute('class', 'bell-sound-wave');
    wave.setAttribute('fill', 'none');
    wave.setAttribute('stroke', '#fbbf24');
    bellGroup.appendChild(wave);
    setTimeout(() => wave.remove(), 800);
    }

    // Inverse Kinematics / Trigonometric Leg solver for Pelican
    // Hip: (95, 140), Crank Center: (110, 250), Crank Radius: 30
    function updatePelicanLegs(angle, bodyBobY) {
    const hipX = 95;
    const hipY = 145 + bodyBobY;
    const crankCenter = { x: 110, y: 250 };
    const crankLength = 28;

    // --- Front Leg & Pedal ---
    const frontPedalX = crankCenter.x + Math.cos(angle) * crankLength;
    const frontPedalY = crankCenter.y + Math.sin(angle) * crankLength;

    frontCrank.setAttribute('x1', crankCenter.x);
    frontCrank.setAttribute('y1', crankCenter.y);
    frontCrank.setAttribute('x2', frontPedalX);
    frontCrank.setAttribute('y2', frontPedalY);

    frontPedalRect.setAttribute('x', frontPedalX - 11);
    frontPedalRect.setAttribute('y', frontPedalY - 4);

    // Knee bending position (midway with forward knee curve)
    const frontKneeX = (hipX + frontPedalX) / 2 + 25 + Math.sin(angle) * 10;
    const frontKneeY = (hipY + frontPedalY) / 2 - 10;

    frontPelicanLeg.setAttribute('d', M ${hipX} ${hipY} Q ${frontKneeX} ${frontKneeY} ${frontPedalX} ${frontPedalY});
    frontPelicanFoot.setAttribute('transform', translate(${frontPedalX}, ${frontPedalY}) rotate(${Math.sin(angle) * 15}));

    // --- Back Leg & Pedal (180 deg / PI out of phase) ---
    const backAngle = angle + Math.PI;
    const backPedalX = crankCenter.x + Math.cos(backAngle) * crankLength;
    const backPedalY = crankCenter.y + Math.sin(backAngle) * crankLength;

    backCrank.setAttribute('x1', crankCenter.x);
    backCrank.setAttribute('y1', crankCenter.y);
    backCrank.setAttribute('x2', backPedalX);
    backCrank.setAttribute('y2', backPedalY);

    backPedalRect.setAttribute('x', backPedalX - 10);
    backPedalRect.setAttribute('y', backPedalY - 4);

    const backKneeX = (hipX - 10 + backPedalX) / 2 + 18 + Math.sin(backAngle) * 10;
    const backKneeY = (hipY + backPedalY) / 2 - 12;

    backPelicanLeg.setAttribute('d', M ${hipX - 10} ${hipY} Q ${backKneeX} ${backKneeY} ${backPedalX} ${backPedalY});
    backPelicanFoot.setAttribute('transform', translate(${backPedalX - 90}, ${backPedalY - 225}));
    }

    // Blinking eye simulation
    let blinkTimer = 0;
    function updateEyeBlink(deltaTime) {
    blinkTimer += deltaTime;
    if (blinkTimer > 3.5) {
    eyeLid.setAttribute('ry', '5.5');
    if (blinkTimer > 3.65) {
    eyeLid.setAttribute('ry', '0');
    blinkTimer = 0;
    }
    }
    }

    // Parallax positions
    let mountainOffset = 0;
    let hillOffset = 0;
    let roadOffset = 0;
    let cloudOffset = 0;

    // Main Animation Loop
    let lastTime = performance.now();

    function animate(currentTime) {
    const deltaMs = currentTime - lastTime;
    const dt = Math.min(deltaMs / 1000, 0.1);
    lastTime = currentTime;

    // Smooth speed easing
    speed += (targetSpeed - speed) * 0.05;
    speedVal.textContent = Math.round(speed);

    const speedFactor = speed / 28;

    // 1. Rotate Wheels & Spokes
    wheelAngle = (wheelAngle + speedFactor 420 dt) % 360;
    rearSpokes.setAttribute('transform', rotate(${wheelAngle}));
    frontSpokes.setAttribute('transform', rotate(${wheelAngle}));

    // 2. Pedaling cadence (Crank rotation)
    crankAngle = (crankAngle + speedFactor 4.5 dt) % (Math.PI * 2);

    // 3. Pelican Body Bobbing (Rhythmic bounce matching pedaling effort)
    const bodyBobY = Math.sin(crankAngle 2) 3.5;
    const bodyRot = Math.cos(crankAngle) * 1.5;
    pelicanBodyGroup.setAttribute('transform', translate(0, ${bodyBobY}) rotate(${bodyRot} 110 160));

    // 4. Throat pouch slight wobbling
    const pouchStretch = Math.sin(crankAngle 2 + 1) 2;
    throatPouch.setAttribute('d', M 148 28 C 170 ${38 + pouchStretch}, 205 ${60 + pouchStretch * 1.5}, 215 35 C 220 25, 175 25, 150 25 Z);

    // 5. Update Legs to stay locked to Pedals
    updatePelicanLegs(crankAngle, bodyBobY);

    // 6. Blinking eyes
    updateEyeBlink(dt);

    // 7. Parallax Scrolling of scenery
    // Far mountains
    mountainOffset = (mountainOffset - speedFactor 30 dt) % 400;
    mountainsFar.setAttribute('transform', translate(${mountainOffset}, 0));

    // Mid hills
    hillOffset = (hillOffset - speedFactor 90 dt) % 260;
    hillsMid.setAttribute('transform', translate(${hillOffset}, 0));

    // Road dash lines
    roadOffset = (roadOffset - speedFactor 400 dt) % 100;
    roadLines.setAttribute('transform', translate(${roadOffset}, 0));

    // Roadside bushes
    const roadsideItems = roadsideDetails.querySelectorAll('.road-item');
    roadsideItems.forEach(item => {
    let curX = parseFloat(item.getAttribute('data-x'));
    curX -= speedFactor 350 dt;
    if (curX < -60) curX += 1400;
    item.setAttribute('data-x', curX);
    item.setAttribute('transform', translate(${curX - parseFloat(item.querySelector('circle').getAttribute('cx'))}, 0));
    });

    // Clouds
    const cloudElems = cloudsLayer.querySelectorAll('.cloud-item');
    cloudElems.forEach((cloud, idx) => {
    let x = (idx 320 - currentTime 0.02 * (idx + 1)) % 1400;
    if (x < -150) x += 1400;
    cloud.setAttribute('transform', translate(${x}, ${60 + idx * 25}) scale(${0.8 + idx * 0.15}));
    });

    // 8. Wind Particles
    const windLines = windParticles.querySelectorAll('.wind-line');
    winds.forEach((w, i) => {
    w.x -= (speedFactor 600 w.speed) * dt;
    if (w.x < -100) {
    w.x = 1250 + Math.random() * 200;
    w.y = 80 + Math.random() * 480;
    }
    if (windLines[i]) {
    windLines[i].setAttribute('x1', w.x);
    windLines[i].setAttribute('y1', w.y);
    windLines[i].setAttribute('x2', w.x + w.len (speedFactor 0.8));
    windLines[i].setAttribute('y2', w.y);
    windLines[i].setAttribute('opacity', Math.min(0.7, 0.15 * speedFactor));
    }
    });

    requestAnimationFrame(animate);
    }

    requestAnimationFrame(animate);

    // ================= INTERACTION HANDLERS =================

    // Speed boost toggle / sprint
    let isSprinting = false;
    function toggleSprint() {
    isSprinting = !isSprinting;
    if (isSprinting) {
    targetSpeed = 54;
    btnSpeed.innerHTML = '💨 巡航';
    btnSpeed.style.background = '#fde047';
    } else {
    targetSpeed = 28;
    btnSpeed.innerHTML = '⚡ 加速';
    btnSpeed.style.background = '';
    }
    }

    btnSpeed.addEventListener('click', toggleSprint);

    // Bell chime button & click on bicycle bell
    btnBell.addEventListener('click', playBellSound);
    bikeBellGroup.addEventListener('click', playBellSound);

    // Theme Switcher (Day -> Sunset -> Night)
    btnTheme.addEventListener('click', () => {
    timeThemeIndex = (timeThemeIndex + 1) % themes.length;
    document.body.className = themes[timeThemeIndex];
    const icons = ['🌅 傍晚', '🌙 夜晚', '☀️ 白天'];
    btnTheme.innerHTML = icons[timeThemeIndex];
    });

    // Keyboard shortcuts
    window.addEventListener('keydown', (e) => {
    if (e.code === 'Space') {
    e.preventDefault();
    toggleSprint();
    } else if (e.code === 'KeyB') {
    playBellSound();
    }
    });
    </script>
    </body>
    </html>

    主楼
  • 佬友记

    目前见过的最好的版本,比grok的还要好

    #1
  • DIAVE971

    佬是使用反代的api吗?用的是啥工具啊,求指路

    #2
  • 紫米

    tg随便搜的一个中转站,大概率是反重力反代

    #3
  • liansishen

    今天刚买了个反重力pro,折腾了好久终于用上了,希望能撑久一点

    #4
  • zlflly

    佬友用的什么harness哇,感觉很简洁很不错

    #5
  • tuozhwei

    难道现在的AI是轮流坐庄吗,Gemini又雄起了?

    #6
  • 紫米

    deepseek harness 自己装了些插件

    #7
  • mmmmmly

    这个看着真不错啊,比我网页版的gpt-5.6-sol画的都好了

    #8
  • catnap

    图片

    我的pro反代,脚蹬子那里拉了

    #9

发表回复

登录后回复