console
let box = document.querySelector('.box')
var line_canvas = document.getElementById("circleCanvas");
var line_ctx = line_canvas.getContext("2d");
var dot_canvas = document.getElementById("dotCanvas");
var dot_ctx = dot_canvas.getContext("2d");
let num = 1
let first_radius = 50
let interval = 10
let center_x = line_canvas.width / 2
let center_y = line_canvas.height
var linearSpeed = 1;
let circle_list = []
let dot_list = []
function generateRainbowColors(numColors, saturation = 1, value = 1) {
function HSVtoRGB(h, s, v) {
let r, g, b, i, f, p, q, t;
if (s === 0) {
r = g = b = v;
} else {
h /= 60;
i = Math.floor(h);
f = h - i;
p = v * (1 - s);
q = v * (1 - s * f);
t = v * (1 - s * (1 - f));
switch (i % 6) {
case 0:
r = v; g = t; b = p;
break;
case 1:
r = q; g = v; b = p;
break;
case 2:
r = p; g = v; b = t;
break;
case 3:
r = p; g = q; b = v;
break;
case 4:
r = t; g = p; b = v;
break;
case 5:
r = v; g = p; b = q;
break;
}
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
const rainbowColors = [];
for (let i = 0; i < numColors; i++) {
const hue = (i / numColors) * 360;
const [r, g, b] = HSVtoRGB(hue, saturation, value);
const color = `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
rainbowColors.push(color);
}
return rainbowColors;
}
function mixColor(color1, color2, weight) {
var d2h = function (d) { return d.toString(16).padStart(2, '0'); };
var h2d = function (h) { return parseInt(h, 16); };
var color = "#";
for (var i = 1; i < 7; i += 2) {
var v1 = h2d(color1.substr(i, 2));
var v2 = h2d(color2.substr(i, 2));
var val = d2h(Math.floor(v2 + (v1 - v2) * weight));
color += val;
}
return color;
}
function drawCircle() {
circle_list.forEach(option => {
line_ctx.beginPath();
line_ctx.arc(center_x, center_y, option.radius, Math.PI, 0);
line_ctx.lineWidth = option.line_width;
line_ctx.strokeStyle = option.color;
line_ctx.stroke();
})
}
function drawDot() {
dot_ctx.clearRect(0, 0, dot_canvas.width, dot_canvas.height);
dot_list.forEach(function (ball) {
var x = center_x - ball.radius * Math.cos(ball.angle);
var y = center_y - ball.radius * Math.sin(ball.angle);
var weight = ball.angle / Math.PI;
if (ball.direction) {
ball.angle += ball.angularSpeed;
} else {
ball.angle -= ball.angularSpeed;
}
if (ball.angle >= Math.PI || ball.angle <= 0) {
ball.direction = !ball.direction;
}
var color = ball.direction
? mixColor(ball.color, '#FFFFFF', weight)
: mixColor('#FFFFFF', ball.color, weight);
dot_ctx.beginPath();
dot_ctx.arc(x, y, 5, 0, 2 * Math.PI);
dot_ctx.fillStyle = color;
dot_ctx.fill();
});
requestAnimationFrame(drawDot);
}
function init() {
let colors = generateRainbowColors(num, 0.75, 0.8)
new Array(num).fill({}).forEach((item, index) => {
let radius = first_radius + index * interval
circle_list.push({
line_width: 2,
radius,
color: colors[index],
})
dot_list.push({
angularSpeed: linearSpeed / radius,
radius,
angle: 0,
color: colors[index],
direction: true
})
})
drawCircle()
drawDot()
}
init()
<div class="relative box">
<canvas class="absolute" width="600" height="400" id="circleCanvas"></canvas>
<canvas class="absolute" width="600" height="400" id="dotCanvas"></canvas>
</div>
.relative{
position: relative
}
.absolute{
position: absolute
}
.box{
width: 600px;
height: 400px;
background-color: #282828;
}