分享图
动画工坊
引擎就绪
<!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分