独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>高精度义齿微型燕尾导轨与弹片卡扣结构 (TRIZ IFR)</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Noto+Sans+SC:wght@300;500;700&display=swap');
:root {
--bg-color: #030712;
--grid-color: #111827;
--base-fill: #1e293b;
--base-stroke: #334155;
--tooth-fill: #f8fafc;
--tooth-shadow: #cbd5e1;
--highlight-amber: #fbbf24;
--highlight-cyan: #22d3ee;
--force-magenta: #f43f5e;
--text-main: #e2e8f0;
--text-muted: #94a3b8;
--hud-bg: rgba(15, 23, 42, 0.75);
--hud-border: #334155;
}
body {
margin: 0;
padding: 0;
background-color: var(--bg-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: 'Noto Sans SC', system-ui, sans-serif;
overflow: hidden;
color: var(--text-main);
}
.animation-container {
width: 100%;
max-width: 1400px;
aspect-ratio: 16 / 9;
box-shadow: 0 0 50px rgba(0, 0, 0, 0.8);
position: relative;
background: radial-gradient(circle at center, #0f172a 0%, #020617 100%);
border: 1px solid var(--grid-color);
}
svg {
width: 100%;
height: 100%;
display: block;
}
/* typography within SVG */
text {
fill: var(--text-main);
font-family: 'Noto Sans SC', sans-serif;
}
.tech-font {
font-family: 'Orbitron', monospace;
}
.title {
font-size: 28px;
font-weight: 700;
fill: #ffffff;
letter-spacing: 2px;
}
.subtitle {
font-size: 16px;
fill: var(--highlight-cyan);
font-weight: 500;
}
.hud-text {
font-size: 14px;
fill: var(--text-muted);
}
.dimension-text {
font-size: 14px;
fill: var(--highlight-amber);
font-family: 'Orbitron', monospace;
font-weight: 700;
}
.force-text {
font-size: 16px;
fill: var(--force-magenta);
font-weight: 700;
}
/* SVG Element Styles */
.tooth-body {
fill: url(#toothGradient);
stroke: var(--tooth-shadow);
stroke-width: 2;
}
.base-body {
fill: url(#baseGradient);
stroke: var(--base-stroke);
stroke-width: 2;
}
.dovetail-glow {
fill: none;
stroke: var(--highlight-amber);
stroke-width: 4;
filter: url(#glowAmber);
opacity: 0; /* Animated */
}
.spring-clip {
fill: none;
stroke: var(--highlight-cyan);
stroke-width: 5;
stroke-linecap: round;
filter: url(#glowCyan);
transform-origin: 550px 310px;
}
.dental-pin {
fill: #94a3b8;
stroke: #cbd5e1;
stroke-width: 1;
}
.chewing-force {
fill: var(--force-magenta);
opacity: 0; /* Animated */
filter: url(#glowMagenta);
}
/* Dynamic HUD */
.status-panel {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
background: var(--hud-bg);
border: 1px solid var(--highlight-cyan);
padding: 15px 30px;
border-radius: 8px;
backdrop-filter: blur(10px);
display: flex;
align-items: center;
gap: 20px;
box-shadow: 0 0 20px rgba(34, 211, 238, 0.2);
}
.status-indicator {
width: 12px;
height: 12px;
border-radius: 50%;
background-color: var(--highlight-cyan);
box-shadow: 0 0 10px var(--highlight-cyan);
animation: pulse 1.5s infinite;
}
.status-text {
font-size: 18px;
font-weight: 700;
color: var(--highlight-cyan);
font-family: 'Orbitron', 'Noto Sans SC', sans-serif;
min-width: 250px;
}
@keyframes pulse {
0% { opacity: 0.5; transform: scale(0.8); }
50% { opacity: 1; transform: scale(1.2); }
100% { opacity: 0.5; transform: scale(0.8); }
}
/* Informational HUDs */
.info-box {
position: absolute;
background: var(--hud-bg);
border: 1px solid var(--hud-border);
padding: 15px;
border-radius: 6px;
backdrop-filter: blur(5px);
border-left: 4px solid var(--highlight-amber);
max-width: 250px;
}
.info-box.triz {
top: 100px;
right: 40px;
border-left-color: var(--highlight-cyan);
}
.info-box h3 {
margin: 0 0 10px 0;
font-size: 14px;
color: #fff;
}
.info-box p, .info-box ul {
margin: 0;
padding: 0;
font-size: 12px;
color: var(--text-muted);
line-height: 1.6;
}
.info-box ul {
padding-left: 15px;
margin-top: 5px;
}
</style>
</head>
<body>
<div class="animation-container">
<!-- Overlay HTML UI -->
<div class="status-panel">
<div class="status-indicator" id="ui-indicator"></div>
<div class="status-text" id="ui-status-text">系统初始化中...</div>
</div>
<div class="info-box triz">
<h3>TRIZ IFR: 最终理想解</h3>
<p>巧妙利用系统现有资源,在不引入复杂辅助结构的前提下解决“稳固咬合”与“无损拆卸”的物理矛盾。</p>
<ul>
<li><strong>资源利用:</strong> 利用义齿自身形态切割出燕尾导轨。</li>
<li><strong>失效边界:</strong> 需微米级高精度加工,公差过大将导致滑槽磨损松动。</li>
</ul>
</div>
<!-- Main SVG Animation Canvas -->
<svg viewBox="0 0 1200 700" preserveAspectRatio="xMidYMid meet" id="main-svg">
<defs>
<!-- Background Grid -->
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" fill="none" stroke="rgba(255,255,255,0.03)" stroke-width="1"/>
</pattern>
<pattern id="grid-large" width="200" height="200" patternUnits="userSpaceOnUse">
<rect width="200" height="200" fill="url(#grid)" />
<path d="M 200 0 L 0 0 0 200" fill="none" stroke="rgba(255,255,255,0.08)" stroke-width="2"/>
</pattern>
<!-- Gradients -->
<linearGradient id="baseGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#334155" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<linearGradient id="toothGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ffffff" />
<stop offset="50%" stop-color="#e2e8f0" />
<stop offset="100%" stop-color="#94a3b8" />
</linearGradient>
<!-- Glow Filters -->
<filter id="glowAmber" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glowCyan" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glowMagenta" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="5" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- Arrow Marker -->
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="var(--highlight-amber)" />
</marker>
</defs>
<!-- Grid Background -->
<rect width="100%" height="100%" fill="url(#grid-large)" />
<!-- Titles -->
<text x="40" y="50" class="title">高精度义齿微型燕尾导轨与弹片卡扣</text>
<text x="40" y="80" class="subtitle">HIGH-PRECISION DENTURE MICRO-DOVETAIL & SPRING CLIP STRUCTURE</text>
<!-- LEFT PANEL: Front Cross Section (Dovetail Profile) -->
<g id="front-view" transform="translate(40, 100)">
<!-- Base / Receptacle -->
<!-- Base start 50, top 250, bottom 450, right 350. Root left 176, right 224 at Y=250. Flares to 160, 240 at Y=310. -->
<path class="base-body" d="M 50 250 L 176 250 L 160 310 L 240 310 L 224 250 L 350 250 L 350 450 L 50 450 Z" />
<!-- Glowing Interface Lines (Activated during chewing) -->
<path id="front-glow-left" class="dovetail-glow" d="M 176 250 L 160 310 L 200 310" />
<path id="front-glow-right" class="dovetail-glow" d="M 224 250 L 240 310 L 200 310" />
<!-- Tooth -->
<g id="tooth-front">
<!-- Crown & Root combined -->
<path class="tooth-body" d="M 150 120 C 130 30, 270 30, 250 120 C 250 190, 230 240, 224 250 L 240 310 L 160 310 L 176 250 C 170 240, 150 190, 150 120 Z" />
</g>
<!-- Front View Dimensions & Labels -->
<text x="50" y="40" class="tech-font" fill="#fff" font-size="18">01.</text>
<text x="80" y="40" class="subtitle" fill="#fff">横截面剖视图 / 燕尾构型</text>
<!-- Bottom width 2.0mm -->
<line x1="160" y1="330" x2="240" y2="330" stroke="var(--highlight-amber)" stroke-width="2" marker-start="url(#arrow)" marker-end="url(#arrow)" />
<text x="200" y="350" text-anchor="middle" class="dimension-text">槽底宽 2.0mm</text>
<!-- 15 Degree Angle -->
<path d="M 176 250 A 40 40 0 0 0 166 280" fill="none" stroke="var(--highlight-amber)" stroke-width="1.5" stroke-dasharray="3,3" />
<line x1="176" y1="250" x2="176" y2="310" stroke="var(--highlight-amber)" stroke-width="1" stroke-dasharray="2,2" />
<text x="120" y="285" class="dimension-text">15° 内倾角</text>
<!-- Front View Chewing Forces (Hidden initially) -->
<g class="chewing-force" id="force-front">
<path d="M 200 10 L 200 50 L 190 50 L 200 70 L 210 50 L 200 50" /> <!-- Vertical -->
<path d="M 90 120 L 130 120 L 130 110 L 150 120 L 130 130 L 130 120" /> <!-- Lateral -->
</g>
</g>
<!-- RIGHT PANEL: Side Cross Section (Slide & Lock) -->
<g id="side-view" transform="translate(450, 100)">
<!-- Base -->
<!-- Base 0 to 650. Y=250 to 450. Tunnel at Y=285-295 from 0 to 100. Slot at Y=250-310 from 100 to 650. -->
<path class="base-body" d="M 0 250 L 100 250 L 100 310 L 650 310 L 650 450 L 0 450 L 0 295 L 100 295 L 100 285 L 0 285 Z" />
<!-- Dental Pin Tool (Starts off-screen left, inside the tunnel) -->
<!-- X starts at 0, goes to 100. Width 100. So initial is -100 to 0. Let's place it at -80 to 20. -->
<rect class="dental-pin" id="dental-pin" x="-80" y="286" width="170" height="8" rx="4" />
<text x="0" y="275" class="hud-text">微孔与专用牙科顶针</text>
<!-- Spring Clip -->
<g id="spring-group">
<path class="spring-clip" d="M 100 310 L 125 290" />
</g>
<text x="80" y="340" class="hud-text" fill="var(--highlight-cyan)">钛合金微型簧片</text>
<!-- Glowing interface for lock -->
<path id="side-glow" class="dovetail-glow" d="M 100 310 L 120 310 L 120 290" />
<!-- Tooth Side View (Animated sliding container) -->
<g id="tooth-side">
<!-- Crown -->
<path class="tooth-body" d="M 100 250 C 80 150, 150 70, 200 70 C 250 70, 320 150, 300 250 Z" />
<!-- Root -->
<!-- Notch left edge at 100. Depth down to 310. Width 25. -->
<path class="tooth-body" d="M 100 250 L 100 290 L 125 290 L 125 310 L 300 310 L 300 250 Z" />
<!-- Text moving with tooth -->
<text x="180" y="160" text-anchor="middle" class="tech-font" fill="var(--base-stroke)">单颗义齿</text>
<text x="110" y="305" font-size="10" fill="var(--text-muted)">限位凹坑</text>
</g>
<!-- Side View Dimensions & Labels -->
<text x="0" y="40" class="tech-font" fill="#fff" font-size="18">02.</text>
<text x="30" y="40" class="subtitle" fill="#fff">纵向滑轨剖视图 / 弹片卡扣锁死时序</text>
<!-- Floating text for click -->
<text id="click-text" x="140" y="280" class="force-text" opacity="0">咔哒!</text>
<text id="unlock-text" x="140" y="280" class="force-text" fill="var(--highlight-cyan)" opacity="0">3.0N 解锁按压</text>
<!-- Side View Chewing Force -->
<g class="chewing-force" id="force-side">
<path d="M 200 10 L 200 50 L 190 50 L 200 70 L 210 50 L 200 50" />
</g>
<text id="force-label" x="230" y="40" class="force-text" opacity="0">抵御垂直与侧向咀嚼力</text>
</g>
</svg>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const uiStatusText = document.getElementById('ui-status-text');
const uiIndicator = document.getElementById('ui-indicator');
const pin = document.getElementById('dental-pin');
const spring = document.getElementById('spring-group');
const toothSide = document.getElementById('tooth-side');
const forceFront = document.getElementById('force-front');
const forceSide = document.getElementById('force-side');
const forceLabel = document.getElementById('force-label');
const frontGlowL = document.getElementById('front-glow-left');
const frontGlowR = document.getElementById('front-glow-right');
const sideGlow = document.getElementById('side-glow');
const clickText = document.getElementById('click-text');
const unlockText = document.getElementById('unlock-text');
const sleep = ms => new Promise(res => setTimeout(res, ms));
// Helper for Web Animations API to guarantee state
async function animateTo(el, keyframes, duration, easing = 'ease-in-out') {
const anim = el.animate(keyframes, { duration, easing, fill: 'forwards' });
await anim.finished;
// Apply final state permanently to avoid stacking issues
const finalFrame = keyframes[keyframes.length - 1];
if(finalFrame.transform) el.style.transform = finalFrame.transform;
if(finalFrame.opacity !== undefined) el.style.opacity = finalFrame.opacity;
anim.commitStyles();
}
function updateUI(text, color) {
uiStatusText.textContent = text;
uiStatusText.style.color = color;
uiIndicator.style.backgroundColor = color;
uiIndicator.style.boxShadow = `0 0 10px ${color}`;
}
async function flashText(el) {
el.animate([
{ opacity: 0, transform: 'translateY(10px) scale(0.9)' },
{ opacity: 1, transform: 'translateY(0px) scale(1.1)', offset: 0.2 },
{ opacity: 1, transform: 'translateY(0px) scale(1)', offset: 0.8 },
{ opacity: 0, transform: 'translateY(-10px) scale(0.9)' }
], { duration: 1500, easing: 'ease-out' });
}
async function simulateChewing() {
updateUI("工作状态:轴向锁死,抵御多向咀嚼力", "var(--highlight-amber)");
const showForce = [ {opacity: 0}, {opacity: 1} ];
const hideForce = [ {opacity: 1}, {opacity: 0} ];
const duration = 500;
forceFront.animate(showForce, {duration, fill: 'forwards'});
forceSide.animate(showForce, {duration, fill: 'forwards'});
forceLabel.animate(showForce, {duration, fill: 'forwards'});
frontGlowL.animate(showForce, {duration, fill: 'forwards'});
frontGlowR.animate(showForce, {duration, fill: 'forwards'});
sideGlow.animate(showForce, {duration, fill: 'forwards'});
// Subtle shake
toothSide.animate([
{transform: 'translateX(0) translateY(0)'},
{transform: 'translateX(0) translateY(1px)'},
{transform: 'translateX(0) translateY(0)'}
], {duration: 200, iterations: 5});
await sleep(2000);
forceFront.animate(hideForce, {duration, fill: 'forwards'});
forceSide.animate(hideForce, {duration, fill: 'forwards'});
forceLabel.animate(hideForce, {duration, fill: 'forwards'});
frontGlowL.animate(hideForce, {duration, fill: 'forwards'});
frontGlowR.animate(hideForce, {duration, fill: 'forwards'});
sideGlow.animate(hideForce, {duration, fill: 'forwards'});
}
async function runAnimationLoop() {
// Ensure initial state
pin.style.transform = 'translateX(0)';
spring.style.transform = 'rotate(0deg)';
toothSide.style.transform = 'translateX(0)';
toothSide.style.opacity = '1';
while(true) {
// Stage 1: Locked & Chewing
await simulateChewing();
await sleep(1000);
// Stage 2: Unlock
updateUI("解锁:专用顶针压下钛合金簧片", "var(--highlight-cyan)");
await animateTo(pin, [{transform: 'translateX(0)'}, {transform: 'translateX(75px)'}], 600);
flashText(unlockText);
await animateTo(spring, [{transform: 'rotate(0deg)'}, {transform: 'rotate(35deg)'}], 300);
await sleep(600);
// Stage 3: Remove
updateUI("拆卸:向侧向平推滑出损坏义齿", "var(--text-muted)");
await animateTo(toothSide, [
{transform: 'translateX(0)', opacity: 1},
{transform: 'translateX(350px)', opacity: 0}
], 1200);
await sleep(800);
// Stage 4: Insert New
updateUI("换装:新义齿沿燕尾滑轨水平滑入", "#fff");
await animateTo(toothSide, [
{transform: 'translateX(350px)', opacity: 0},
{transform: 'translateX(0px)', opacity: 1}
], 1200);
// Stage 5: Lock
updateUI("锁死:抽出顶针,簧片复位卡入凹坑", "var(--force-magenta)");
animateTo(pin, [{transform: 'translateX(75px)'}, {transform: 'translateX(0)'}], 600);
await animateTo(spring, [{transform: 'rotate(35deg)'}, {transform: 'rotate(0deg)'}], 300, 'cubic-bezier(0.175, 0.885, 0.32, 1.275)'); // Bouncy spring
flashText(clickText);
await sleep(1500);
}
}
// Start auto-play loop
runAnimationLoop();
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
