万花筒效果

186 阅读1分钟

效果说明

本案例实现了一个动态的万花筒效果。通过Canvas绘制基础图形,结合旋转变换和对称复制,创建出绚丽的万花筒图案。效果包含颜色渐变、波浪动画和鼠标交互功能。

万花筒.gif

核心实现

1. 基础配置

使用配置对象管理关键参数:

const config = {
    segments: 12, // 分段数量,决定万花筒的对称性
    radius: Math.min(canvas.width, canvas.height) 0.4, // 半径
    centerX: canvas.width / 2, // 中心点X坐标
    centerY: canvas.height / 2, // 中心点Y坐标
    hue: 0 // 初始色相值
};

2. 渐变效果

使用HSL颜色空间创建从中心向外的渐变效果:

const gradient = ctx.createLinearGradient(0, 0, config.radius, 0);
gradient.addColorStop(0, `hsla(${config.hue}, 100%, 50%, 1)`);      // 中心点颜色
gradient.addColorStop(1, `hsla(${config.hue + 60}, 100%, 50%, 0)`); // 边缘颜色

3. 波浪动画

通过正弦函数创建动态波浪效果:

const time = Date.now() * 0.001;  // 时间因子
for (let i = 0; i <= 10; i++) {
    const t = i / 10;  // 归一化参数
    const x = config.radius * t;  
    const y = Math.sin(t * 5 + time) * 20;  // 使用正弦函数生成波浪
    ctx.lineTo(x, y);
}

4. 对称复制

通过循环旋转绘制多个分段,实现对称效果:

for (let i = 0; i < config.segments; i++) {
    const angle = (i * Math.PI * 2) / config.segments;
    drawSegment(angle);
}

5. 交互控制

实现鼠标拖拽改变半径的功能:

canvas.addEventListener('mousemove', (e) => {
    if (isMouseDown) {
        const dx = e.clientX - config.centerX;
        const dy = e.clientY - config.centerY;
        config.radius = Math.sqrt(dx * dx + dy * dy);
    }
});

技术要点

  1. Canvas变换

    • 使用translate移动坐标系
    • 使用rotate实现旋转效果
    • save()和restore()管理绘图状态
  2. HSL颜色应用

    • 使用HSL颜色空间实现平滑的颜色过渡
    • 通过改变色相值(hue)实现彩虹色效果
  3. 动画实现

    • requestAnimationFrame实现流畅动画
    • 使用时间因子控制波浪运动
    • 渐变色循环产生动态效果
  4. 性能优化

    • 使用半透明遮罩实现轨迹渐隐
    • 合理使用Canvas状态管理

Demo