Почему мой js для создания дождевых бабочек не работает?

Я делаю проект, в котором мне нужно создать html-холст с изображением дождевой бабочки. Вот мой js:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
let img = new Image("images.png")
var ok2animate = true;
img.onload = function(){
function Drop() {
    this.x = Math.random() * (canvas.width - 20);
    this.y = -Math.random() * 20;
    this.fallRate = Math.random()*.5+.5;
}
//
Drop.prototype.draw = function () {
  //   this.x;
  // this.y;
  
  ctx.drawImage(img, this.x, this.y)
    return (this);
}
//
Drop.prototype.fall = function () {
    this.y += this.fallRate;
    return (this);
}

function animate() {

    // request another animation frame
    if (ok2animate) {
        requestAnimationFrame(animate);
    }

  
        ctx.fillRect(0,0,canvas.width,canvas.height)
    //ctx.clearRect(0, 0, canvas.width, canvas.height);

    // make all drops fall and then redraw them
    
    for (var i = 0; i < drops.length; i++) {
        drops[i].fall().draw();
    }

}





// an array of objects each representing 1 drop
var drops = [];

// add some test drops
for (var i = 0; i < 10; i++) {
    drops.push(new Drop());
}
setInterval(function(){requestAnimationFrame(animate)}, 1000)
requestAnimationFrame(animate)
}
<canvas id = "canvas" width=300 height=300></canvas>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Как сделать так, чтобы изображения сыпались с интервалом в 1 секунду? (Я включил файл изображения в ту же папку) Я пытался использовать файл изображения из Интернета, используя холст большего размера, используя другие версии jquery, но ни одна из них не сработала.

Внутри функции animate вы немедленно снова вызываете animate, чтобы войти в рекурсивный цикл. Это не позволяет setInterval вызывать animate каждую секунду. То же самое касается requestAnimationFrame(animate) в конце вашего кода.

Emiel Zuurbier 16.03.2022 22:58

Я также вижу проблему в том, что вы вызываете метод draw несколько раз подряд. Таким образом, вы создаете кучу new Image("images.png") объектов, что довольно расточительно. Вы также никогда не ждете загрузки изображения (т. е. никогда не ждете события load). Вероятно, лучше переключиться на синтаксис class и создать одно приватное поле #image = new Image("images.png");, на которое можно ссылаться с помощью this.#image.

Sebastian Simon 16.03.2022 23:02

Спасибо за предложения, я добавил для него события загрузки, но он все еще не работает.

lolBOT V9.17 17.03.2022 00:07
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
41
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Создание образа

Вы можете создать новый образ с помощью конструктора Image. Вы уже сделали это, однако конструктор принимает аргументы width и height изображения, а не URL. Вам нужно свойство src изображения, чтобы ссылаться на файл изображения.

И поскольку вы используете только одно изображение, оно не меняется, вам нужно создать и загрузить его только один раз. Вы можете повторно использовать одно и то же изображение столько раз, сколько захотите.

Запуск цикла

Теперь вам нужно запустить цикл после, чтобы все изображения (в данном случае одно) были загружены. Прослушивайте событие onload на изображении и вызывайте функцию setInterval всякий раз, когда изображение загружается.
setInterval начнет рендеринг здесь, поэтому нет необходимости вызывать requestAnimationFrame(animate) где-либо еще.

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

// Create the image like this.
const image = new Image(100, 100);
image.src = "https://www.fillmurray.com/100/100";

function Drop() {
  this.x = Math.random() * (canvas.width - 20);
  this.y = -Math.random() * 20;
  this.fallRate = Math.random() * 10 + 0.5;
}

Drop.prototype.draw = function() {
  ctx.drawImage(image, this.x, this.y)
  return this;
}

Drop.prototype.fall = function() {
  this.y += this.fallRate;
  return this;
}

const drops = [];
for (let i = 0; i < 10; i++) {
  drops.push(new Drop());
}

function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillRect(0, 0, canvas.width, canvas.height)

  for (const drop of drops) {
    drop.fall().draw();
  }
}

image.onload = () => {
  setInterval(function() {
    requestAnimationFrame(animate)
  }, 1000)
};
<canvas id = "canvas" width=300 height=300></canvas>

Другие вопросы по теме