实测Qwen3.8-27B-Q4_K_M.gguf(RTX3090部署) 。鹈鹕骑自行车
Qwen3.8-27B-Q4_K_M.gguf来自 unsloth/Qwen3.8-27B-GGUF at main (https://huggingface.co/unsloth/Qwen3.8-27B-GGUF/tree/main)
完全通过对话一句话生成html(无harness或agent):
https://cdn3.ldstatic.com/original/4X/1/0/e/10e3becbf943986d9c8ddea74484a5a1fda0121d.webp
https://cdn3.ldstatic.com/optimized/4X/a/d/f/adf91355d1e75198d40f6b5974871b3250a8fb05_2_690x481.png
代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>鹈鹕骑行 · Pelican Ride</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=ZCOOL+KuaiLe&family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet">
<style>
*{box-sizing:border-box}
html,body{height:100%;margin:0;overflow:hidden}
body{
font-family:'Noto Sans SC','PingFang SC','Microsoft YaHei',sans-serif;
background:linear-gradient(180deg,#6fc7ea,#e9f6e6);
-webkit-user-select:none;user-select:none;
}
#scene{position:fixed;inset:0;width:100%;height:100%;display:block;touch-action:none;cursor:grab}
body.sprinting #scene{cursor:grabbing}
/* ---------- HUD ---------- */
.hud{position:fixed;z-index:10}
.card{
background:#fffdf8;border:3px solid #173142;border-radius:16px;
box-shadow:5px 6px 0 rgba(23,49,66,.20);
transition:transform .25s ease,box-shadow .25s ease;
}
.card:hover{transform:translateY(-3px);box-shadow:7px 10px 0 rgba(23,49,66,.24)}
.title-card{top:20px;left:20px;padding:10px 18px 12px;transform:rotate(-2deg)}
.title-card:hover{transform:rotate(-2deg) translateY(-3px)}
.title-card h1{margin:0;font-family:'ZCOOL KuaiLe','Noto Sans SC',sans-serif;font-weight:400;
font-size:clamp(20px,3vw,27px);letter-spacing:3px;color:#173142;line-height:1.15}
.title-card .sub{margin:3px 0 0;font-size:10px;letter-spacing:4px;font-weight:700;color:#ff6b4a}
.speed-card{top:20px;right:20px;padding:10px 18px;display:flex;align-items:center;gap:12px;transform:rotate(1.6deg)}
.speed-card:hover{transform:rotate(1.6deg) translateY(-3px)}
.speed-card .label{display:flex;align-items:center;gap:7px;font-size:12px;font-weight:700;color:#5b7186;letter-spacing:2px}
.dot{width:9px;height:9px;border-radius:50%;background:#4e9d5b;animation:dotPulse 1.8s ease-in-out infinite;transition:background .3s}
@keyframes dotPulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.6);opacity:.55}}
body.sprinting .dot{background:#ff6b4a;animation-duration:.45s}
.speed{display:flex;align-items:baseline;gap:4px}
.speed b{font-family:'ZCOOL KuaiLe','Noto Sans SC',sans-serif;font-weight:400;
font-size:clamp(26px,3.4vw,36px);color:#ff6b4a;line-height:1;display:inline-block;transition:transform .25s ease}
body.sprinting .speed b{transform:scale(1.14)}
.speed i{font-style:normal;font-size:11px;font-weight:700;color:#5b7186}
.hint{bottom:18px;left:50%;transform:translateX(-50%);
background:#173142;color:#eaf2f7;border-radius:999px;padding:9px 20px;
font-size:13px;letter-spacing:1px;display:flex;gap:12px;align-items:center;
box-shadow:5px 6px 0 rgba(23,49,66,.20);white-space:nowrap}
.hint .sep{opacity:.4}
kbd{background:#fffdf8;color:#173142;border:2px solid #2c4a63;border-bottom-width:3px;border-radius:7px;
padding:1px 8px;font-family:inherit;font-size:12px;font-weight:700}
@media (max-width:640px){
.hint{font-size:11px;padding:7px 14px;flex-wrap:wrap;justify-content:center;max-width:92vw;white-space:normal;text-align:center}
}
/* ---------- SVG 动画 ---------- */
.eyelid{transform-box:fill-box;transform-origin:center;transform:scaleY(.05);animation:blink 4.6s infinite}
@keyframes blink{0%,90.5%,96.5%,100%{transform:scaleY(.05)}92.5%,94.5%{transform:scaleY(1)}}
.gullMove{animation:cross linear infinite}
.g1{animation-duration:17s}
.g2{animation-duration:26s;animation-delay:-11s}
@keyframes cross{from{transform:translateX(-150px)}to{transform:translateX(1430px)}}
.gullFlap{transform-box:fill-box;transform-origin:center;animation:flap .55s ease-in-out infinite}
.g2 .gullFlap{animation-duration:.75s}
@keyframes flap{0%,100%{transform:scaleY(1)}50%{transform:scaleY(.35)}}
.puffA{fill:#d5dcd6;transform-box:fill-box;transform-origin:center;animation:puffA .95s linear infinite}
.puffB{fill:#c8d2cc;transform-box:fill-box;transform-origin:center;animation:puffB 1.2s linear infinite}
@keyframes puffA{0%{opacity:.55;transform:translate(0,0) scale(.4)}100%{opacity:0;transform:translate(-115px,20px) scale(1.9)}}
@keyframes puffB{0%{opacity:.5;transform:translate(0,0) scale(.5)}100%{opacity:0;transform:translate(-135px,-12px) scale(2.1)}}
.w{animation:wind .55s linear infinite}
@keyframes wind{0%{opacity:0;transform:translateX(45px)}30%{opacity:.9}100%{opacity:0;transform:translateX(-95px)}}
.tail{transform-box:fill-box;transform-origin:0% 50%;animation:tailWag .8s ease-in-out infinite alternate}
@keyframes tailWag{from{transform:rotate(-24deg)}to{transform:rotate(24deg)}}
.sway{transform-box:fill-box;transform-origin:50% 100%;animation:sway 3s ease-in-out infinite alternate}
@keyframes sway{from{transform:rotate(-1.8deg)}to{transform:rotate(1.8deg)}}
.rays{transform-box:fill-box;transform-origin:center;animation:spin 46s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.sunPulse{transform-box:fill-box;transform-origin:center;animation:sunPulse 5s ease-in-out infinite alternate}
@keyframes sunPulse{from{transform:scale(1)}to{transform:scale(1.06)}}
.lamp{animation:lamp 2.4s ease-in-out infinite}
@keyframes lamp{0%,100%{opacity:.35}50%{opacity:1}}
#bubble{transform-box:fill-box;transform-origin:50% 100%;transform:scale(.25);opacity:0;
transition:transform .24s cubic-bezier(.34,1.56,.64,1),opacity .16s ease}
#bubble.show{transform:scale(1);opacity:1}
@media (prefers-reduced-motion:reduce){
.puffA,.puffB,.w,.gullMove,.gullFlap,.tail,.sway,.rays,.sunPulse,.lamp,.dot,.eyelid{animation:none}
}
</style>
</head>
<body>
<svg id="scene" viewBox="0 0 1280 640" preserveAspectRatio="xMidYMid slice" role="img" aria-label="一只鹈鹕骑着自行车沿海岸公路飞驰">
<title>鹈鹕骑自行车</title>
<defs>
<linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#6fc7ea"/><stop offset=".55" stop-color="#a8e2f2"/><stop offset="1" stop-color="#e9f6e6"/>
</linearGradient>
<radialGradient id="sunGlow">
<stop offset="0" stop-color="#fff3c4" stop-opacity=".95"/><stop offset="1" stop-color="#fff3c4" stop-opacity="0"/>
</radialGradient>
<linearGradient id="road" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#7b8b98"/><stop offset="1" stop-color="#5c6c79"/>
</linearGradient>
<radialGradient id="vig" cx=".5" cy=".45" r=".75">
<stop offset=".62" stop-color="#0e2a3d" stop-opacity="0"/><stop offset="1" stop-color="#0e2a3d" stop-opacity=".16"/>
</radialGradient>
<g id="cloud">
<ellipse cx="0" cy="0" rx="46" ry="19" fill="#fff"/>
<ellipse cx="-30" cy="-9" rx="26" ry="14" fill="#fff"/>
<ellipse cx="30" cy="-12" rx="28" ry="16" fill="#fff"/>
<ellipse cx="4" cy="-20" rx="24" ry="14" fill="#fff"/>
</g>
<g id="treeA">
<rect x="-4" y="-26" width="8" height="26" rx="3" fill="#8a6a4a"/>
<circle cx="-12" cy="-34" r="16" fill="#5fae6b"/><circle cx="12" cy="-36" r="15" fill="#6fbf78"/><circle cx="0" cy="-48" r="17" fill="#7cc987"/>
</g>
<g id="treeB">
<rect x="-3.5" y="-24" width="7" height="24" rx="3" fill="#96754f"/>
<ellipse cx="0" cy="-44" rx="20" ry="24" fill="#4e9d5b"/><ellipse cx="0" cy="-50" rx="13" ry="15" fill="#5fae6b"/>
</g>
<g id="tuft" stroke="#4e9d5b" stroke-width="3" stroke-linecap="round" fill="none">
<path d="M0 0 C-2 -8 -6 -12 -9 -14"/><path d="M0 0 C0 -10 1 -14 0 -18"/><path d="M0 0 C2 -8 6 -11 9 -13"/>
</g>
<g id="flower">
<line x1="0" y1="0" x2="0" y2="-12" stroke="#4e9d5b" stroke-width="2.5"/>
<circle cx="0" cy="-15" r="4.5" fill="#ff6b4a"/><circle cx="0" cy="-15" r="1.8" fill="#ffd75e"/>
</g>
<g id="flower2">
<line x1="0" y1="0" x2="0" y2="-12" stroke="#4e9d5b" stroke-width="2.5"/>
<circle cx="0" cy="-15" r="4.5" fill="#ffc247"/><circle cx="0" cy="-15" r="1.8" fill="#fffdf6"/>
</g>
<g id="boat">
<path d="M-12 0 L12 0 L7 6 L-8 6 Z" fill="#8a5a3a"/>
<path d="M2 -2 L2 -22 L14 -2 Z" fill="#fff"/><path d="M0 -2 L0 -18 L-10 -2 Z" fill="#f2e9d8"/>
</g>
<!-- 远景层(海 + 岬角) -->
<g id="tileFar">
<rect x="0" y="470" width="1280" height="50" fill="#8fd4e4"/>
<rect x="0" y="470" width="1280" height="5" fill="#d6f2f6"/>
<path d="M0 470 V436 Q100 402 220 430 T470 428 T720 424 T960 432 T1180 426 T1280 436 V470 Z" fill="#b7d9e6"/>
<path d="M0 470 V448 Q160 428 330 446 T700 444 T1050 448 T1280 448 V470 Z" fill="#9cc9da" opacity=".8"/>
<g stroke="#cdeef4" stroke-width="3" stroke-linecap="round" opacity=".9">
<line x1="120" y1="492" x2="180" y2="492"/><line x1="420" y1="506" x2="470" y2="506"/>
<line x1="760" y1="490" x2="830" y2="490"/><line x1="1080" y1="504" x2="1130" y2="504"/>
</g>
<use href="#boat" x="560" y="488"/>
<use href="#boat" transform="translate(950,498) scale(.7)"/>
</g>
<!-- 中景层(树 / 灯塔 / 路牌) -->
<g id="tileMid">
<clipPath id="lhC"><path d="M120 520 L132 432 H152 L164 520 Z"/></clipPath>
<path d="M120 520 L132 432 H152 L164 520 Z" fill="#fdfaf2"/>
<g clip-path="url(#lhC)">
<rect x="112" y="494" width="60" height="24" fill="#ff6b5a"/>
<rect x="112" y="446" width="60" height="24" fill="#ff6b5a"/>
</g>
<rect x="128" y="420" width="28" height="12" fill="#2c4a63"/>
<path d="M126 420 L142 404 L158 420 Z" fill="#ff6b5a"/>
<circle class="lamp" cx="142" cy="426" r="4" fill="#ffd75e"/>
<use href="#treeA" transform="translate(340,520)"/>
<use href="#treeB" transform="translate(520,520) scale(.85)"/>
<use href="#treeA" transform="translate(980,520) scale(1.12)"/>
<use href="#treeB" transform="translate(1180,520) scale(.7)"/>
<ellipse cx="260" cy="514" rx="26" ry="12" fill="#8fcf98"/>
<ellipse cx="660" cy="515" rx="20" ry="10" fill="#83c48d"/>
<ellipse cx="880" cy="514" rx="24" ry="11" fill="#8fcf98"/>
<ellipse cx="430" cy="516" rx="14" ry="7" fill="#d8e2dc"/>
<ellipse cx="770" cy="517" rx="10" ry="5" fill="#cfdad4"/>
<g class="sway">
<rect x="698" y="472" width="6" height="48" fill="#7a5c3e"/>
<rect x="652" y="440" width="98" height="34" rx="8" fill="#fffdf6" stroke="#2c4a63" stroke-width="3"/>
<text x="701" y="463" text-anchor="middle" font-size="17" fill="#2c4a63" font-family="'ZCOOL KuaiLe','Noto Sans SC',sans-serif">海岸线 →</text>
</g>
</g>
<!-- 近景层(路边草 + 花 + 石子) -->
<g id="tileNear">
<rect x="0" y="512" width="1280" height="8" fill="#85c98b"/>
<rect x="0" y="512" width="1280" height="2.5" fill="#a5dba8"/>
<use href="#tuft" transform="translate(80,520)"/>
<use href="#tuft" transform="translate(300,520) scale(-1,1)"/>
<use href="#tuft" transform="translate(540,520)"/>
<use href="#tuft" transform="translate(760,520) scale(-1,1)"/>
<use href="#tuft" transform="translate(990,520)"/>
<use href="#tuft" transform="translate(1230,520) scale(-1,1)"/>
<use href="#flower" transform="translate(180,519)"/>
<use href="#flower2" transform="translate(430,519)"/>
<use href="#flower" transform="translate(680,519) scale(.9)"/>
<use href="#flower2" transform="translate(900,519)"/>
<use href="#flower" transform="translate(1150,519)"/>
<ellipse cx="240" cy="592" rx="7" ry="3" fill="#b9c4c9" opacity=".5"/>
<ellipse cx="620" cy="612" rx="9" ry="3.5" fill="#b9c4c9" opacity=".45"/>
<ellipse cx="1010" cy="586" rx="6" ry="2.5" fill="#b9c4c9" opacity=".5"/>
</g>
<g id="tileC1">
<use href="#cloud" transform="translate(180,110) scale(.8)"/>
<use href="#cloud" transform="translate(640,72) scale(.55)"/>
<use href="#cloud" transform="translate(1020,150) scale(.9)"/>
</g>
<g id="tileC2">
<use href="#cloud" transform="translate(420,196) scale(1.2)"/>
<use href="#cloud" transform="translate(90,120)"/>
</g>
</defs>
<!-- 天空 / 太阳 -->
<rect width="1280" height="640" fill="url(#sky)"/>
<g transform="translate(1050,135)">
<circle r="74" fill="url(#sunGlow)"/>
<g class="rays" stroke="#ffd75e" stroke-width="5" stroke-linecap="round" opacity=".85">
<line x1="46" y1="0" x2="60" y2="0"/><line x1="-46" y1="0" x2="-60" y2="0"/>
<line x1="0" y1="46" x2="0" y2="60"/><line x1="0" y1="-46" x2="0" y2="-60"/>
<line x1="32.5" y1="32.5" x2="42.4" y2="42.4"/><line x1="-32.5" y1="32.5" x2="-42.4" y2="42.4"/>
<line x1="32.5" y1="-32.5" x2="42.4" y2="-42.4"/><line x1="-32.5" y1="-32.5" x2="-42.4" y2="-42.4"/>
</g>
<circle class="sunPulse" r="34" fill="#ffd75e"/>
<circle r="34" fill="none" stroke="#ffc247" stroke-width="3" opacity=".6"/>
</g>
<!-- 云(两层视差) -->
<g id="clouds1" opacity=".85"><use href="#tileC1"/><use href="#tileC1" x="1280"/></g>
<g id="clouds2" opacity=".95"><use href="#tileC2"/><use href="#tileC2" x="1280"/></g>
<!-- 海鸥 -->
<g transform="translate(0,150)"><g class="gullMove g1">
<g class="gullFlap"><path d="M0 0 Q9 -9 18 -1 Q27 -9 36 0" fill="none" stroke="#4a6b80" stroke-width="3.5" stroke-linecap="round"/></g>
</g></g>
<g transform="translate(0,25)"><g class="gullMove g2"><g transform="scale(.7)">
<g class="gullFlap"><path d="M0 0 Q9 -9 18 -1 Q27 -9 36 0" fill="none" stroke="#5b7f96" stroke-width="4" stroke-linecap="round"/></g>
</g></g></g>
<!-- 视差层 -->
<g id="layerFar"><use href="#tileFar"/><use href="#tileFar" x="1280"/></g>
<g id="layerMid"><use href="#tileMid"/><use href="#tileMid" x="1280"/></g>
<!-- 公路 -->
<rect x="0" y="520" width="1280" height="120" fill="url(#road)"/>
<line id="dashes" x1="-40" y1="578" x2="1320" y2="578" stroke="#f4f7f5" stroke-width="7" stroke-dasharray="46 54" opacity=".85"/>
<g id="layerNear"><use href="#tileNear"/><use href="#tileNear" x="1280"/></g>
<!-- ============ 鹈鹕 + 自行车 ============ -->
<g id="bikeWorld" transform="translate(560,462)">
<ellipse cx="92" cy="57" rx="152" ry="9" fill="#12303f" opacity=".15"/>
<!-- 扬尘 -->
<g id="dust" opacity=".35">
<circle class="puffA" cx="-54" cy="46" r="7"/>
<circle class="puffB" cx="-60" cy="52" r="9" style="animation-delay:-.3s"/>
<circle class="puffA" cx="-48" cy="50" r="5" style="animation-delay:-.55s"/>
<circle class="puffB" cx="-58" cy="42" r="6" style="animation-delay:-.8s"/>
</g>
<!-- 远侧脚踏 / 远腿 -->
<g id="pedalF" transform="translate(50,-20)">
<rect x="-10" y="-1" width="20" height="5" rx="2" fill="#2a3540"/>
<path d="M-8 -1 C-8 -7 3 -8 9 -5 L15 -2 C16 -1 16 0 15 1 L8 3 C2 5 -8 4 -8 -1 Z" fill="#d97f22"/>
<path d="M4 -6 L5 -1 M9 -4 L9 1" stroke="#b5641c" stroke-width="1.4"/>
</g>
<line id="thighF" x1="46" y1="-102" x2="92.7" y2="-67.7" stroke="#7f8a2e" stroke-width="10" stroke-linecap="round"/>
<line id="shinF" x1="92.7" y1="-67.7" x2="50" y2="-20" stroke="#8a9433" stroke-width="8" stroke-linecap="round"/>
<!-- 远侧翅膀(扶把) -->
<g id="wingF">
<path d="M76 -142 C108 -152 148 -144 172 -127 C178 -123 176 -16 168 -18 C146 -124 12 -126 78 -124 Z" fill="#e6dcc6"/>
</g>
<!-- 车轮 -->
<g>
<circle r="58" fill="none" stroke="#2f3b46" stroke-width="10"/>
<circle r="49" fill="none" stroke="#e8ef2" stroke-width="4"/>
<g id="spinR">
<g stroke="#a9b8c4" stroke-width="3" stroke-linecap="round">
<line x1="0" y1="-46" x2="0" y2="46"/><line x1="-46" y1="0" x2="46" y2="0"/>
<line x1="-32.5" y1="-32.5" x2="32.5" y2="32.5"/><line x1="-32.5" y1="32.5" x2="32.5" y2="-32.5"/>
</g>
<circle cx="0" cy="-46" r="2.6" fill="#5b6c7a"/>
<circle r="7" fill="#3c4a57"/><circle r="2.6" fill="#dfe7ec"/>
</g>
</g>
<g transform="translate(178,0)">
<circle r="58" fill="none" stroke="#2f3b46" stroke-width="10"/>
<circle r="49" fill="none" stroke="#e8eef2" stroke-width="4"/>
<g id="spinF">
<g stroke="#a9b8c4" stroke-width="3" stroke-linecap="round">
<line x1="0" y1="-46" x2="0" y2="46"/><line x1="-46" y1="0" x2="46" y2="0"/>
<line x1="-32.5" y1="-32.5" x2="32.5" y2="32.5"/><line x1="-32.5" y1="32.5" x2="32.5" y2="-32.5"/>
</g>
<circle cx="0" cy="-46" r="2.6" fill="#5b6c7a"/>
<circle r="7" fill="#3c4a57"/><circle r="2.6" fill="#dfe7ec"/>
</g>
</g>
<!-- 车架 -->
<g stroke="#128a8a" stroke-width="7" stroke-linecap="round" fill="none">
<path d="M82 -20 L0 0"/><path d="M42 -98 L0 0"/><path d="M82 -20 L42 -102"/>
<path d="M82 -20 L164 -92"/><path d="M46 -100 L162 -96"/><path d="M178 0 Q170 -52 162 -98"/>
</g>
<circle cx="0" cy="0" r="9" fill="none" stroke="#3c4a57" stroke-width="3"/>
<path id="chain" d="M82 -39 L0 -9 A9 9 0 0 0 0 9 L82 -1 A19 19 0 0 0 82 -39" fill="none"
stroke="#4a5866" stroke-width="4" stroke-dasharray="7 5"/>
<g id="gCrank" transform="translate(82,-20)">
<circle r="19" fill="none" stroke="#3c4a57" stroke-width="4"/>
<g fill="#3c4a57">
<circle cx="12" cy="0" r="2.2"/><circle cx="-12" cy="0" r="2.2"/>
<circle cx="0" cy="12" r="2.2"/><circle cx="0" cy="-12" r="2.2"/>
</g>
<line x1="0" y1="0" x2="-32" y2="0" stroke="#2a3540" stroke-width="6" stroke-linecap="round"/>
<line x1="0" y1="0" x2="32" y2="0" stroke="#3404c" stroke-width="6" stroke-linecap="round"/>
<circle r="4.5" fill="#3404c"/>
</g>
<!-- 座管 / 车座 / 车把 / 车铃 -->
<line x1="42" y1="-102" x2="36" y2="-118" stroke="#33404c" stroke-width="5" stroke-linecap="round"/>
<path d="M16 -118 Q34 -128 58 -117 Q38 -10 16 -118 Z" fill="#33404c"/>
<line x1="162" y1="-98" x2="158" y2="-14" stroke="#3404c" stroke-width="6" stroke-linecap="round"/>
<path d="M158 -114 Q172 -128 184 -120" fill="none" stroke="#33404c" stroke-width="6" stroke-linecap="round"/>
<circle cx="184" cy="-120" r="4" fill="#22303c"/>
<circle cx="157" cy="-18" r="3.5" fill="#ffc247" stroke="#e8a13c" stroke-width="1.2"/>
<!-- 前车筐 + 小鱼 -->
<path d="M156 -96 L198 -96 L192 -72 L162 -72 Z" fill="#c98a4b"/>
<g transform="translate(176,-84)">
<g transform="translate(9,0)"><g class="tail"><path d="M0 0 L8 -6 L8 6 Z" fill="#4a7fa5"/></g></g>
<ellipse cx="0" cy="0" rx="10" ry="5.5" fill="#5b8fb8"/>
<path d="M-3 -5 L0 -9 L3 -5 Z" fill="#4a7fa5"/>
<circle cx="-6" cy="-1" r="1.3" fill="#1d2c38"/>
</g>
<path d="M156 -84 L198 -84 L192 -72 L162 -72 Z" fill="#b97c40"/>
<path d="M158 -8 L196 -88 M160 -80 L194 -80" stroke="#a06a35" stroke-width="1.5" opacity=".7"/>
<!-- 鹈鹕身体(整体上下起伏) -->
<g id="bodyG">
<path d="M8 -140 L-16 -152 L2 -132 Z" fill="#f3ead9"/>
<path d="M10 -130 L-14 -140 L6 -120 Z" fill="#eadfc8"/>
<path d="M2 -126 C-8 -152 24 -172 60 -166 C94 -160 114 -146 112 -126 C111 -108 92 -94 66 -92 C40 -90 10 -100 2 -126 Z"
fill="#fdf9f1" stroke="#e2d9c8" stroke-width="2"/>
<ellipse cx="64" cy="-110" rx="36" ry="17" fill="#f4ecdc" opacity=".8"/>
<path d="M98 -146 C106 -158 110 -174 118 -190" stroke="#fdf9f1" stroke-width="15" stroke-linecap="round" fill="none"/>
<path d="M106 -206 Q96 -218 88 -216 Q98 -210 104 -202 Z" fill="#f3ead9"/>
<path d="M100 -198 Q90 -206 84 -205 Q92 -20 98 -194 Z" fill="#eadfc8"/>
<circle cx="120" cy="-196" r="15" fill="#fdf9f1"/>
<circle cx="110" cy="-190" r="4" fill="#ffb3a0" opacity=".55"/>
<g id="pouch">
<path d="M130 -186 C148 -164 190 -160 214 -179 C192 -152 152 -154 130 -186 Z" fill="#ff8a4d"/>
<path d="M136 -182 C156 -166 188 -162 208 -176" stroke="#ef7038" stroke-width="2" fill="none"/>
</g>
<path d="M128 -204 C162 -200 198 -190 217 -181 C219 -179 218 -177 215 -178 C192 -181 158 -185 129 -187 Z"
fill="#ffc247" stroke="#eaa63c" stroke-width="1.5"/>
<path d="M146 -196 L158 -193" stroke="#eaa63c" stroke-width="2" stroke-linecap="round"/>
<circle cx="124" cy="-20" r="5.5" fill="#fff" stroke="#d8cfc0" stroke-width="1"/>
<circle cx="126" cy="-200" r="2.8" fill="#2303c"/>
<circle cx="127.2" cy="-201.4" r="1" fill="#fff"/>
<ellipse class="eyelid" cx="124" cy="-200" rx="6" ry="6.5" fill="#fdf9f1"/>
</g>
<!-- 近侧翅膀(扶把) -->
<g id="wingN">
<path d="M64 -148 C98 -162 14 -154 178 -130 C186 -124 184 -116 174 -119 C158 -124 146 -127 132 -128 C108 -130 82 -130 64 -136 Z"
fill="#f8f1e3" stroke="#e0d5c0" stroke-width="2"/>
<path d="M16 -140 C138 -138 156 -132 168 -125 M100 -146 C124 -146 148 -140 162 -132" stroke="#e6dcc8" stroke-width="2" fill="none"/>
</g>
<!-- 近侧腿 + 脚踏 -->
<line id="thighN" x1="38" y1="-100" x2="92.5" y2="-80.3" stroke="#a4ad3b" stroke-width="11" stroke-linecap="round"/>
<line id="shinN" x1="92.5" y1="-80.3" x2="114" y2="-20" stroke="#b3bc45" stroke-width="9" stroke-linecap="round"/>
<g id="pedalN" transform="translate(114,-20)">
<rect x="-10" y="-1" width="20" height="5.5" rx="2" fill="#33404c"/>
<path d="M-8 -1 C-8 -8 3 -9 9 -6 L15 -3 C16 -2 16 -1 15 0 L8 2 C2 4 -8 4 -8 -1 Z" fill="#ffa032"/>
<path d="M4 -7 L5 -2 M9 -5 L9 0" stroke="#d97f22" stroke-width="1.5"/>
</g>
<!-- 风线 -->
<g id="wind" opacity=".15" stroke="#ffffff" stroke-width="5" stroke-linecap="round">
<line class="w" x1="-30" y1="-158" x2="-88" y2="-158"/>
<line class="w" x1="-12" y1="-124" x2="-80" y2="-124" style="animation-delay:-.18s"/>
<line class="w" x1="-26" y1="-96" x2="-72" y2="-96" style="animation-delay:-.36s"/>
</g>
<!-- 叫声气泡 -->
<g transform="translate(150,-252)">
<g id="bubble">
<path d="M-8 8 L0 30 L16 8 Z" fill="#fffdf6" stroke="#173142" stroke-width="3"/>
<rect x="-62" y="-38" width="124" height="48" rx="14" fill="#fffdf6" stroke="#173142" stroke-width="3"/>
<path d="M-8 8 L0 30 L16 8 Z" fill="#fffdf6"/>
<text x="0" y="-4" text-anchor="middle" font-size="26" fill="#ff6b4a"
font-family="'ZCOOL KuaiLe','Noto Sans SC',sans-serif">嘎嘎!</text>
</g>
</g>
</g>
<rect width="1280" height="640" fill="url(#vig)" pointer-events="none"/>
</svg>
<!-- HUD -->
<header class="hud card title-card">
<h1>鹈鹕骑行</h1>
<p class="sub">PELICAN RIDE · 2D SVG</p>
</header>
<div class="hud card speed-card" id="speedCard">
<span class="label"><span class="dot"></span>时速</span>
<span class="speed"><b id="kmh">14</b><i>km/h</i></span>
</div>
<div class="hud hint">
<span><kbd>空格</kbd> 或按住画面 → 冲刺</span>
<span class="sep">·</span>
<span>点一下鹈鹕,它会叫</span>
</div>
<script>
(function(){
const $=id=>document.getElementById(id);
const BASE=260, SPRINT=640, TILE=1280, R2D=180/Math.PI;
let speed=BASE, sprinting=false;
let crank=0, wheelA=0, chainOff=0, dashOff=0;
let offF=0, offM=0, offN=0, offC1=0, offC2=0;
const el={
far:$('layerFar'),mid:$('layerMid'),near:$('layerNear'),c1:$('clouds1'),c2:$('clouds2'),
dash:$('dashes'),spinR:$('spinR'),spinF:$('spinF'),crank:$('gCrank'),chain:$('chain'),
pedN:$('pedalN'),pedF:$('pedalF'),
thN:$('thighN'),shN:$('shinN'),thF:$('thighF'),shF:$('shinF'),
body:$('bodyG'),wingN:$('wingN'),wingF:$('wingF'),pouch:$('pouch'),
bike:$('bikeWorld'),wind:$('wind'),dust:$('dust'),kmh:$('kmh'),bubble:$('bubble')
};
// 曲柄中心 / 曲柄长 / 腿长
const B={x:82,y:-20}, CR=32, L1=58, L2=64;
const hipN={x:38,y:-100}, hipF={x:46,y:-102};
const ped=a=>({x:B.x+CR*Math.cos(a), y:B.y+CR*Math.sin(a)});
// 两骨 IK:髋 → 膝 → 脚
function ik(h,f){
let dx=f.x-h.x, dy=f.y-h.y, d=Math.hypot(dx,dy);
const mn=Math.abs(L1-L2)+1, mx=L1+L2-1;
if(d<mn)d=mn; if(d>mx)d=mx;
const a=Math.atan2(dy,dx);
const t=Math.acos(Math.max(-1,Math.min(1,(L1*L1+d*d-L2*L2)/(2*L1*d))));
const ka=a-t; // 膝盖朝前弯曲
return {x:h.x+L1*Math.cos(ka), y:h.y+L1*Math.sin(ka)};
}
function line(e,x1,y1,x2,y2){
e.setAttribute('x1',x1.toFixed(1)); e.setAttribute('y1',y1.toFixed(1));
e.setAttribute('x2',x2.toFixed(1)); e.setAttribute('y2',y2.toFixed(1));
}
let last=performance.now();
function tick(now){
const dt=Math.min(.05,(now-last)/1000); last=now;
const tgt=sprinting?SPRINT:BASE;
speed+=(tgt-speed)*Math.min(1,dt*(sprinting?2.4:1.5));
const sf=Math.max(0,Math.min(1,(speed-BASE)/(SPRINT-BASE)));
// 驱动量
crank+=speed/58*1.9*dt; // 曲柄角速度(带齿比)
wheelA+=speed/58*dt; // 车轮与路面速度严格一致
chainOff-=speed*.62*dt;
dashOff=(dashOff+speed*dt)%100;
// 视差滚动
offF=(offF+speed*.12*dt)%TILE; offM=(offM+speed*.42*dt)%TILE; offN=(offN+speed*dt)%TILE;
offC1=(offC1+(14+speed*.045)*dt)%TILE; offC2=(offC2+(26+speed*.085)*dt)%TILE;
el.far .setAttribute('transform','translate('+(-offF)+',0)');
el.mid .setAttribute('transform','translate('+(-offM)+',0)');
el.near.setAttribute('transform','translate('+(-offN)+',0)');
el.c1 .setAttribute('transform','translate('+(-offC1)+',0)');
el.c2 .setAttribute('transform','translate('+(-offC2)+',0)');
el.dash .setAttribute('stroke-dashoffset',dashOff.toFixed(1));
el.chain.setAttribute('stroke-dashoffset',chainOff.toFixed(1));
// 车轮 / 牙盘
const wd=(wheelA*R2D)%360, cd=(crank*R2D)%360;
el.spinR.setAttribute('transform','rotate('+wd.toFixed(2)+')');
el.spinF.setAttribute('transform','rotate('+wd.toFixed(2)+')');
el.crank.setAttribute('transform','translate(82,-20) rotate('+cd.toFixed(2)+')');
// 脚踏位置 + 双腿 IK
const pN=ped(crank), pF=ped(crank+Math.PI);
el.pedN.setAttribute('transform','translate('+pN.x.toFixed(1)+','+pN.y.toFixed(1)+')');
el.pedF.setAttribute('transform','translate('+pF.x.toFixed(1)+','+pF.y.toFixed(1)+')');
const kN=ik(hipN,pN), kF=ik(hipF,pF);
line(el.thN,hipN.x,hipN.y,kN.x,kN.y); line(el.shN,kN.x,kN.y,pN.x,pN.y);
line(el.thF,hipF.x,hipF.y,kF.x,kF.y); line(el.shF,kF.x,kF.y,pF.x,pF.y);
// 身体起伏 / 翅膀推把 / 喉囊摆动(幅度随速度)
const bobY=Math.sin(crank*2)*(1.1+1.7*sf);
const bobR=Math.sin(crank*2+.55)*(.5+.9*sf);
el.body .setAttribute('transform','translate(0,'+bobY.toFixed(2)+') rotate('+bobR.toFixed(2)+' 40 -106)');
const wr=Math.sin(crank-.45)*(2.6+2.6*sf);
el.wingN.setAttribute('transform','rotate('+wr.toFixed(2)+' 66 -138)');
el.wingF.setAttribute('transform','rotate('+(-wr*.8).toFixed(2)+' 76 -132)');
el.pouch.setAttribute('transform','rotate('+(Math.sin(crank+.9)*(1.4+1.6*sf)).toFixed(2)+' 130 -188)');
// 冲刺时车身前倾
el.bike.setAttribute('transform','translate(560,462) rotate('+(-1.5*sf).toFixed(2)+' 178 58)');
el.wind.setAttribute('opacity',(0.12+0.88*sf).toFixed(2));
el.dust.setAttribute('opacity',(0.25+0.6*sf).toFixed(2));
el.kmh.textContent=Math.round(speed*.055);
document.body.classList.toggle('sprinting',sf>.55);
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
// ---------- 交互 ----------
let holding=false, holdT=0, holdX=0, holdY=0;
const svg=$('scene');
const setSprint=v=>{sprinting=v;};
svg.addEventListener('pointerdown',e=>{
holding=true; holdT=performance.now(); holdX=e.clientX; holdY=e.clientY; setSprint(true);
});
window.addEventListener('pointerup',e=>{
if(holding){
const d=performance.now()-holdT;
if(d<260 && Math.hypot(e.clientX-holdX,e.clientY-holdY)<12) quack();
}
holding=false; setSprint(false);
});
window.addEventListener('pointercancel',()=>{holding=false;setSprint(false);});
window.addEventListener('keydown',e=>{
if(e.code==='Space'&&!e.repeat){e.preventDefault();setSprint(true);}
});
window.addEventListener('keyup',e=>{if(e.code==='Space')setSprint(false);});
svg.addEventListener('contextmenu',e=>e.preventDefault());
let qt;
function quack(){
el.bubble.classList.add('show');
clearTimeout(qt);
qt=setTimeout(()=>el.bubble.classList.remove('show'),1200);
}
})();
</script>
</body>
</html>
Qwen3.8-27B-Q4_K_M.gguf,部署在RTX3090 24G,
启动参数:
~/llama.cpp/build/bin/llama-server \
-m /root/models/Qwen3.8-27B-Q4_K_M.gguf \
-ngl 99 \
-ctk q4_1 -ctv q4_1 \
--spec-type draft-mtp --spec-draft-n-max 1 \
--reasoning-preserve \
-c 150000 --jinja -fa on \
--host 0.0.0.0 \
--port 49444
内存占用如下:
https://cdn3.ldstatic.com/original/4X/8/a/8/8a85b511bc4611c0e713a2821e9cb5a3a943f173.png
实际速度:
https://cdn3.ldstatic.com/original/4X/f/d/1/fd1152c2bbcd78d9e81b789349a04bd164164738.png 星颖的星友们都太优秀了,我大概是来拖后腿的,不过,拖得久了,也许能拖出个新高度,嘿嘿! 今天的收获:把课程当字典反复看,每遍都有新收获,投资自己永不亏
页:
[1]