簡體   English   中英

從對象屬性在畫布上繪制圖像

[英]Draw an image on a Canvas from an Object property

我想在每次迭代時在畫布上繪制圖像,圖像來自對象。 我在控制台中收到“不是HTML格式的信息...”,或者什么也沒有,它阻止了循環。

有沒有一種方法可以在畫布上繪制圖像而無需先將其放在index.html上,也可以不從URL加載?

我嘗試了兩種標准解決方案,但它們沒有起作用。

使用包含圖像的對象屬性將其繪制在畫布上時,我沒有發現類似的問題。

function Board(width, height) {
    this.width = width;
    this.height = height;
    this.chartBoard = [];

    // Création du plateau logique
    for (var i = 0; i < this.width; i++) {
        const row = [];
        this.chartBoard.push(row);
        for (var j = 0; j < this.height; j++) {
            const col = {};
            row.push(col);
        }
    }
}
let board = new Board(10, 10);
console.log(board);

// CONTEXT OF THE CANVAS
const ctx = $('#board').get(0).getContext('2d');

Board.prototype.drawBoard = function () {
    for (var i = 0; i < this.width; i++) {
        for (var j = 0; j < this.height; j++) {
            ctx.beginPath();
            ctx.strokeStyle = 'black';
            ctx.strokeRect(j * 64, i * 64, 64, 64);
            ctx.closePath();
        }
    }
};

board.drawBoard();



Board.prototype.test = test;

function test() {
    console.log(this);
}


// OBJECT TO DRAW
function Obstacle(name, sprite) {
    this.name = name;
    this.sprite = sprite;
}

const lava = new Obstacle("Lave", "assets/lave.png");
const lava1 = new Obstacle("Lave1", "assets/lave.png");
const lava2 = new Obstacle("Lave2", "assets/lave.png");
const lava3 = new Obstacle("Lave3", "assets/lave.png");
const lava4 = new Obstacle("Lave4", "assets/lave.png");
const lava5 = new Obstacle("Lave5", "assets/lave.png");
const lava6 = new Obstacle("Lave6", "assets/lave.png");
const lava7 = new Obstacle("Lave7", "assets/lave.png");
const lava8 = new Obstacle("Lave8", "assets/lave.png");
const lava9 = new Obstacle("Lave9", "assets/lave.png");
const lavaArray = [lava, lava1, lava2, lava3, lava4, lava5, lava6, lava7, lava8, lava9];


// FUNCTION TO DRAW

Board.prototype.setPiece = function (piece) {

    let randomX = Math.floor(Math.random() * board.width);
    let randomY = Math.floor(Math.random() * board.height);

    let drawX = randomX * 64;
    let drawY = randomY * 64;


    if (randomX >= this.width || randomY >= this.height) {
        throw new Error('Pièce hors limite');
    }

    if (piece instanceof Obstacle) {

        if (!(this.chartBoard[randomY][randomX] instanceof Obstacle)) {
            this.chartBoard[randomY][randomX] = piece;

            // CODE TO DRAW, BUG DOESN'T WORK
            ctx.fillRect(drawX, drawY,64,64);
            let image = Obstacle.sprite;
            ctx.drawImage = (image, drawX, drawY);
        }
    } 

    } else {
        throw new Error('Pièce non valide');
    }
};

Board.prototype.setObstacles = function () {
    for (let lava of lavaArray) {

        const obstacle = board.setPiece(lava);
    }
};
board.setObstacles();

實際:未繪制圖像。 如果我嘗試fillRect,它會很好地工作。 這樣循環就可以了。

預期:能夠通過對象屬性在畫布上繪制圖像。

目前尚不清楚您要做什么。

您已評論的代碼

ctx.drawImage = (image, drawX, drawY);

應該是這個

ctx.drawImage(image, drawX, drawY);

看得更廣一點,你有這個

let image = Obstacle.sprite;
ctx.drawImage(image, drawX, drawY);  // assume this was fixed

但是Obstacle是一個類,而不是該類的實例。 你要

let image = piece.sprite;
ctx.drawImage(image, drawX, drawY);

但這導致下一個問題。 查看代碼piece.sprite的其余部分piece.sprite是一個字符串而不是圖像。 請參閱此代碼。

// OBJECT TO DRAW
function Obstacle(name, sprite) {
    this.name = name;
    this.sprite = sprite;
}

const lava = new Obstacle("Lave", "assets/lave.png");

有幾種方法可以將圖像繪制到畫布上。 如果它們來自文件,則必須等待它們下載。 否則,您可以從另一個畫布生成它們。 您還可以使用createImageDataputImageData作為制作圖像的另一種方法。

讓我們更改代碼以加載一堆圖像,然后開始

我將所有類代碼移至頂部,將啟動代碼移至底部。

有內部一些地方Board的方法,其中的全局變量board來代替this ,所以我固定的。

這是一個加載圖像並返回Promise的函數

function loadImage(url) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => { resolve(img); };
    img.onerror = reject;
    img.crossOrigin = 'anonymous';  // REMOVE IF SAME DOMAIN!
    img.src = url;
  });
}

您可以使用它加載這樣的一張圖像

loadImage(urlOfImage).then(function(img) {
  // use the loaded img
});

我使用該函數編寫了該函數,該函數將名稱對象傳遞給url,然后將名稱對象返回給加載的圖像。

function loadImages(images) {
  return new Promise((resolve) => {
    const loadedImages = {};
    const imagePromises = Object.entries(images).map((keyValue) => {
      const [name, url] = keyValue;
      return loadImage(url).then((img) => {
         loadedImages[name] = img;
      });
    });
    Promise.all(imagePromises).then(() => {
      resolve(loadedImages);
    });
  });
}

然后,我將其調用,並將名稱對象傳遞給已加載的圖像到start函數。 目前僅加載一個圖像,但您可以添加更多圖像。

const images = {
  lave: 'https://i.imgur.com/enx5Xc8.png',
  // player: 'foo/player.png',
  // enemy: 'foo/enemny.png',
};
loadImages(images).then(start);

 // CONTEXT OF THE CANVAS const ctx = $('#board').get(0).getContext('2d'); function Board(width, height) { this.width = width; this.height = height; this.chartBoard = []; // Création du plateau logique for (var i = 0; i < this.width; i++) { const row = []; this.chartBoard.push(row); for (var j = 0; j < this.height; j++) { const col = {}; row.push(col); } } } Board.prototype.drawBoard = function () { for (var i = 0; i < this.width; i++) { for (var j = 0; j < this.height; j++) { ctx.beginPath(); ctx.strokeStyle = 'black'; ctx.strokeRect(j * 64, i * 64, 64, 64); ctx.closePath(); } } }; // OBJECT TO DRAW function Obstacle(name, sprite) { this.name = name; this.sprite = sprite; } // FUNCTION TO DRAW Board.prototype.setPiece = function (piece) { let randomX = Math.floor(Math.random() * this.width); let randomY = Math.floor(Math.random() * this.height); let drawX = randomX * 64; let drawY = randomY * 64; if (randomX >= this.width || randomY >= this.height) { throw new Error('Pièce hors limite'); } if (piece instanceof Obstacle) { if (!(this.chartBoard[randomY][randomX] instanceof Obstacle)) { this.chartBoard[randomY][randomX] = piece; // CODE TO DRAW, BUG DOESN'T WORK ctx.fillRect(drawX, drawY,64,64); let image = piece.sprite; ctx.drawImage(image, drawX, drawY); } } else { throw new Error('Pièce non valide'); } }; Board.prototype.setObstacles = function (lavaArray) { for (let lava of lavaArray) { const obstacle = this.setPiece(lava); } }; function start(images) { let board = new Board(10, 10); // console.log(board); const lava = new Obstacle("Lave", images.lave); const lava1 = new Obstacle("Lave1", images.lave); const lava2 = new Obstacle("Lave2", images.lave); const lava3 = new Obstacle("Lave3", images.lave); const lava4 = new Obstacle("Lave4", images.lave); const lava5 = new Obstacle("Lave5", images.lave); const lava6 = new Obstacle("Lave6", images.lave); const lava7 = new Obstacle("Lave7", images.lave); const lava8 = new Obstacle("Lave8", images.lave); const lava9 = new Obstacle("Lave9", images.lave); const lavaArray = [lava, lava1, lava2, lava3, lava4, lava5, lava6, lava7, lava8, lava9]; board.drawBoard(); board.setObstacles(lavaArray); } function loadImage(url) { return new Promise((resolve, reject) => { const img = new Image(); img.onload = () => { resolve(img); }; img.onerror = reject; img.crossOrigin = 'anonymous'; // REMOVE IF SAME DOMAIN! img.src = url; }); } function loadImages(images) { return new Promise((resolve) => { const loadedImages = {}; // for each name/url pair in image make a promise to load the image // by calling loadImage const imagePromises = Object.entries(images).map((keyValue) => { const [name, url] = keyValue; // load the image and when it's finished loading add the name/image // pair to loadedImages return loadImage(url).then((img) => { loadedImages[name] = img; }); }); // wait for all the images to load then pass the name/image object Promise.all(imagePromises).then(() => { resolve(loadedImages); }); }); } const images = { lave: 'https://i.imgur.com/enx5Xc8.png', // player: 'foo/player.png', // enemy: 'foo/enemny.png', }; loadImages(images).then(start); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <canvas id="board" width="640" height="640"></canvas> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM