Метеор — это эстетическое астрономическое явление. Когда-то я хотел нарисовать его с помощью того, чему научился. Недавно я вдохновился учебником по холсту на MDN, чтобы нарисовать метеоры с эффектом длинного хвоста холста...
Что такое эффект длинного хвоста?
Мы знаем, что реализация анимации холста зависит от перерисовки холста.Постоянно очищая холст, основной эффект анимации может быть достигнут путем рисования холста. Обычно используйте метод clearRect, чтобы очистить указанную прямоугольную область для перерисовки. Эффект длинного хвоста достигается за счет использования прозрачного цвета заливки вместо метода clearRect.
использовать клиррект
Tucao: Поскольку частота кадров программного обеспечения для записи экрана не поспевает за холстом, это изображение GIF немного застревает.
использовать fillRect
1. Прозрачность 1
Видно, что когда прозрачность равна 1, эффект такой же, как и эффект очистки.Мы можем понять, что на холст накрывается другой холст. , скрывает то, что было нарисовано до этого, поэтому эффект такой же, как и при очистке.2. Прозрачность равна 0Эффект прозрачности 0 эквивалентен эффекту не очистки холста.В это время движущаяся сфера похожа на змею у которой постоянно растет хвост.Вы можете догадаться исходя из этого, установите прозрачность между 0 и 1 для настройки Длина хвоста для достижения эффекта размытия движения с помощью хвоста.
3. Эффект длинного хвостаПоскольку прозрачное полотно непрерывно покрыто, создается путь осветляющего цвета от точки рисования к начальной точке, создавая визуальный эффект динамического размытия.
метеор
Метеор можно разложить на круг и эффект длинного хвоста:
Визуальный эффект:
фактический эффект:Инкапсулировать форму страницы
Объектно-ориентированное программирование завершается холстом для рисования
Лунный класс
class Moon {
constructor(x, y, ctx, r = 25) {
this.x = x;
this.y = y;
this.ctx = ctx;
this.r = r;
}
draw() {
this.ctx.fillStyle = 'rgba(255,255,255,0.6)';
this.ctx.shadowBlur = this.r + 5; //光晕半径
this.ctx.shadowColor = "#fff"; // 光晕颜色
this.ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
this.ctx.fill();
}
}
Because the moon is still on the page, there is only one draw method. The realization of the moon halo is to set the shadow and fill to the same color, and then make the shadow transparency greater than the fill transparency to form an outer glow эффект.
звездный класс
class Star extends Moon {
constructor(x, y, ctx, r) {
super(x, y, ctx, r);
}
draw() {
this.ctx.fillStyle = 'rgba(255,255,255,0.8)';
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
this.ctx.closePath();
this.ctx.fill();
}
move() {
this.x += 0.08;
if (this.x > meteorCanvas.width) {
this.x = 0;
}
this.draw();
}
}
Единственная разница между звездами и луной заключается в том, что их можно перемещать, поэтому используйте класс звезды, чтобы наследовать класс луны, чтобы добиться объектно-ориентированного наследования и полиморфизма.
Медленное движение звезды вправо имитирует эффект вращения Земли.
Метеор Класс
class Meteor extends Star {
constructor(x, y, ctx, r,angle) {
super(x, y, ctx, r);
this.angle = angle;
}
draw() {
this.ctx.fillStyle = '#ffffff';
this.ctx.rotate(this.angle);
this.ctx.translate(100, -meteorCanvas.height / 1.5);
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
this.ctx.closePath();
this.ctx.fill();
this.ctx.translate(-100, meteorCanvas.height / 1.5);
this.ctx.rotate(-this.angle);
}
move() {
this.x += 4;
this.y += 1;
if (this.x > meteorCanvas.width) {
this.x = Math.random() * 5
this.y = -2 * meteorCanvas.height + Math.random() * meteorCanvas.height * 3;
}
this.draw();
}
}
Точно так же используйте класс метеора, чтобы наследовать класс звезды.
Обратите внимание, что разница между движением класса метеора и класса звезды заключается в том, что метеор имеет прилежащий угол по небу, поэтому после поворота угла холста во время рисования ему необходимо вернуться в исходное положение.
Для того, чтобы позиция метеора не казалась слишком плотной, я буду позиционировать появившийся метеор по оси ординат от минус двухкратной высоты холста до 1-кратной высоты холста, холст и перемещать вверх на высоту метод рисования холста 2/3 (так же, как вы хотите, чтобы холст возвращался).
рисовать холст
Метеоры должны быть отрисованы с использованием эффекта длинного хвоста, звезды должны быть перерисованы с помощью clearRect, а луна должна быть отрисована только один раз. Чтобы три фигуры не мешали друг другу, я использовал разные холсты для их рендеринга.
Достоинства: отсутствие помех друг другу, четкая логика отрисовки, оптимизированный рендеринг.
исходный код
const meteorCanvas = document.getElementById('meteor');
const starCanvas = document.getElementById('star');
const moonCanvas = document.getElementById('moon');
const meteors = [], stars = [];
meteorCanvas.width = document.body.clientWidth;
meteorCanvas.height = document.body.clientHeight;
starCanvas.width = document.body.clientWidth;
starCanvas.height = document.body.clientHeight / 3;
moonCanvas.width = document.body.clientWidth;
moonCanvas.height = document.body.clientHeight / 3;
const meteorCtx = meteorCanvas.getContext('2d');
const starCtx = starCanvas.getContext('2d');
const moonCtx = moonCanvas.getContext('2d');
init();
animate();
function init() {
for (var i = 0; i < 4; i++) {
meteors[i] = new Meteor(Math.random() * meteorCanvas.width,
-2 * meteorCanvas.height + Math.random() * meteorCanvas.height * 3,
meteorCtx, Math.floor(Math.random() * 2) + 1.5, Math.PI / 7);
meteors[i].draw();
}
for (var i = 0; i < 60; i++) {
stars[i] = new Star(Math.random() * starCanvas.width, Math.random() * starCanvas.height,
starCtx, Math.random());
stars[i].draw();
}
moon = new Moon(moonCanvas.width - 50, 50, moonCtx)
moon.draw();
}
function animate() {
starCtx.clearRect(0, 0, starCanvas.width, starCanvas.height);
meteorCtx.fillStyle = `rgba(0, 0, 0, 0.1)`;
meteorCtx.fillRect(0, 0, meteorCanvas.width, meteorCanvas.height);
for (let meteor of meteors)
meteor.move();
for (let star of stars)
star.move();
requestAnimationFrame(animate);
}
function recover() {
for (let meteor of meteors)
meteor = null;
for (let star of stars)
star = null;
moon = null;
}
window.onresize = function () {
meteorCanvas.width = document.body.clientWidth;
meteorCanvas.height = document.body.clientHeight;
starCanvas.width = document.body.clientWidth;
starCanvas.height = document.body.clientHeight / 3;
moonCanvas.width = document.body.clientWidth;
moonCanvas.height = document.body.clientHeight / 3;
recover();
init();
}
Эпилог
Сопровождать вас, чтобы посмотреть, как метеоритный дождь падает на эту землю
Пусть твои слезы падают на мое плечо
Я хочу, чтобы ты поверил, что моя любовь готова быть только смелой...
Статья подошла к концу пением «Метеоритный дождь». Жизнь, как падающая звезда, быстротечна, однако, падающая звезда быстротечна, истина вечна...