У меня на сайте есть вот такой след от курсора:
Реализован он следующим образом (все на канвасе):
При движении мыши (mousemove) фиксируются координаты двух точек (начальная и конечная).
Между этими точками прокладываются окружности, цвет которых все время вычисляется по-разному, таким образом, получается градиентная линия.
Проблема в следующем:
Клиент хочет, чтобы градиент был анимированным, например, чтобы цвет переливался.
Чтобы мне это сделать, мне нужно стирать канвас и каждый раз отрисовывать нарисованные окружности уже с новым цветом, чтобы создать эффект переливания. А чтобы заново отрисовывать стертые окружности, я должен хранить где-то координаты точек, между которыми они были нарисованы.
Как мне это сделать, если точек слишком много и это нагружает браузер?
И вообще, правильно ли, что я сразу перешел к канвасу или и без него это можно было сделать?
var c = document.querySelector("canvas");
var ctx = c.getContext("2d");
var colors = [
{r: 2, g: 127, b: 243},
{r: 0, g: 198, b: 255},
{r: 103, g: 43, b: 185},
];
var cIndex = 0;
var maxColors = colors.length;
var total = 0;
var segment = 1500;
var px, py;
setSize();
window.onmousemove = function (e) {
plot(e);
};
function getPos(e) {
var r = c.getBoundingClientRect();
return {
x: e.clientX - r.left,
y: e.clientY - r.top
}
}
// plot вызывается при движении мыши
function plot(e) {
var pos = getPos(e);
plotLine(ctx, px, py, pos.x, pos.y);
px = pos.x;
py = pos.y;
}
// тут вычисляется цвет
function getColor() {
var r, g, b, t, c1, c2;
c1 = colors[cIndex];
c2 = colors[(cIndex + 1) % maxColors];
t = Math.min(1, total/segment);
if (++total > segment) {
total = 0;
if (++cIndex >= maxColors)
cIndex = 0;
}
r = c1.r + (c2.r - c1.r) * t;
g = c1.g + (c2.g - c1.g) * t;
b = c1.b + (c2.b - c1.b) * t;
return `rgb(${r}, ${g}, ${b})`;
}
// здесь отрисовка окружностей между двумя точками
function plotLine(ctx, x1, y1, x2, y2) {
var diffX = Math.abs(x2 - x1);
var diffY = Math.abs(y2 - y1);
var dist = Math.sqrt(diffX*diffX + diffY*diffY);
var step = dist/10;
var i = 0;
var t, x, y;
while (i < dist) {
t = i/dist;
x = x1 + (x2 - x1) * t;
y = y1 + (y2 - y1) * t;
ctx.fillStyle = getColor();
ctx.beginPath();
ctx.arc(x, y, 60, 0, Math.PI*2);
ctx.fill();
i += step;
}
}
window.onresize = setSize;
function setSize() {
c.width = window.innerWidth;
c.height = window.innerHeight;
}