前端融球效果原理讲解+具体实现+模糊度,对比度基础教学

发布于:2025-05-25 ⋅ 阅读:(16) ⋅ 点赞:(0)

这是github链接,文末也有本人封装好的融球效果+讲解页面完整代码:

sq/UI/src/components/MetaballEffect at main · afigzb/sq (github.com)https://github.com/afigzb/sq/tree/main/UI/src/components/MetaballEffect讲解部分看这个静态页面截图即可:

融球组件代码:

/**
 * 融球效果 Web Component
 * 为容器内的元素提供融球效果,支持任意HTML内容
 */
class MetaballContainer extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.blurIntensity = 10;
        this.contrastLevel = 20;
        this.init();
    }

    init() {
        this.shadowRoot.innerHTML = `
            <style>
                :host {
                    display: block;
                    position: relative;
                    /* 核心:高对比度滤镜实现融球效果 */
                    filter: contrast(${this.contrastLevel}) blur(0.5px);
                    background: inherit;
                }

                ::slotted(*) {
                    /* 核心:为所有插槽内容添加模糊效果 */
                    filter: blur(${this.blurIntensity}px) !important;
                }

                .container {
                    width: 100%;
                    height: 100%;
                    position: relative;
                }
            </style>
            <div class="container">
                <slot></slot>
            </div>
        `;
    }

    /**
     * 设置模糊强度
     * @param {number} intensity - 模糊强度 (2-15)
     */
    setBlur(intensity) {
        this.blurIntensity = intensity;
        this.updateStyles();
    }

    /**
     * 设置对比度
     * @param {number} level - 对比度级别 (10-40)
     */
    setContrast(level) {
        this.contrastLevel = level;
        this.updateStyles();
    }

    /**
     * 更新样式
     * @private
     */
    updateStyles() {
        const style = this.shadowRoot.querySelector('style');
        style.textContent = `
            :host {
                display: block;
                position: relative;
                filter: contrast(${this.contrastLevel}) blur(0.5px);
                background: inherit;
            }

            ::slotted(*) {
                filter: blur(${this.blurIntensity}px) !important;
            }

            .container {
                width: 100%;
                height: 100%;
                position: relative;
            }
        `;
    }

    /**
     * 获取所有子元素
     * @returns {Array} 子元素数组
     */
    getItems() {
        return Array.from(this.children);
    }

    /**
     * 获取当前模糊强度
     * @returns {number} 当前模糊强度
     */
    getBlur() {
        return this.blurIntensity;
    }

    /**
     * 获取当前对比度
     * @returns {number} 当前对比度
     */
    getContrast() {
        return this.contrastLevel;
    }
}

// 注册Web Component
customElements.define('metaball-container', MetaballContainer);

// 导出组件
export default MetaballContainer;

融球组件示例页面代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>融球控件 - Web Component</title>
    <style>
        body {
            margin: 0;
            padding: 20px;
            background: #1a1a1a;
            font-family: Arial, sans-serif;
            color: white;
        }

        .demo-container {
            position: relative;
            width: 100vw;
            height: 80vh;
            background: #000;
            border-radius: 10px;
            overflow: hidden;
        }

        .demo-item {
            position: absolute;
            transition: all 0.1s ease;
        }

        .ball {
            width: 80px;
            height: 80px;
            border-radius: 50%;
            background: #ff6b6b;
        }

        .square {
            width: 60px;
            height: 60px;
            background: #4ecdc4;
        }

        .triangle {
            width: 0;
            height: 0;
            border-left: 30px solid transparent;
            border-right: 30px solid transparent;
            border-bottom: 52px solid #ffe66d;
        }

        .text-item {
            font-size: 24px;
            font-weight: bold;
            color: #a8e6cf;
            padding: 10px 20px;
            background: #a8e6cf;
            border-radius: 20px;
        }

        .controls {
            margin-bottom: 20px;
            display: flex;
            gap: 10px;
            align-items: center;
        }

        button {
            padding: 8px 16px;
            background: #4ecdc4;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }

        button:hover {
            background: #45b7aa;
        }

        .info {
            margin-bottom: 20px;
            padding: 15px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 8px;
        }
    </style>
</head>
<body>
    <div class="info">
        <h2>融球控件 (Metaball Component)</h2>
        <p>这是一个Web Component封装的融球控件,可以为任何插入的元素提供融球效果。</p>
        <p>控件只负责融球效果,元素的移动由外部控制。</p>
    </div>

    <div class="controls">
        <button onclick="toggleAnimation()">开始/停止动画</button>
        <button onclick="resetPositions()">重置位置</button>
        <label>
            模糊强度: 
            <input type="range" id="blurSlider" min="2" max="15" value="8" 
                   onchange="updateBlur(this.value)">
            <span id="blurValue">8</span>px
        </label>
        <label>
            对比度: 
            <input type="range" id="contrastSlider" min="10" max="40" value="20" 
                   onchange="updateContrast(this.value)">
            <span id="contrastValue">20</span>
        </label>
    </div>

    <!-- 使用融球控件 -->
    <metaball-container class="demo-container">
        <div class="demo-item ball" style="left: 100px; top: 100px;"></div>
        <div class="demo-item square" style="left: 300px; top: 200px;"></div>
        <div class="demo-item triangle" style="left: 500px; top: 150px;"></div>
        <div class="demo-item text-item" style="left: 200px; top: 300px;">TEXT</div>
    </metaball-container>

    <script type="module">
        // 导入融球控件
        import MetaballContainer from './MetaballEffect.js';

        // 演示动画控制
        let animationId = null;
        let isAnimating = false;
        const items = [];

        // 初始化演示项目
        function initDemo() {
            const container = document.querySelector('metaball-container');
            const demoItems = container.querySelectorAll('.demo-item');
            
            demoItems.forEach((item, index) => {
                const rect = item.getBoundingClientRect();
                const containerRect = container.getBoundingClientRect();
                
                items.push({
                    element: item,
                    x: parseFloat(item.style.left) || 0,
                    y: parseFloat(item.style.top) || 0,
                    vx: (Math.random() - 0.5) * 2,
                    vy: (Math.random() - 0.5) * 2,
                    width: item.offsetWidth,
                    height: item.offsetHeight
                });
            });
        }

        // 动画循环
        function animate() {
            if (!isAnimating) return;

            const container = document.querySelector('metaball-container');
            const containerRect = container.getBoundingClientRect();

            items.forEach(item => {
                // 更新位置
                item.x += item.vx;
                item.y += item.vy;

                // 边界检测
                if (item.x <= 0 || item.x >= containerRect.width - item.width) {
                    item.vx *= -1;
                    item.x = Math.max(0, Math.min(containerRect.width - item.width, item.x));
                }
                if (item.y <= 0 || item.y >= containerRect.height - item.height) {
                    item.vy *= -1;
                    item.y = Math.max(0, Math.min(containerRect.height - item.height, item.y));
                }

                // 应用位置
                item.element.style.left = `${item.x}px`;
                item.element.style.top = `${item.y}px`;
            });

            animationId = requestAnimationFrame(animate);
        }

        // 控制函数
        window.toggleAnimation = function() {
            isAnimating = !isAnimating;
            if (isAnimating) {
                animate();
            } else {
                cancelAnimationFrame(animationId);
            }
        };

        window.resetPositions = function() {
            items.forEach(item => {
                item.x = Math.random() * 400;
                item.y = Math.random() * 300;
                item.vx = (Math.random() - 0.5) * 2;
                item.vy = (Math.random() - 0.5) * 2;
                item.element.style.left = `${item.x}px`;
                item.element.style.top = `${item.y}px`;
            });
        };

        window.updateBlur = function(value) {
            const container = document.querySelector('metaball-container');
            container.setBlur(value);
            document.getElementById('blurValue').textContent = value;
        };

        window.updateContrast = function(value) {
            const container = document.querySelector('metaball-container');
            container.setContrast(value);
            document.getElementById('contrastValue').textContent = value;
        };

        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            // 等待Web Component注册完成
            setTimeout(() => {
                initDemo();
            }, 100);
        });

        // 鼠标交互演示
        document.addEventListener('mousemove', (e) => {
            if (!isAnimating) return;
            
            const container = document.querySelector('metaball-container');
            const rect = container.getBoundingClientRect();
            const mouseX = e.clientX - rect.left;
            const mouseY = e.clientY - rect.top;

            // 鼠标吸引效果
            items.forEach(item => {
                const dx = mouseX - (item.x + item.width / 2);
                const dy = mouseY - (item.y + item.height / 2);
                const distance = Math.sqrt(dx * dx + dy * dy);
                
                if (distance < 150) {
                    const force = (150 - distance) / 150 * 0.01;
                    item.vx += dx / distance * force;
                    item.vy += dy / distance * force;
                }
            });
        });
    </script>
</body>
</html>

 这是文首的讲解页面代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>融球效果原理讲解</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: #333;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            overflow: hidden;
        }

        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 40px;
            text-align: center;
        }

        .header h1 {
            font-size: 2.5em;
            margin-bottom: 10px;
        }

        .header p {
            font-size: 1.2em;
            opacity: 0.9;
        }

        .content {
            padding: 40px;
        }

        .section {
            margin-bottom: 50px;
        }

        .section h2 {
            color: #667eea;
            font-size: 1.8em;
            margin-bottom: 20px;
            border-bottom: 3px solid #667eea;
            padding-bottom: 10px;
        }

        .demo-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 30px;
            margin: 30px 0;
        }

        .demo-box {
            background: #f8f9fa;
            border-radius: 15px;
            padding: 20px;
            border: 2px solid #e9ecef;
            transition: all 0.3s ease;
        }

        .demo-box:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0,0,0,0.1);
        }

        .demo-box h3 {
            color: #495057;
            margin-bottom: 15px;
            font-size: 1.3em;
        }

        .demo-area {
            width: 100%;
            height: 200px;
            background: #000;
            border-radius: 10px;
            position: relative;
            overflow: hidden;
            margin: 15px 0;
        }

        .ball {
            position: absolute;
            width: 60px;
            height: 60px;
            background: #fff;
            border-radius: 50%;
        }

        .ball-1 { left: 50px; top: 70px; }
        .ball-2 { left: 100px; top: 70px; }

        /* 四种状态演示 */
        .state-1 .demo-area {
            /* 无模糊,无对比度 */
        }

        .state-2 .demo-area {
            /* 只有模糊,无对比度 */
        }
        .state-2 .ball {
            filter: blur(10px);
        }

        .state-3 .demo-area {
            /* 无模糊,只有对比度 */
            filter: contrast(20);
        }

        .state-4 .demo-area {
            /* 融球效果:容器对比度 + 元素模糊 */
            filter: contrast(20) blur(0.5px);
        }
        .state-4 .ball {
            filter: blur(10px);
        }

        .interactive-demo {
            background: #f8f9fa;
            border-radius: 15px;
            padding: 30px;
            margin: 30px 0;
        }

        .controls {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
            margin-bottom: 20px;
            align-items: center;
        }

        .control-group {
            display: flex;
            flex-direction: column;
            gap: 5px;
        }

        .control-group label {
            font-weight: 600;
            color: #495057;
        }

        .control-group input[type="range"] {
            width: 200px;
            height: 6px;
            border-radius: 3px;
            background: #ddd;
            outline: none;
            -webkit-appearance: none;
        }

        .control-group input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background: #667eea;
            cursor: pointer;
        }

        .value-display {
            font-weight: bold;
            color: #667eea;
        }

        .interactive-area {
            width: 100%;
            height: 300px;
            background: #000;
            border-radius: 10px;
            position: relative;
            overflow: hidden;
        }

        .movable-ball {
            position: absolute;
            width: 80px;
            height: 80px;
            background: #fff;
            border-radius: 50%;
            transition: all 0.1s ease;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            color: #333;
        }

        .ball-a { left: 100px; top: 110px; background: #ff6b6b; }
        .ball-b { left: 200px; top: 110px; background: #4ecdc4; }

        .explanation {
            background: #e3f2fd;
            border-left: 4px solid #2196f3;
            padding: 20px;
            margin: 20px 0;
            border-radius: 0 10px 10px 0;
        }

        .explanation h4 {
            color: #1976d2;
            margin-bottom: 10px;
        }

        .code-block {
            background: #2d3748;
            color: #e2e8f0;
            padding: 20px;
            border-radius: 10px;
            font-family: 'Courier New', monospace;
            margin: 20px 0;
            overflow-x: auto;
            font-size: 14px;
            line-height: 1.5;
        }

        .code-block .comment {
            color: #68d391;
        }

        .code-block .property {
            color: #63b3ed;
        }

        .code-block .value {
            color: #fbb6ce;
        }

        .highlight {
            background: #ffd54f;
            padding: 2px 4px;
            border-radius: 3px;
            color: #333;
        }

        .principle-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
            margin: 30px 0;
        }

        .principle-card {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 25px;
            border-radius: 15px;
            text-align: center;
        }

        .principle-card h4 {
            font-size: 1.3em;
            margin-bottom: 15px;
        }

        .principle-card .icon {
            font-size: 3em;
            margin-bottom: 15px;
            opacity: 0.8;
        }

        .warning {
            background: #fff3cd;
            border: 1px solid #ffeaa7;
            border-radius: 8px;
            padding: 15px;
            margin: 20px 0;
            color: #856404;
        }

        .warning strong {
            color: #d63031;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🌊 融球效果原理讲解</h1>
            <p>深入理解容器对比度 + 元素模糊如何创造神奇的融球效果</p>
        </div>

        <div class="content">
            <!-- 原理概述 -->
            <div class="section">
                <h2>🎯 核心原理</h2>
                <p>融球效果(Metaball Effect)的实现原理是:<span class="highlight">容器应用高对比度滤镜</span> + <span class="highlight">元素应用模糊滤镜</span>。当模糊的元素靠近时,它们的边缘会在高对比度的作用下自然融合。</p>
                
                <div class="warning">
                    <strong>重要:</strong>很多人误以为是同时对元素应用模糊和对比度,实际上正确的做法是分层应用 - 容器负责对比度,元素负责模糊!
                </div>
                
                <div class="principle-grid">
                    <div class="principle-card">
                        <div class="icon">📦</div>
                        <h4>容器对比度</h4>
                        <p>容器应用高对比度滤镜,将灰色区域转换为黑白分明的边界</p>
                    </div>
                    <div class="principle-card">
                        <div class="icon">🌫️</div>
                        <h4>元素模糊</h4>
                        <p>每个元素应用模糊滤镜,创造柔和的渐变边缘</p>
                    </div>
                    <div class="principle-card">
                        <div class="icon">🔗</div>
                        <h4>融合效果</h4>
                        <p>模糊元素的重叠区域经过容器对比度处理后形成连接</p>
                    </div>
                </div>
            </div>

            <!-- 四种状态对比 -->
            <div class="section">
                <h2>📚 四种状态对比演示</h2>
                <p>让我们通过四种不同的状态来理解融球效果的形成过程:</p>

                <div class="demo-grid">
                    <div class="demo-box state-1">
                        <h3>状态 1: 无模糊 + 无对比度</h3>
                        <div class="demo-area">
                            <div class="ball ball-1"></div>
                            <div class="ball ball-2"></div>
                        </div>
                        <div class="code-block">
<span class="comment">/* 容器 */</span>
.<span class="property">container</span> {
    <span class="comment">/* 无滤镜 */</span>
}

<span class="comment">/* 元素 */</span>
.<span class="property">ball</span> {
    <span class="comment">/* 无滤镜 */</span>
}
                        </div>
                        <p>两个清晰的圆球,边界分明,无任何效果。</p>
                    </div>

                    <div class="demo-box state-2">
                        <h3>状态 2: 有模糊 + 无对比度</h3>
                        <div class="demo-area">
                            <div class="ball ball-1"></div>
                            <div class="ball ball-2"></div>
                        </div>
                        <div class="code-block">
<span class="comment">/* 容器 */</span>
.<span class="property">container</span> {
    <span class="comment">/* 无滤镜 */</span>
}

<span class="comment">/* 元素 */</span>
.<span class="property">ball</span> {
    <span class="property">filter</span>: <span class="value">blur(10px)</span>;
}
                        </div>
                        <p>球体变模糊,但没有融合效果,只是单纯的模糊。</p>
                    </div>

                    <div class="demo-box state-3">
                        <h3>状态 3: 无模糊 + 有对比度</h3>
                        <div class="demo-area">
                            <div class="ball ball-1"></div>
                            <div class="ball ball-2"></div>
                        </div>
                        <div class="code-block">
<span class="comment">/* 容器 */</span>
.<span class="property">container</span> {
    <span class="property">filter</span>: <span class="value">contrast(20)</span>;
}

<span class="comment">/* 元素 */</span>
.<span class="property">ball</span> {
    <span class="comment">/* 无滤镜 */</span>
}
                        </div>
                        <p>边界更加锐利,但仍然没有融合效果。</p>
                    </div>

                    <div class="demo-box state-4">
                        <h3>状态 4: 有模糊 + 有对比度</h3>
                        <div class="demo-area">
                            <div class="ball ball-1"></div>
                            <div class="ball ball-2"></div>
                        </div>
                        <div class="code-block">
<span class="comment">/* 容器 */</span>
.<span class="property">container</span> {
    <span class="property">filter</span>: <span class="value">contrast(20) blur(0.5px)</span>;
}

<span class="comment">/* 元素 */</span>
.<span class="property">ball</span> {
    <span class="property">filter</span>: <span class="value">blur(10px)</span>;
}
                        </div>
                        <p>🎉 完美的融球效果!模糊的边缘在高对比度下形成自然连接。</p>
                    </div>
                </div>
            </div>

            <!-- 技术原理详解 -->
            <div class="section">
                <h2>🔬 技术原理详解</h2>
                
                <!-- 基础概念讲解 -->
                <div class="section">
                    <h3>📖 基础概念:什么是模糊和对比度?</h3>
                    
                    <div class="explanation">
                        <h4>🌫️ 什么是"模糊"?</h4>
                        <p>想象一下你摘掉眼镜看东西,或者相机没有对焦时的效果 - 这就是模糊。在计算机图形学中,模糊就是让图像的边缘变得不清晰,从锐利的边界变成柔和的过渡。</p>
                    </div>

                    <div class="demo-grid">
                        <div class="demo-box">
                            <h4>模糊效果对比</h4>
                            <div style="display: flex; gap: 15px; align-items: center; margin: 15px 0;">
                                <div style="width: 50px; height: 50px; background: #ff6b6b; border-radius: 50%;"></div>
                                <span>→</span>
                                <div style="width: 50px; height: 50px; background: #ff6b6b; border-radius: 50%; filter: blur(3px);"></div>
                            </div>
                            <p style="text-align: center; color: #666;">清晰的圆 → 模糊的圆</p>
                            <p><strong>看到了吗?</strong>右边的圆边缘变得柔和了,不再是硬邦邦的边界。</p>
                        </div>
                        <div class="demo-box">
                            <h4>Web开发中的模糊应用</h4>
                            <ul style="margin-left: 20px;">
                                <li>🖼️ 图片背景虚化效果</li>
                                <li>🎭 遮罩层后的内容模糊</li>
                                <li>🔍 搜索结果的渐进加载</li>
                                <li>🎨 毛玻璃效果 (backdrop-filter)</li>
                                <li>💫 悬停时的焦点突出</li>
                            </ul>
                            <p><strong>共同点:</strong>都是通过模糊来创造视觉层次和焦点!</p>
                        </div>
                    </div>

                    <div class="explanation">
                        <h4>⚡ 什么是"对比度"?</h4>
                        <p>对比度就是黑白之间的差别程度。高对比度意味着黑的更黑,白的更白,中间的灰色会被"推向"黑色或白色。就像调节电视机的对比度旋钮一样。</p>
                    </div>

                    <div class="demo-grid">
                        <div class="demo-box">
                            <h4>对比度效果对比</h4>
                            <div style="background: linear-gradient(to right, #000, #333, #666, #999, #ccc, #fff); height: 40px; margin: 10px 0; border-radius: 5px; position: relative;">
                                <span style="position: absolute; left: 5px; top: 10px; color: white; font-size: 12px; font-weight: bold;">正常对比度</span>
                            </div>
                            <div style="background: linear-gradient(to right, #000, #333, #666, #999, #ccc, #fff); height: 40px; margin: 10px 0; border-radius: 5px; filter: contrast(5); position: relative;">
                                <span style="position: absolute; left: 5px; top: 10px; color: white; font-size: 12px; font-weight: bold;">高对比度</span>
                            </div>
                            <p><strong>看到了吗?</strong>下面的渐变中,灰色部分变少了,更多的是纯黑和纯白。</p>
                        </div>
                        <div class="demo-box">
                            <h4>Web开发中的对比度应用</h4>
                            <ul style="margin-left: 20px;">
                                <li>🎨 主题切换中的色彩增强</li>
                                <li>🖼️ 图像处理和滤镜效果</li>
                                <li>📱 无障碍设计的可读性提升</li>
                                <li>🎭 蒙版效果的边缘锐化</li>
                                <li>🔲 SVG图标的清晰度优化</li>
                            </ul>
                            <p><strong>共同点:</strong>都是通过对比度来增强视觉效果的清晰度!</p>
                        </div>
                    </div>
                </div>

                <!-- CSS中的模糊和对比度 -->
                <div class="section">
                    <h3>💻 CSS中如何实现模糊和对比度?</h3>
                    
                    <div class="explanation">
                        <h4>CSS滤镜 (filter) 是什么?</h4>
                        <p>CSS滤镜就像给图片加特效的工具,就像美图软件里的滤镜一样。我们可以用它来让元素变模糊、调整对比度等。</p>
                    </div>

                    <div class="code-block">
<span class="comment">/* 基础语法 - 就像给元素"戴眼镜" */</span>
.<span class="property">my-element</span> {
    <span class="property">filter</span>: <span class="value">blur(5px)</span>;        <span class="comment">/* 让元素变模糊 */</span>
    <span class="property">filter</span>: <span class="value">contrast(2)</span>;      <span class="comment">/* 增加对比度 */</span>
    <span class="property">filter</span>: <span class="value">blur(5px) contrast(2)</span>; <span class="comment">/* 同时应用多个效果 */</span>
}
                    </div>

                    <div class="demo-grid">
                        <div class="demo-box">
                            <h4>模糊值的含义</h4>
                            <div class="code-block">
<span class="comment">/* 数字越大,越模糊 */</span>
<span class="property">filter</span>: <span class="value">blur(0px)</span>;   <span class="comment">/* 不模糊 */</span>
<span class="property">filter</span>: <span class="value">blur(3px)</span>;   <span class="comment">/* 轻微模糊 */</span>
<span class="property">filter</span>: <span class="value">blur(10px)</span>;  <span class="comment">/* 很模糊 */</span>
<span class="property">filter</span>: <span class="value">blur(20px)</span>;  <span class="comment">/* 非常模糊 */</span>
                            </div>
                            <p><strong>记住:</strong>数字越大,越看不清!</p>
                        </div>
                        <div class="demo-box">
                            <h4>对比度值的含义</h4>
                            <div class="code-block">
<span class="comment">/* 数字越大,黑白越分明 */</span>
<span class="property">filter</span>: <span class="value">contrast(1)</span>;   <span class="comment">/* 正常 */</span>
<span class="property">filter</span>: <span class="value">contrast(2)</span>;   <span class="comment">/* 增强一点 */</span>
<span class="property">filter</span>: <span class="value">contrast(10)</span>;  <span class="comment">/* 很强 */</span>
<span class="property">filter</span>: <span class="value">contrast(20)</span>;  <span class="comment">/* 非常强 */</span>
                            </div>
                            <p><strong>记住:</strong>数字越大,黑白越分明!</p>
                        </div>
                    </div>
                </div>

                <!-- 融球效果中的应用 -->
                <div class="section">
                    <h3>🎯 它们在融球效果中的神奇作用</h3>
                    
                    <div class="explanation">
                        <h4>为什么模糊+对比度能产生融球效果?</h4>
                        <p>这就像一个魔术!让我们一步步揭秘:</p>
                    </div>

                    <div class="demo-grid">
                        <div class="demo-box">
                            <h4>第一步:模糊创造"过渡地带"</h4>
                            <div style="display: flex; gap: 10px; align-items: center; margin: 15px 0;">
                                <div style="width: 40px; height: 40px; background: #fff; border: 2px solid #333; border-radius: 50%;"></div>
                                <span>+</span>
                                <div style="width: 40px; height: 40px; background: #fff; border: 2px solid #333; border-radius: 50%;"></div>
                                <span>=</span>
                                <span>两个分离的圆</span>
                            </div>
                            <div style="display: flex; gap: 10px; align-items: center; margin: 15px 0; background: #333; padding: 10px; border-radius: 5px;">
                                <div style="width: 40px; height: 40px; background: #fff; border-radius: 50%; filter: blur(5px);"></div>
                                <span style="color: #fff;">+</span>
                                <div style="width: 40px; height: 40px; background: #fff; border-radius: 50%; filter: blur(5px);"></div>
                                <span style="color: #fff;">=</span>
                                <span style="color: #fff;">边缘变柔和了</span>
                            </div>
                            <p><strong>关键:</strong>模糊让硬边界变成了柔和的"过渡地带"</p>
                        </div>
                        <div class="demo-box">
                            <h4>第二步:对比度"决定"黑白</h4>
                            <p>当两个模糊的圆靠近时,它们的"过渡地带"会重叠,产生灰色区域。</p>
                            <p><strong>这时对比度出场了!</strong></p>
                            <ul style="margin-left: 20px; margin-top: 10px;">
                                <li>🔍 对比度说:"灰色?不行!"</li>
                                <li>⚫ "要么变成黑色(背景)"</li>
                                <li>⚪ "要么变成白色(连接)"</li>
                                <li>🎉 结果:两个圆"融合"了!</li>
                            </ul>
                        </div>
                    </div>

                    <div class="explanation">
                        <h4>具体在代码中是怎么做的?</h4>
                        <p>我们需要分工合作:</p>
                    </div>

                    <div class="code-block">
<span class="comment">/* 容器负责"决定黑白" */</span>
.<span class="property">container</span> {
    <span class="property">filter</span>: <span class="value">contrast(20)</span>;  <span class="comment">/* 我来决定什么是黑,什么是白! */</span>
}

<span class="comment">/* 元素负责"变模糊" */</span>
.<span class="property">ball</span> {
    <span class="property">filter</span>: <span class="value">blur(10px)</span>;   <span class="comment">/* 我来创造柔和的边缘! */</span>
}

<span class="comment">/* 结果:当模糊的球靠近时,重叠的灰色区域被对比度"判决"为白色连接! */</span>
                    </div>
                </div>

                <div class="explanation">
                    <h4>总结:融球效果的"魔法公式"</h4>
                    <p><strong>模糊</strong>(创造柔和边缘)+ <strong>对比度</strong>(决定黑白)= <strong>融球效果</strong>(液体般的融合)</p>
                    <p>关键在于分层应用:容器负责对比度处理,元素负责模糊效果,两者协同工作创造出自然的融合效果。</p>
                </div>
            </div>

            <!-- 交互式演示 -->
            <div class="section">
                <h2>🎮 交互式演示</h2>
                <p>观看下面的自动演示,体验融球效果的形成过程:</p>

                <div class="interactive-demo">
                    <div class="controls">
                        <div class="control-group">
                            <label>元素模糊强度: <span class="value-display" id="blurValue">10</span>px</label>
                            <input type="range" id="blurSlider" min="0" max="20" value="10">
                        </div>
                        <div class="control-group">
                            <label>容器对比度: <span class="value-display" id="contrastValue">20</span></label>
                            <input type="range" id="contrastSlider" min="1" max="50" value="20">
                        </div>
                        <div class="control-group">
                            <label>容器额外模糊: <span class="value-display" id="containerBlurValue">0.5</span>px</label>
                            <input type="range" id="containerBlurSlider" min="0" max="3" step="0.1" value="0.5">
                        </div>
                    </div>

                    <div class="interactive-area" id="interactiveArea">
                        <div class="movable-ball ball-a" id="ballA">A</div>
                        <div class="movable-ball ball-b" id="ballB">B</div>
                    </div>

                    <p style="margin-top: 15px; color: #666;">
                        💡 <strong>提示:</strong>调整上方的参数,观察球体的自动运动和融合效果。试试将模糊或对比度调到0,看看会发生什么!
                    </p>
                </div>
            </div>

            <!-- 实际应用 -->
            <div class="section">
                <h2>🚀 实际应用场景</h2>
                <div class="demo-grid">
                    <div class="demo-box">
                        <h3>🎨 UI设计</h3>
                        <p>流体按钮、动态加载指示器、有机形状的界面元素</p>
                    </div>
                    <div class="demo-box">
                        <h3>🎮 游戏开发</h3>
                        <p>液体物理效果、粒子系统、动态地形变化</p>
                    </div>
                    <div class="demo-box">
                        <h3>📱 移动应用</h3>
                        <p>手势反馈效果、动态图标、流体导航</p>
                    </div>
                    <div class="demo-box">
                        <h3>🎬 动画制作</h3>
                        <p>角色变形、液体模拟、有机过渡效果</p>
                    </div>
                </div>
            </div>

            <!-- 总结 -->
            <div class="section">
                <h2>📝 总结</h2>
                <div class="explanation">
                    <h4>融球效果的关键要素:</h4>
                    <ul style="margin-left: 20px; margin-top: 10px;">
                        <li><strong>分层应用</strong>:容器应用对比度,元素应用模糊</li>
                        <li><strong>元素模糊</strong>:为形状创建柔和的边缘渐变</li>
                        <li><strong>容器对比度</strong>:将重叠的渐变区域转换为清晰的连接</li>
                        <li><strong>参数平衡</strong>:模糊强度和对比度需要合理搭配</li>
                        <li><strong>Web Component封装</strong>:使用Shadow DOM实现样式隔离和复用</li>
                    </ul>
                </div>
                
                <p>理解了这个分层滤镜的原理,你就掌握了融球效果的精髓。通过Web Component的封装,可以轻松地在任何项目中应用这种效果,创造出令人印象深刻的用户体验!</p>
            </div>
        </div>
    </div>

    <script type="module">
        // 导入融球控件(模拟导入,实际使用时需要正确的路径)
        // import MetaballContainer from './MetaballEffect.js';

        // 交互式演示控制
        const interactiveArea = document.getElementById('interactiveArea');
        const blurSlider = document.getElementById('blurSlider');
        const contrastSlider = document.getElementById('contrastSlider');
        const containerBlurSlider = document.getElementById('containerBlurSlider');
        const blurValue = document.getElementById('blurValue');
        const contrastValue = document.getElementById('contrastValue');
        const containerBlurValue = document.getElementById('containerBlurValue');

        // 更新滤镜效果
        function updateFilters() {
            const blur = blurSlider.value;
            const contrast = contrastSlider.value;
            const containerBlur = containerBlurSlider.value;

            // 更新显示值
            blurValue.textContent = blur;
            contrastValue.textContent = contrast;
            containerBlurValue.textContent = containerBlur;

            // 应用滤镜(按照正确的融球原理)
            interactiveArea.style.filter = `contrast(${contrast}) blur(${containerBlur}px)`;
            
            const balls = interactiveArea.querySelectorAll('.movable-ball');
            balls.forEach(ball => {
                ball.style.filter = `blur(${blur}px)`;
            });
        }

        // 绑定滑块事件
        blurSlider.addEventListener('input', updateFilters);
        contrastSlider.addEventListener('input', updateFilters);
        containerBlurSlider.addEventListener('input', updateFilters);

        // 初始化
        updateFilters();

        // 自动演示动画
        function autoDemo() {
            const ballA = document.getElementById('ballA');
            const ballB = document.getElementById('ballB');
            
            let time = 0;
            function animate() {
                time += 0.02;
                const centerX = interactiveArea.offsetWidth / 2 - 40;
                const centerY = interactiveArea.offsetHeight / 2 - 40;
                
                ballA.style.left = (centerX - 50 + Math.cos(time) * 40) + 'px';
                ballA.style.top = (centerY + Math.sin(time * 0.7) * 25) + 'px';
                
                ballB.style.left = (centerX + 50 + Math.cos(time + Math.PI) * 40) + 'px';
                ballB.style.top = (centerY + Math.sin(time * 0.7 + Math.PI) * 25) + 'px';
                
                requestAnimationFrame(animate);
            }
            
            // 立即开始自动演示
            animate();
        }

        autoDemo();
    </script>
</body>
</html> 

 


网站公告

今日签到

点亮在社区的每一天
去签到