Fable 5.1 MAX 鹈鹕测试

ZackWill 2026-09-02 02:56 1




<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>鹈鹕骑车</title>
<style>
:root {
--ink: #1e3a4c;
--accent: #f4b23c;
--hud-bg: rgba(23, 34, 44, .62);
}
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
overflow: hidden;
background: #6fb6e2;
font-family: "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif;
color: var(--ink);
}
#scene {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
display: block;
}
.title {
position: fixed;
top: 22px;
left: 26px;
pointer-events: none;
}
.title h1 {
margin: 0;
font-size: 24px;
font-weight: 600;
letter-spacing: .06em;
}
.title p {
margin: 6px 0 0;
font-size: 13px;
opacity: .75;
}
.hud {
position: fixed;
right: 20px;
bottom: 20px;
display: flex;
align-items: center;
gap: 12px;
padding: 8px 12px 8px 8px;
border-radius: 999px;
background: var(--hud-bg);
color: #fff;
font-size: 14px;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.hud button {
font: inherit;
color: #fff;
background: transparent;
border: 1px solid rgba(255, 255, 255, .55);
border-radius: 999px;
padding: 6px 16px;
min-width: 68px;
cursor: pointer;
}
.hud button:hover { background: rgba(255, 255, 255, .12); }
.hud label { opacity: .9; }
.hud input[type="range"] {
width: 130px;
accent-color: var(--accent);
}
.hud :focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
@media (max-width: 600px) {
.title h1 { font-size: 20px; }
.title p { display: none; }
.hud input[type="range"] { width: 90px; }
}
</style>
</head>
<body>

<svg id="scene" viewBox="0 0 1200 675" preserveAspectRatio="xMidYMid slice"
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="#6fb6e2"/>
<stop offset="1" stop-color="#e3f3fb"/>
</linearGradient>
<linearGradient id="seaGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#2b7ea6"/>
<stop offset="1" stop-color="#5eb0d4"/>
</linearGradient>
<radialGradient id="sunGlow">
<stop offset="0" stop-color="#fff6c8" stop-opacity=".95"/>
<stop offset="1" stop-color="#fff6c8" stop-opacity="0"/>
</radialGradient>
<linearGradient id="featherGrad" x1="0" y1="0" x2=".35" y2="1">
<stop offset="0" stop-color="#fdfcf8"/>
<stop offset="1" stop-color="#e1dccf"/>
</linearGradient>
<linearGradient id="pouchGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#f4a066"/>
<stop offset="1" stop-color="#e2814a"/>
</linearGradient>

<g id="cloud" fill="#fff" opacity=".96">
<ellipse cx="0" cy="8" rx="36" ry="14"/>
<circle cx="-14" cy="0" r="16"/>
<circle cx="6" cy="-9" r="21"/>
<circle cx="27" cy="2" r="15"/>
</g>

<g id="palm">
<path d="M0,0 C6,-50 4,-110 16,-165" stroke="#9c7350" stroke-width="10" stroke-linecap="round" fill="none"/>
<path d="M0,0 C6,-50 4,-110 16,-165" stroke="#b58a62" stroke-width="4" stroke-linecap="round" fill="none" stroke-dasharray="3 9"/>
<g fill="none" stroke-linecap="round" stroke-width="9">
<path d="M16,-165 C-10,-175 -40,-165 -58,-140" stroke="#2f7a4d"/>
<path d="M16,-165 C-5,-190 -30,-198 -52,-190" stroke="#3d8a5a"/>
<path d="M16,-165 C20,-195 8,-215 -8,-225" stroke="#3d8a5a"/>
<path d="M16,-165 C40,-190 60,-195 84,-185" stroke="#45995f"/>
<path d="M16,-165 C42,-172 68,-160 80,-138" stroke="#2f7a4d"/>
<path d="M16,-165 C30,-150 44,-132 46,-110" stroke="#2c6f46"/>
<path d="M16,-165 C0,-148 -14,-130 -18,-108" stroke="#2c6f46"/>
</g>
<circle cx="10" cy="-160" r="6" fill="#6b4a2b"/>
<circle cx="22" cy="-156" r="6" fill="#7a5533"/>
</g>

<g id="tuft" fill="none" stroke="#8fa25c" stroke-width="2.2" stroke-linecap="round">
<path d="M0,0 C-3,-8 -9,-14 -12,-20"/>
<path d="M0,0 C-1,-9 -3,-16 -5,-24"/>
<path d="M0,0 C1,-9 4,-16 5,-23"/>
<path d="M0,0 C3,-8 8,-13 12,-18"/>
<path d="M0,0 C5,-5 10,-8 16,-9"/>
</g>

<g id="umbrella">
<path d="M0,0 L0,-70" stroke="#6b4a2b" stroke-width="3" stroke-linecap="round"/>
<path d="M-42,-70 A42,42 0 0 1 42,-70 Z" fill="#e75f4d"/>
<path d="M0,-70 L-42,-70 A42,42 0 0 1 -34,-94.7 Z" fill="#fbe9dc"/>
<path d="M0,-70 L13,-109.9 A42,42 0 0 1 34,-94.7 Z" fill="#fbe9dc"/>
</g>

<g id="boat">
<path d="M-14,0 L14,0 L10,5 L-10,5 Z" fill="#3f4650"/>
<path d="M0,-1 L0,-24 L12,-1 Z" fill="#fff"/>
<path d="M-2,-1 L-2,-17 L-9,-1 Z" fill="#f2f2f2"/>
</g>

<g id="lighthouse">
<ellipse cx="0" cy="0" rx="42" ry="7" fill="#6e6a60"/>
<path d="M-30,0 C-26,-6 -10,-9 0,-9 C10,-9 26,-6 30,0 Z" fill="#7d786c"/>
<path d="M-9,-6 L-6,-58 L6,-58 L9,-6 Z" fill="#f4efe3"/>
<path d="M-8.2,-20 L8.2,-20 L7.7,-30 L-7.7,-30 Z" fill="#c8453b"/>
<path d="M-7,-40 L7,-40 L6.6,-48 L-6.6,-48 Z" fill="#c8453b"/>
<rect x="-7" y="-66" width="14" height="8" fill="#2f3a44"/>
<rect x="-5" y="-64" width="10" height="5" fill="#ffe27a"/>
<path d="M-8,-66 L0,-74 L8,-66 Z" fill="#c8453b"/>
</g>
</defs>

<!-- ===== sky ===== -->
<rect width="1200" height="372" fill="url(#skyGrad)"/>
<circle cx="1010" cy="96" r="95" fill="url(#sunGlow)"/>
<circle cx="1010" cy="96" r="40" fill="#fff1a8"/>

<g id="L_clouds">
<g id="cloudsTile">
<use href="#cloud" transform="translate(140 110) scale(1.1)"/>
<use href="#cloud" transform="translate(520 70) scale(.8)"/>
<use href="#cloud" transform="translate(860 150) scale(1.3)"/>
<use href="#cloud" transform="translate(1110 62) scale(.7)"/>
</g>
<use href="#cloudsTile" x="-1200"/>
<use href="#cloudsTile" x="1200"/>
</g>

<g id="L_gulls" fill="none" stroke="#3c4a55" stroke-width="2.5" stroke-linecap="round">
<g id="gullsTile">
<path transform="translate(260 140)">
<animate attributeName="d" dur=".7s" repeatCount="indefinite"
values="M-14,4 Q-7,-6 0,0 Q7,-6 14,4; M-14,-6 Q-7,2 0,0 Q7,2 14,-6; M-14,4 Q-7,-6 0,0 Q7,-6 14,4"/>
</path>
<path transform="translate(320 168) scale(.75)">
<animate attributeName="d" dur=".8s" begin="-.3s" repeatCount="indefinite"
values="M-14,4 Q-7,-6 0,0 Q7,-6 14,4; M-14,-6 Q-7,2 0,0 Q7,2 14,-6; M-14,4 Q-7,-6 0,0 Q7,-6 14,4"/>
</path>
<path transform="translate(760 108) scale(.9)">
<animate attributeName="d" dur=".75s" begin="-.5s" repeatCount="indefinite"
values="M-14,4 Q-7,-6 0,0 Q7,-6 14,4; M-14,-6 Q-7,2 0,0 Q7,2 14,-6; M-14,4 Q-7,-6 0,0 Q7,-6 14,4"/>
</path>
</g>
<use href="#gullsTile" x="-1200"/>
<use href="#gullsTile" x="1200"/>
</g>

<!-- ===== sea ===== -->
<rect y="372" width="1200" height="70" fill="url(#seaGrad)"/>
<rect y="371" width="1200" height="2" fill="#bfe3f0" opacity=".8"/>

<g id="L_boats">
<g id="boatsTile">
<use href="#boat" transform="translate(200 372) scale(.8)"/>
<use href="#boat" transform="translate(690 372)"/>
</g>
<use href="#boatsTile" x="-1200"/>
<use href="#boatsTile" x="1200"/>
</g>

<g id="L_light">
<g id="lightTile">
<use href="#lighthouse" transform="translate(960 378) scale(.9)"/>
</g>
<use href="#lightTile" x="-1200"/>
<use href="#lightTile" x="1200"/>
</g>

<g id="L_waves" fill="none" stroke="#d7eef7" stroke-width="2" stroke-linecap="round" opacity=".75">
<g id="wavesTile">
<path d="M0,392 H1200" stroke-dasharray="40 80"/>
<path d="M0,409 H1200" stroke-dasharray="60 90" stroke-dashoffset="35"/>
<path d="M0,426 H1200" stroke-dasharray="30 70" stroke-dashoffset="60"/>
</g>
<use href="#wavesTile" x="-1200"/>
<use href="#wavesTile" x="1200"/>
</g>

<!-- ===== sand ===== -->
<rect y="440" width="1200" height="80" fill="#eedcae"/>
<rect y="440" width="1200" height="9" fill="#d9c48f" opacity=".75"/>
<rect y="440" width="1200" height="2" fill="#fff" opacity=".85"/>

<g id="L_sand">
<g id="sandTile">
<use href="#palm" transform="translate(150 517) scale(1.05)"/>
<use href="#palm" transform="translate(640 517) scale(.8)"/>
<use href="#palm" transform="translate(1000 517) scale(1.15)"/>
<use href="#umbrella" transform="translate(830 517) scale(.75)"/>
<use href="#tuft" transform="translate(300 515) scale(1.2)"/>
<use href="#tuft" transform="translate(470 517) scale(1.1)"/>
<use href="#tuft" transform="translate(900 516) scale(1.3)"/>
<use href="#tuft" transform="translate(1140 515) scale(1.1)"/>
</g>
<use href="#sandTile" x="-1200"/>
<use href="#sandTile" x="1200"/>
</g>

<!-- ===== road ===== -->
<rect y="518" width="1200" height="92" fill="#57616c"/>
<rect y="523" width="1200" height="3" fill="#e9e3cf" opacity=".9"/>
<rect y="601" width="1200" height="3" fill="#e9e3cf" opacity=".9"/>

<g id="L_road">
<g id="roadTile">
<path d="M0,582 H1200" stroke="#eee7d0" stroke-width="4" stroke-dasharray="60 60" fill="none"/>
<g id="specks" fill="#6c7683"></g>
</g>
<use href="#roadTile" x="-1200"/>
<use href="#roadTile" x="1200"/>
</g>

<!-- ===== rider ===== -->
<g id="rider" transform="translate(20 0)">
<ellipse cx="560" cy="566" rx="200" ry="6" fill="#000" opacity=".16"/>

<!-- far leg (behind everything) -->
<path id="farThigh" fill="none" stroke="#d9d3c6" stroke-width="22" stroke-linecap="round"/>
<path id="farShin" fill="none" stroke="#c97a2a" stroke-width="9" stroke-linecap="round"/>
<line id="farCrank" x1="528" y1="505" x2="528" y2="535" stroke="#33363a" stroke-width="6" stroke-linecap="round"/>
<g id="farPedal"><rect x="-11" y="-2.5" width="22" height="5" rx="1.5" fill="#1e2023"/></g>
<g id="farFoot"><path d="M-11,-9 C-5,-13 6,-13 13,-9 L23,-3 L20,-2 L-9,-2 L-14,-5 Z" fill="#c97a2a"/></g>

<!-- wheels -->
<g transform="translate(450 498)">
<circle r="56" fill="none" stroke="#2d2f33" stroke-width="12"/>
<circle r="48" fill="none" stroke="#d8dbdf" stroke-width="4"/>
<g id="spokesR" stroke="#cfd3d8" stroke-width="1.6"></g>
<circle r="8" fill="#8a8f96"/>
</g>
<g transform="translate(670 498)">
<circle r="56" fill="none" stroke="#2d2f33" stroke-width="12"/>
<circle r="48" fill="none" stroke="#d8dbdf" stroke-width="4"/>
<g id="spokesF" stroke="#cfd3d8" stroke-width="1.6"></g>
<circle r="8" fill="#8a8f96"/>
<circle r="3" fill="#3a3d42"/>
</g>

<!-- frame -->
<g fill="none" stroke="#cf4a3c" stroke-width="7" stroke-linecap="round" stroke-linejoin="round">
<path d="M528,505 L498,402"/>
<path d="M498,408 L648,418"/>
<path d="M528,505 L660,452"/>
<path d="M648,410 L664,458"/>
<path d="M664,458 Q666,480 670,498"/>
<path d="M528,505 L450,498"/>
<path d="M498,404 L450,498"/>
</g>
<g fill="none" stroke="#8a8f96" stroke-width="5" stroke-linecap="round">
<path d="M498,402 L495,378"/>
<path d="M648,410 L651,393"/>
<path d="M634,393 L676,393"/>
</g>
<path d="M634,393 L649,393" stroke="#3a2a22" stroke-width="7.5" stroke-linecap="round" fill="none"/>
<path d="M466,372 C472,365 500,363 524,367 L522,377 C502,383 482,383 468,380 Z" fill="#5c3d2e"/>

<!-- basket with fish -->
<g>
<g transform="translate(700 396) rotate(-18)">
<ellipse rx="17" ry="7" fill="#a4bccb"/>
<path d="M14,0 L27,-10 L25,10 Z" fill="#7f99a9"/>
<circle cx="-9" cy="-1.5" r="1.6" fill="#243038"/>
</g>
<path d="M672,396 L716,396 L712,428 L676,428 Z" fill="#cfa55f"/>
<g stroke="#b98c46" stroke-width="1.5" fill="none">
<path d="M673,404 H715 M674,412 H714 M675,420 H713"/>
<path d="M684,396 L686,428 M694,396 L694,428 M704,396 L702,428"/>
</g>
<path d="M670,396 L718,396" stroke="#8f6a33" stroke-width="3.5" stroke-linecap="round"/>
</g>

<!-- drivetrain -->
<circle cx="450" cy="498" r="9" fill="#6b6f76"/>
<circle cx="450" cy="498" r="3" fill="#3a3d42"/>
<path id="chain" d="M450,489 L528,484 A21,21 0 0 1 528,526 L450,507 A9,9 0 0 1 450,489 Z"
fill="none" stroke="#3c3f44" stroke-width="3" stroke-dasharray="4 3"/>
<g transform="translate(528 505)" fill="none" stroke="#6b6f76">
<circle r="21" stroke-width="5"/>
<path d="M0,0 L0,-19 M0,0 L18,-6 M0,0 L11,15 M0,0 L-11,15 M0,0 L-18,-6" stroke-width="3"/>
</g>
<line id="nearCrank" x1="528" y1="505" x2="528" y2="475" stroke="#4c4f54" stroke-width="6" stroke-linecap="round"/>
<circle cx="528" cy="505" r="6" fill="#4c4f54"/>
<g id="nearPedal"><rect x="-11" y="-2.5" width="22" height="5" rx="1.5" fill="#2f3237"/></g>

<!-- pelican -->
<g id="neckHead">
<path d="M544,258 C556,230 552,196 574,172 C588,158 600,152 612,150"
fill="none" stroke="url(#featherGrad)" stroke-width="30" stroke-linecap="round"/>
<g fill="#fbfaf5" stroke="#d8d2c4" stroke-width="1.2" stroke-linejoin="round">
<path d="M594,136 L572,122 L598,128 Z"/>
<path d="M598,129 L580,110 L604,122 Z"/>
<path d="M604,124 L594,100 L612,118 Z"/>
</g>
<circle cx="612" cy="150" r="27" fill="#fbfaf5"/>
<g id="pouch">
<path d="M622,164 C660,168 730,180 782,188 C760,198 700,234 640,204 C628,196 622,180 622,164 Z" fill="url(#pouchGrad)"/>
</g>
<path d="M628,138 C690,144 750,164 786,179 C794,183 792,192 784,189 C745,176 690,162 632,158 Z" fill="#f4b23c"/>
<path d="M630,138 C690,144 750,164 786,179" fill="none" stroke="#d9822b" stroke-width="1.8" stroke-linecap="round"/>
<g id="eye" transform="translate(622 142)">
<circle r="7" fill="#f5d76e"/>
<circle r="4.6" fill="#1d1d1d"/>
<circle cx="1.6" cy="-1.6" r="1.5" fill="#fff"/>
</g>
</g>

<path id="nearThigh" fill="none" stroke="#f3efe6" stroke-width="22" stroke-linecap="round"/>

<g id="body">
<g id="tail">
<path d="M448,326 L406,298 L412,316 L392,316 L408,330 L394,340 L418,344 L448,350 Z"
fill="#f3efe6" stroke="#d8d2c4" stroke-width="1.2" stroke-linejoin="round"/>
</g>
<path d="M556,234 C590,254 596,312 566,350 C548,372 500,376 466,364 C436,354 418,322 428,284 C438,244 480,214 520,218 C536,220 548,226 556,234 Z"
fill="url(#featherGrad)"/>
<path d="M536,224 C500,222 462,238 440,272 C458,250 492,236 536,238 Z" fill="#e6e1d4" opacity=".9"/>
</g>

<path id="nearShin" fill="none" stroke="#f09a3c" stroke-width="9" stroke-linecap="round"/>
<g id="nearFoot"><path d="M-11,-9 C-5,-13 6,-13 13,-9 L23,-3 L20,-2 L-9,-2 L-14,-5 Z" fill="#f09a3c"/></g>

<g id="wing">
<path d="M546,252 C580,256 608,296 628,344 C638,364 648,380 650,392 C651,400 642,404 636,400 Q616,390 612,368 Q593,359 590,338 Q571,333 566,314 Q548,314 540,298 L530,290 C526,278 532,262 546,252 Z"
fill="#fbfaf5"/>
<path d="M626,374 C636,384 646,392 650,398 C647,404 638,404 632,398 C624,390 618,382 612,374 Z" fill="#2b2b2b"/>
</g>
</g>

<!-- ===== foreground verge ===== -->
<rect y="610" width="1200" height="65" fill="#e5cf9c"/>
<rect y="610" width="1200" height="3" fill="#cdb480"/>
<g id="L_fore">
<g id="foreTile">
<use href="#tuft" transform="translate(90 660) scale(1.7)" stroke="#6f8a4a"/>
<use href="#tuft" transform="translate(380 655) scale(1.5)" stroke="#6f8a4a"/>
<use href="#tuft" transform="translate(700 662) scale(1.8)" stroke="#6f8a4a"/>
<use href="#tuft" transform="translate(1010 656) scale(1.4)" stroke="#6f8a4a"/>
<g fill="#cdb480">
<ellipse cx="220" cy="640" rx="6" ry="3.5"/>
<ellipse cx="540" cy="632" rx="4" ry="2.5"/>
<ellipse cx="860" cy="645" rx="7" ry="4"/>
<ellipse cx="1130" cy="636" rx="5" ry="3"/>
</g>
</g>
<use href="#foreTile" x="-1200"/>
<use href="#foreTile" x="1200"/>
</g>
</svg>

<header class="title">
<h1>鹈鹕骑车</h1>
<p>空格键暂停,滑块调节踩踏速度</p>
</header>

<div class="hud">
<button id="toggle" type="button">暂停</button>
<label for="speed">踩踏速度</label>
<input id="speed" type="range" min="0.2" max="1.4" step="0.05" value="0.65">
</div>

<script>
(() => {
const NS = 'http://www.w3.org/2000/svg';
const W = 1200;
const $ = id => document.getElementById(id);
const TAU = Math.PI * 2;

// ---- bike & rider geometry (rider-local coordinates) ----
const G = {
bb: { x: 528, y: 505 }, crank: 28,
rWheel: 62, rRing: 21, rCog: 9,
hip: { x: 496, y: 368 }, L1: 72, L2: 88,
ankle: { x: -5, y: -10 },
};
const GEAR = G.rRing / G.rCog;

// spokes
for (const id of ['spokesR', 'spokesF']) {
const g = $(id);
for (let i = 0; i < 14; i++) {
const l = document.createElementNS(NS, 'line');
l.setAttribute('y1', '-9'); l.setAttribute('y2', '-47');
l.setAttribute('transform', `rotate(${i * 360 / 14})`);
g.appendChild(l);
}
}

// asphalt specks (deterministic pseudo-random)
{
const g = $('specks');
let s = 7;
const rnd = () => (s = (s * 16807) % 2147483647) / 2147483647;
for (let i = 0; i < 26; i++) {
const c = document.createElementNS(NS, 'circle');
c.setAttribute('cx', (rnd() * W).toFixed(1));
c.setAttribute('cy', (528 + rnd() * 70).toFixed(1));
c.setAttribute('r', (0.8 + rnd() * 1.2).toFixed(2));
g.appendChild(c);
}
}

const layers = [
['L_clouds', .04], ['L_gulls', .1], ['L_boats', .07], ['L_light', .12],
['L_waves', .2], ['L_sand', .55], ['L_road', 1], ['L_fore', 1.25],
].map(([id, k]) => ({ el: $(id), k }));

const E = {};
for (const id of ['spokesR', 'spokesF', 'chain', 'nearCrank', 'farCrank', 'nearPedal', 'farPedal',
'nearFoot', 'farFoot', 'nearThigh', 'farThigh', 'nearShin', 'farShin',
'neckHead', 'body', 'tail', 'pouch', 'eye', 'rider']) E[id] = $(id);

// two-bone IK: returns knee position, knee bends forward (+x)
function knee(hip, target, L1, L2) {
const dx = target.x - hip.x, dy = target.y - hip.y;
const d = Math.min((L1 + L2) * .985, Math.max(Math.abs(L1 - L2) + 2, Math.hypot(dx, dy)));
const a = Math.acos((L1 * L1 + d * d - L2 * L2) / (2 * L1 * d));
const ang = Math.atan2(dy, dx) - a;
return { x: hip.x + L1 * Math.cos(ang), y: hip.y + L1 * Math.sin(ang) };
}

function setLeg(side, hip, pedal) {
const ankle = { x: pedal.x + G.ankle.x, y: pedal.y + G.ankle.y };
const k = knee(hip, ankle, G.L1, G.L2);
E[side + 'Thigh'].setAttribute('d', `M${hip.x},${hip.y} L${k.x.toFixed(2)},${k.y.toFixed(2)}`);
E[side + 'Shin'].setAttribute('d', `M${k.x.toFixed(2)},${k.y.toFixed(2)} L${ankle.x.toFixed(2)},${ankle.y.toFixed(2)}`);
E[side + 'Foot'].setAttribute('transform', `translate(${pedal.x.toFixed(2)} ${pedal.y.toFixed(2)})`);
E[side + 'Pedal'].setAttribute('transform', `translate(${pedal.x.toFixed(2)} ${pedal.y.toFixed(2)})`);
E[side + 'Crank'].setAttribute('x2', pedal.x.toFixed(2));
E[side + 'Crank'].setAttribute('y2', pedal.y.toFixed(2));
}

// ---- state ----
let theta = 0; // crank angle (rad), increases clockwise = forward
let clock = 0; // animated seconds (stops while paused)
let cadence = parseFloat($('speed').value); // crank rev/s
let nextBlink = 2.2;
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
let paused = reduceMotion;

function render() {
const thW = theta * GEAR; // wheel angle
const dist = thW * G.rWheel; // ground distance travelled

for (const l of layers) {
const off = ((dist * l.k) % W + W) % W;
l.el.setAttribute('transform', `translate(${(-off).toFixed(2)} 0)`);
}

const degW = ((thW * 180 / Math.PI) % 360).toFixed(2);
E.spokesR.setAttribute('transform', `rotate(${degW})`);
E.spokesF.setAttribute('transform', `rotate(${degW})`);
E.chain.setAttribute('stroke-dashoffset', (-(theta * G.rRing) % 7).toFixed(2));

const bob = 1.5 * Math.sin(2 * theta);
const hbob = 1.4 * Math.sin(2 * theta - .7);
E.rider.setAttribute('transform', `translate(20 ${(0.8 * Math.sin(2 * theta + .3)).toFixed(2)})`);
E.body.setAttribute('transform', `translate(0 ${bob.toFixed(2)})`);
E.neckHead.setAttribute('transform', `translate(0 ${hbob.toFixed(2)})`);
E.tail.setAttribute('transform', `rotate(${(2.5 * Math.sin(2 * theta + 1)).toFixed(2)} 448 340)`);
E.pouch.setAttribute('transform', `rotate(${(1.6 * Math.sin(2 * theta + .9)).toFixed(2)} 622 166)`);

const hip = { x: G.hip.x, y: G.hip.y + bob };
const near = { x: G.bb.x + G.crank * Math.cos(theta), y: G.bb.y + G.crank * Math.sin(theta) };
const far = { x: G.bb.x - G.crank * Math.cos(theta), y: G.bb.y - G.crank * Math.sin(theta) };
setLeg('near', hip, near);
setLeg('far', hip, far);

// blink
let k = 1;
if (clock > nextBlink) {
const p = (clock - nextBlink) / .16;
if (p < 1) k = 1 - .92 * Math.sin(Math.PI * p);
else nextBlink = clock + 2.4 + Math.random() * 3;
}
E.eye.setAttribute('transform', `translate(622 142) scale(1 ${k.toFixed(3)})`);
}

let last = null;
function frame(now) {
if (last === null) last = now;
const dt = Math.min(.05, (now - last) / 1000);
last = now;
if (!paused) {
theta += TAU * cadence * dt;
clock += dt;
}
render();
requestAnimationFrame(frame);
}

// ---- controls ----
const svg = $('scene');
const btn = $('toggle');
function applyPaused() {
btn.textContent = paused ? '继续' : '暂停';
btn.setAttribute('aria-pressed', String(paused));
paused ? svg.pauseAnimations() : svg.unpauseAnimations();
}
btn.addEventListener('click', () => { paused = !paused; applyPaused(); });
addEventListener('keydown', e => {
if (e.code === 'Space' && e.target.tagName !== 'INPUT') { e.preventDefault(); paused = !paused; applyPaused(); }
});
$('speed').addEventListener('input', e => { cadence = parseFloat(e.target.value); });

// landscape: fill the viewport and crop the edges; portrait: show the whole
// rider in a narrower window anchored to the bottom (the page background
// continues the top of the sky gradient).
function fitViewport() {
const portrait = innerWidth / innerHeight < 1.2;
svg.setAttribute('viewBox', portrait ? '320 0 560 675' : '0 0 1200 675');
svg.setAttribute('preserveAspectRatio', portrait ? 'xMidYMax meet' : 'xMidYMid slice');
}
addEventListener('resize', fitViewport);
fitViewport();

applyPaused();
render();
requestAnimationFrame(frame);

// small hook for tinkering from the console
window.pelican = { setTheta: v => { theta = v; render(); }, setCadence: v => { cadence = v; } };
})();
</script>
</body>
</html>
最新回复 (9)
  • Shern Hung 09-02 02:58
    1

    看来这个东西已经进训练集了,以后测试没什么用了

  • ZackWill 楼主 09-02 03:01
    2

    是的,以他的知识库已经能意识到这是一个测试题了

  • IssunmiHaichi 09-02 03:03
    3

    已经没用了这个提示词,被特化了说是,针对测试集来训练。。。


    细看效果还是挺好的,该有的都有。。。

  • event 09-02 03:04
    4

    可以说在众多鹈鹕中测试名列前茅,感觉不赖

  • ZackWill 楼主 09-02 03:04
    5

    效果是不错,但你很难说这是不是做了特化训练的 ^-^ 也没法去证明

  • ZackWill 楼主 09-02 03:06
    6

    是这样的,抛开其他因素单看做的怎么样还是很不错的

  • helloergou 09-02 03:16
    7

    这鸟模型到底能干啥 我写的项目动不动就给我切 4.8 去了。

  • Featux 09-02 03:19
    8

    为啥现在测试大模型都用这个鹈鹕骑自行车?

  • undercat 09-02 03:35
    9

    换成其他场景的svg什么的试试,比如舞台上小狗撒尿啥的,反正重点就是测试svg生成的咋样,细节方面等等

* 帖子来源Linux.do
返回