Я делаю проект, в котором мне нужно создать 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, но ни одна из них не сработала.
Я также вижу проблему в том, что вы вызываете метод draw
несколько раз подряд. Таким образом, вы создаете кучу new Image("images.png")
объектов, что довольно расточительно. Вы также никогда не ждете загрузки изображения (т. е. никогда не ждете события load
). Вероятно, лучше переключиться на синтаксис class
и создать одно приватное поле #image = new Image("images.png");
, на которое можно ссылаться с помощью this.#image
.
Спасибо за предложения, я добавил для него события загрузки, но он все еще не работает.
Вы можете создать новый образ с помощью конструктора 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>
Внутри функции
animate
вы немедленно снова вызываетеanimate
, чтобы войти в рекурсивный цикл. Это не позволяетsetInterval
вызыватьanimate
каждую секунду. То же самое касаетсяrequestAnimationFrame(animate)
в конце вашего кода.