[英]Issue drawing multiple Images on Canvas with drawImage()
我只是無法讓它為我工作。
我正在嘗試使用drawImage()將多個圖像繪制到畫布上。 我覺得自己在很大程度上忽略了一些東西。
它應該在畫布上繪制18張卡片。 它將從左側開始50px,從頂部開始向下,並繪制100w * 150h的每張卡片。 每個卡片圖片之間應有25px。 畫布尺寸設置為825w * 600h。
嘗試使用簡單的Javascript(不使用jQuery)完成此任務。 任何幫助表示贊賞。
// Draw the cards to the canvas.
function drawCards()
{
// Starting positions.
var x = 50;
var y = 50;
// Counter that will hold current card position.
var cardCount = 0;
var img = new Image(100, 150);
// How many rows.
for (var row = 0; row < 3; row++)
{
// How many columns.
for (var column = 0; column < 6; column++)
{
// Store the current card.
var card = memoryDeck[cardCount];
// Check if the card is flipped, if it is set an image with url to face card.
if (card.flipped == true)
{
img.onload = function() {
ctx.drawImage(this, x, y, 100, 150);
}
img.src = card.faceImage;
}
// Otherwise set image url to back of card.
else
{
img.onload = function() {
ctx.drawImage(this, x, y, 100, 150);
}
img.src = card.backImage;
}
// Increase the x position (the width of a card, plus the space in between), and the current card position being stored.
x += 125;
cardCount++;
}
// We are on a new row, reset the column card position and increase the row card position.
x = 50;
y += 175;
}
}
JS變量的作用域不是阻塞,而是作用域。 因此,當img.onload訪問x
和y
,它們引用x
和y
的最終值。 要創建塊作用域變量,請使用let語句或IIFE。
// Draw the cards to the canvas.
function drawCards()
{
// Starting positions.
var x = 50;
var y = 50;
// Counter that will hold current card position.
var cardCount = 0;
var img = new Image(100, 150);
// How many rows.
for (var row = 0; row < 3; row++)
{
// How many columns.
for (var column = 0; column < 6; column++)
{
// Store the current card.
var card = memoryDeck[cardCount];
// Check if the card is flipped, if it is set an image with url to face card.
if (card.flipped == true)
{
(function(x, y) {
img.onload = function() {
ctx.drawImage(this, x, y, 100, 150);
}
img.src = card.faceImage;
})(x, y);
}
// Otherwise set image url to back of card.
else
{
(function(x, y) {
img.onload = function() {
ctx.drawImage(this, x, y, 100, 150);
}
img.src = card.backImage;
})(x, y);
}
// Increase the x position (the width of a card, plus the space in between), and the current card position being stored.
x += 125;
cardCount++;
}
// We are on a new row, reset the column card position and increase the row card position.
x = 50;
y += 175;
}
}
一個類似的簡單問題是:
READ THE SOURCE CODE! <script> function demo1() { for (var i = 0; i <= 5; i++) { setTimeout(function(){alert('i === ' + i)}, i * 200); } // i === 6 // You expect this to happen: // [alerts "i === 1"] // [alerts "i === 2"] // [alerts "i === 3"] // [alerts "i === 4"] // [alerts "i === 5"] // What actually happens: // [alerts "i === 6"] // [alerts "i === 6"] // [alerts "i === 6"] // [alerts "i === 6"] // [alerts "i === 6"] // [alerts "i === 6"] } </script> <button onclick="demo1();">Demo 1 </button> <script> function demo2(){ for (var i = 0; i <= 5; i++) { // IIFE for the win! (function(i) { setTimeout(function(){alert('i === ' + i)}, i * 200); })(i); } // Expected: // [alerts "i === 0"] // [alerts "i === 1"] // [alerts "i === 2"] // [alerts "i === 3"] // [alerts "i === 4"] // [alerts "i === 5"] // Actual: // [alerts "i === 0"] // [alerts "i === 1"] // [alerts "i === 2"] // [alerts "i === 3"] // [alerts "i === 4"] // [alerts "i === 5"] } </script> <button onclick="demo2();">Demo 2</button>
給定的答案是有問題的,因為它在循環中聲明了函數調用。 這種聲明方式很危險,如果您不了解閉包,可能會導致內存泄漏。 用於克服范圍問題的方法效率也很低。 而且該代碼將不起作用,因為僅創建了一個圖像,並且每次設置src時,都會取消先前的加載src並重新開始該過程。
另外,創建匿名函數會使調試代碼更加困難,因為任何錯誤都將使跟蹤變得困難,並且分析也將難以閱讀。 始終命名函數,並將函數始終放在其作用域的頂部。
function drawCards(){
// declare all variables and functions
var row, column, src, cardIndex, card;
function loadThenDisplayImage (src, x, y) {
var image;
function onImageload () {
ctx.drawImage(this, x, y, cardW, cardH);
}
image = new Image(cardW, cardH);
image.src = src;
image.onload = onImageLoad;
}
// define constants and variables.
const left = 50;
const top = 50;
const cardW = 100;
const cardH = 150;
const xSpacing = 25;
const ySpacing = 25;
cardIndex= 0;
// function logic
for (row = 0; row < 3; row += 1) {
for (column = 0; column < 6; column += 1) {
card = memoryDeck[cardIndex += 1];
scr = card.flipped ? card.faceImage : card.backImage;
loadThenDisplayImage( // long function call best split for readbility
src,
left + (cardW + xSpacing) * column,
top + (cardH + ySpacing) * row
);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.