'use client'; import React, { useState, useEffect, useRef } from 'react'; // 预设演示的颜色序列 (R, G, B) const COLOR_SEQUENCE = [ { r: 255, g: 0, b: 0, name: '红色 (Red)' }, { r: 0, g: 255, b: 0, name: '绿色 (Green)' }, { r: 0, g: 0, b: 255, name: '蓝色 (Blue)' }, { r: 255, g: 255, b: 0, name: '黄色 (Yellow = R+G)' }, { r: 0, g: 255, b: 255, name: '青色 (Cyan = G+B)' }, { r: 255, g: 0, b: 255, name: '洋红 (Magenta = R+B)' }, { r: 255, g: 255, b: 255, name: '白色 (White = R+G+B)' }, { r: 255, g: 128, b: 0, name: '橙色 (Orange)' }, { r: 128, g: 0, b: 128, name: '紫色 (Purple)' }, ]; const VIEW_WIDTH = 1000; const VIEW_HEIGHT = 600; // 辅助函数:十进制转8位二进制 const toBinary = (num: number) => num.toString(2).padStart(8, '0'); // 辅助函数:RGB转Hex const toHex = (r: number, g: number, b: number) => `#${[r, g, b].map(x => Math.round(x).toString(16).padStart(2, '0')).join('').toUpperCase()}`; // 线性插值 const lerp = (start: number, end: number, factor: number) => start + (end - start) * factor; export const ColorMixingPrinciple = () => { const [targetIndex, setTargetIndex] = useState(0); // 当前显示的颜色值(用于动画过渡) const [currentRGB, setCurrentRGB] = useState({ r: 0, g: 0, b: 0 }); const requestRef = useRef(); const startTimeRef = useRef(); // 自动循环切换颜色 useEffect(() => { const interval = setInterval(() => { setTargetIndex((prev) => (prev + 1) % COLOR_SEQUENCE.length); }, 4000); // 每4秒切换一次 return () => clearInterval(interval); }, []); // 动画循环:平滑过渡颜色数值 useEffect(() => { const target = COLOR_SEQUENCE[targetIndex]; const animate = () => { setCurrentRGB(prev => { // 简单的缓动效果 (Ease out) const factor = 0.05; const r = lerp(prev.r, target.r, factor); const g = lerp(prev.g, target.g, factor); const b = lerp(prev.b, target.b, factor); // 如果非常接近目标值,就不再更新以节省资源(可选,这里为了流畅一直跑) return { r, g, b }; }); requestRef.current = requestAnimationFrame(animate); }; requestRef.current = requestAnimationFrame(animate); return () => { if (requestRef.current) cancelAnimationFrame(requestRef.current); }; }, [targetIndex]); const { r, g, b } = currentRGB; const intR = Math.round(r); const intG = Math.round(g); const intB = Math.round(b); const hex = toHex(r, g, b); const targetName = COLOR_SEQUENCE[targetIndex].name; // 布局参数 const centerX = VIEW_WIDTH / 2 + 100; const centerY = VIEW_HEIGHT / 2; const layerSize = 220; const offset = 60; // 层与层之间的偏移量 return ( {/* 背景 */} {/* 装饰性网格背景 */} {/* 标题区域 */} 计算机色彩原理: RGB 通道叠加 Computer Color Recognition & Mixing Logic {/* 左侧:数据面板 (Data Panel) */} {/* 面板背景 */} 数据通道 (Data Channels) {/* 红色通道数据 */} R (Red) {intR} {toBinary(intR)} {/* 绿色通道数据 */} G (Green) {intG} {toBinary(intG)} {/* 蓝色通道数据 */} B (Blue) {intB} {toBinary(intB)} {/* 综合结果数值 */} HEX Code: {hex} {targetName} {/* 连接线:从数据到视觉层 */} {/* 右侧:视觉叠加演示 (Visual Stacking) */} {/* 这是一个利用 CSS mix-blend-mode 模拟光线叠加的关键部分 */} {/* 在 SVG 中,我们通常使用 filter 或 isolate 组配合 CSS 属性 */} {/* 红色层 (Red Layer) - 左上偏移 */} {/* 标注 */} R 通道 {/* 绿色层 (Green Layer) - 居中 */} G 通道 {/* 蓝色层 (Blue Layer) - 右下偏移 */} B 通道 {/* 中心合成结果的高亮框 (指示最终合成颜色) */} {/* 只在三个图层重叠的中心区域画一个示意框 */} {/* 动态计算中心区域的颜色,用于展示最终结果 */} {/* 牵引线指向结果 */} 最终呈色 Final Pixel {/* 底部说明文字 */} 原理:屏幕上的每个像素由红(R)、绿(G)、蓝(B)三个子像素组成。通过调整这三个通道的亮度比例(0-255),混合出人眼可见的各种颜色。 ); };