// 初始化Canvas和上下文
const canvas = document.getElementById('kaleidoscope');
const ctx = canvas.getContext('2d');
let width, height;
// 控制元素
const symmetrySlider = document.getElementById('symmetry');
const symmetryValue = document.getElementById('symmetry-value');
const speedSlider = document.getElementById('speed');
const randomizeBtn = document.getElementById('randomize');
const resetBtn = document.getElementById('reset');
// 状态变量
let segments = 6;
let speed = 5;
let colors = [];
let angle = 0;
let isDrawing = false;
let lastPoint = { x: 0, y: 0 };
let hue = 0;
// 初始化函数
function init() {
resizeCanvas();
generateRandomColors();
setupEventListeners();
animate();
}
// 调整Canvas大小
function resizeCanvas() {
width = canvas.width = canvas.offsetWidth;
height = canvas.height = canvas.offsetHeight;
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, width, height);
}
// 生成随机颜色
function generateRandomColors() {
colors = [];
const baseHue = Math.random() * 360;
for (let i = 0; i < 3; i++) {
colors.push(`hsl(${(baseHue + i * 120) % 360}, 80%, 60%)`);
}
}
// 设置事件监听器
function setupEventListeners() {
window.addEventListener('resize', resizeCanvas);
canvas.addEventListener('mousedown', (e) => {
isDrawing = true;
lastPoint = getCanvasPoint(e);
});
canvas.addEventListener('mousemove', (e) => {
if (!isDrawing) return;
const currentPoint = getCanvasPoint(e);
drawSegment(lastPoint, currentPoint);
lastPoint = currentPoint;
});
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseout', () => isDrawing = false);
// 触摸支持
canvas.addEventListener('touchstart', (e) => {
e.preventDefault();
isDrawing = true;
lastPoint = getCanvasPoint(e.touches[0]);
});
canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
if (!isDrawing) return;
const currentPoint = getCanvasPoint(e.touches[0]);
drawSegment(lastPoint, currentPoint);
lastPoint = currentPoint;
});
canvas.addEventListener('touchend', () => isDrawing = false);
// 控制面板事件
symmetrySlider.addEventListener('input', () => {
segments = parseInt(symmetrySlider.value);
symmetryValue.textContent = segments;
});
speedSlider.addEventListener('input', () => {
speed = parseInt(speedSlider.value);
});
randomizeBtn.addEventListener('click', generateRandomColors);
resetBtn.addEventListener('click', () => {
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.fillRect(0, 0, width, height);
});
}
// 获取Canvas坐标点
function getCanvasPoint(e) {
const rect = canvas.getBoundingClientRect();
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
}
// 绘制对称线段
function drawSegment(start, end) {
const segmentAngle = (Math.PI * 2) / segments;
const center = { x: width / 2, y: height / 2 };
ctx.lineWidth = 2;
ctx.lineCap = 'round';
for (let i = 0; i < segments; i++) {
const currentAngle = segmentAngle * i;
// 旋转起点
const rotatedStart = rotatePoint(start, center, currentAngle);
const rotatedEnd = rotatePoint(end, center, currentAngle);
// 绘制线段
const gradient = ctx.createLinearGradient(
rotatedStart.x, rotatedStart.y,
rotatedEnd.x, rotatedEnd.y
);
gradient.addColorStop(0, colors[0]);
gradient.addColorStop(0.5, colors[1]);
gradient.addColorStop(1, colors[2]);
ctx.strokeStyle = gradient;
ctx.beginPath();
ctx.moveTo(rotatedStart.x, rotatedStart.y);
ctx.lineTo(rotatedEnd.x, rotatedEnd.y);
ctx.stroke();
}
}
// 旋转点
function rotatePoint(point, center, angle) {
const x = point.x - center.x;
const y = point.y - center.y;
const rotatedX = x * Math.cos(angle) - y * Math.sin(angle);
const rotatedY = x * Math.sin(angle) + y * Math.cos(angle);
return {
x: rotatedX + center.x,
y: rotatedY + center.y
};
}
// 动画循环
function animate() {
requestAnimationFrame(animate);
// 淡出效果
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, width, height);
// 自动旋转
if (!isDrawing && speed > 0) {
angle += 0.002 * speed;
const center = { x: width / 2, y: height / 2 };
const point = { x: center.x + 100, y: center.y };
const rotatedPoint = rotatePoint(point, center, angle);
hue = (hue + 0.5) % 360;
colors = [
`hsl(${hue}, 80%, 60%)`,
`hsl(${(hue + 120) % 360}, 80%, 60%)`,
`hsl(${(hue + 240) % 360}, 80%, 60%)`
];
drawSegment(center, rotatedPoint);
}
}
// 启动应用
init();
评论