在 Javascript 中调整重复图像的大小
Resize Repeated Image in Javascript
我的代码使用二维数组来知道在网格布局上显示什么图像。使用的图像是 repeated.The 图像是在 javascript 文件中用 var ground = new Image()
创建的。我正在尝试调整图像的大小,但我无法弄清楚。我尝试过使用各种组合,例如 ground.value.height="10px"
、ground.height="10px"
、ground.value.height="10"
和 ground.value.height=10
。
更具体地说,我想要的是图像的大小 canvas 除以二维数组的相关维度。即网格中的图块大小可以是 10px x 10px,我希望图像大小相同。如果它按照我认为的方式运行,那么当图像重复时,每个图块都应该重复显示的图像。
var gameContext = null;
var gameMap = [
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
var mapW = 10,
mapH = 10;
var boxEdge = window.innerWidth / mapW / 2;
var tileW = boxEdge,
tileH = boxEdge;
var currentSecond = 0,
frameCount = 0,
framesLastSecond = 0;
var ground = new Image();
ground.src = "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/65614919-0734-4dc8-9460-7034fd979346/dbg8qqd-0fb0aced-d05c-4df6-a7c6-b8e04c184ac5.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzY1NjE0OTE5LTA3MzQtNGRjOC05NDYwLTcwMzRmZDk3OTM0NlwvZGJnOHFxZC0wZmIwYWNlZC1kMDVjLTRkZjYtYTdjNi1iOGUwNGMxODRhYzUucG5nIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.9IQbxC3HC3uuJLf8V9Ridq005b2_-4zFg6Cb9rJ2tbw";
var wall = new Image();
wall.src = "data:image/png;base64,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";
window.onload = function() {
gameCanvas = document.getElementById("game");
gameContext = gameCanvas.getContext("2d");
gameCanvas.width = window.innerWidth / 2;
gameCanvas.height = window.innerWidth / 2;
/*gameContext = document.getElementById('game').getContext("2d");
gameContext.font = "bold 10pt sans-serif";*/
requestAnimationFrame(drawGame);
};
function drawGame() {
var groundPattern = gameContext.createPattern(ground, "repeat");
var wallPattern = gameContext.createPattern(wall, "repeat");
if (gameContext == null) {
return;
}
var sec = Math.floor(Date.now() / 1000);
if (sec != currentSecond) {
currentSecond = sec;
framesLastSecond = frameCount;
frameCount = 1;
} else {
frameCount++;
}
for (var y = 0; y < mapH; ++y) {
for (var x = 0; x < mapW; ++x) {
switch (gameMap[y][x]) {
case 0:
gameContext.fillStyle = wallPattern;
break;
default:
gameContext.fillStyle = groundPattern;
//gameContext.fillStyle = "#5aa457";
}
gameContext.fillRect(x * tileW, y * tileH, tileW, tileH);
}
}
//gameContext.fillStyle = "#ff0000";
//gameContext.fillText("FPS: " + framesLastSecond, 10, 20);
requestAnimationFrame(drawGame);
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body style="background-color:powderblue;">
<script src="script.js"></script>
<canvas id="game"></canvas>
</body>
</html>
您可以将图块绘制为缩放图像而不是图案:
ctx.drawImage(
imgAsset.img,
col * tile.width,
row * tile.height,
tile.width,
tile.height
);
此示例使用 CanvasRenderingContext2D.drawImage()
的第二个构造函数:
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
在下面的示例中,我添加了资产查找地图以提高效率。您可以添加额外的图像资源并相应地更新您的瓷砖地图。该代码仍然有效。
const assets = {
images: {
wall: {
id: 0,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850378944653164604/wall.png'
},
ground: {
id: 1,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850378948168384562/ground.png'
},
water: {
id: 2,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850398765726302298/water.png'
}
}
};
const imgKeyLookup = Object.entries(assets.images)
.reduce((acc, [key, { id }]) => acc.set(id, key), new Map);
const getImageAsset = id => assets.images[imgKeyLookup.get(id)];
let currentSecond = 0, frameCount = 0, framesLastSecond = 0;
const tileMap = [
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 2, 2, 2, 1, 1, 0],
[0, 1, 0, 1, 2, 2, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
const ctx = document.querySelector('#game').getContext('2d');
const grid = { rows: tileMap.length, cols: tileMap[0].length };
const boxEdge = window.innerWidth / grid.cols / 2;
const tile = { width: boxEdge, height: boxEdge };
const loadImage = (url) => new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.addEventListener('error', (err) => reject(err));
img.src = url;
});
const main = () => {
Object.assign(ctx.canvas, {
width: window.innerWidth / 2,
height: window.innerWidth / 2
});
requestAnimationFrame(drawGame);
};
function drawGame() {
const sec = Math.floor(Date.now() / 1000);
if (sec != currentSecond) {
currentSecond = sec;
framesLastSecond = frameCount;
frameCount = 1;
} else {
frameCount++;
}
for (let row = 0; row < grid.rows; row++) {
for (let col = 0; col < grid.cols; col++) {
const imgAsset = getImageAsset(tileMap[row][col]);
if (imgAsset) {
ctx.drawImage(imgAsset.img,
col * tile.width, row * tile.height,
tile.width, tile.height);
}
}
}
requestAnimationFrame(drawGame);
};
const imageAssets = Object.values(assets.images);
Promise.all(imageAssets.map(({ url }) => url).map(loadImage))
.then(imgArr => imgArr.forEach((img, index) => {
Object.assign(imageAssets[index], { img });
}))
.then(main);
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
background-color: powderblue;
align-items: center;
justify-content: center;
}
<canvas id="game"></canvas>
设置 Image 构造函数的 width
和 height
不会调整您的图块图像的大小(如下所示)。
const assets = {
images: {
wall: {
id: 0,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850378944653164604/wall.png'
},
ground: {
id: 1,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850378948168384562/ground.png'
}
}
};
const imgKeyLookup = Object.entries(assets.images)
.reduce((acc, [key, { id }]) => acc.set(id, key), new Map);
const getImageAsset = id => assets.images[imgKeyLookup.get(id)];
let currentSecond = 0, frameCount = 0, framesLastSecond = 0;
const tileMap = [
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
const ctx = document.querySelector('#game').getContext('2d');
const grid = { rows: tileMap.length, cols: tileMap[0].length };
const boxEdge = window.innerWidth / grid.cols / 2;
const tile = { width: boxEdge, height: boxEdge };
const loadImage = (url) => new Promise((resolve, reject) => {
const img = new Image(tile.width, tile.height);
img.addEventListener('load', () => resolve(img));
img.addEventListener('error', (err) => reject(err));
img.src = url;
});
const main = () => {
Object.entries(assets.images).forEach(([key, value]) =>
Object.assign(value, {
pattern: ctx.createPattern(value.img, 'repeat')
}));
Object.assign(ctx.canvas, {
width: window.innerWidth / 2,
height: window.innerWidth / 2
});
requestAnimationFrame(drawGame);
};
function drawGame() {
const sec = Math.floor(Date.now() / 1000);
if (sec != currentSecond) {
currentSecond = sec;
framesLastSecond = frameCount;
frameCount = 1;
} else {
frameCount++;
}
for (let row = 0; row < grid.rows; row++) {
for (let col = 0; col < grid.cols; col++) {
const imgAsset = getImageAsset(tileMap[row][col]);
if (imgAsset) {
ctx.fillStyle = imgAsset.pattern;
ctx.fillRect(col * tile.width, row * tile.height, tile.width, tile.height);
}
}
}
requestAnimationFrame(drawGame);
};
const imageAssets = Object.values(assets.images);
Promise.all(imageAssets.map(({ url }) => url).map(loadImage))
.then(imgArr => imgArr.forEach((img, index) => {
Object.assign(imageAssets[index], { img });
}))
.then(main);
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
background-color: powderblue;
align-items: center;
justify-content: center;
}
<canvas id="game"></canvas>
图像的大小应该传递给构造函数。
如果你想要 10px 的 10px 图片,你需要写:
var image = new Image(10, 10)
Based on the https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image
我的代码使用二维数组来知道在网格布局上显示什么图像。使用的图像是 repeated.The 图像是在 javascript 文件中用 var ground = new Image()
创建的。我正在尝试调整图像的大小,但我无法弄清楚。我尝试过使用各种组合,例如 ground.value.height="10px"
、ground.height="10px"
、ground.value.height="10"
和 ground.value.height=10
。
更具体地说,我想要的是图像的大小 canvas 除以二维数组的相关维度。即网格中的图块大小可以是 10px x 10px,我希望图像大小相同。如果它按照我认为的方式运行,那么当图像重复时,每个图块都应该重复显示的图像。
var gameContext = null;
var gameMap = [
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
var mapW = 10,
mapH = 10;
var boxEdge = window.innerWidth / mapW / 2;
var tileW = boxEdge,
tileH = boxEdge;
var currentSecond = 0,
frameCount = 0,
framesLastSecond = 0;
var ground = new Image();
ground.src = "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/65614919-0734-4dc8-9460-7034fd979346/dbg8qqd-0fb0aced-d05c-4df6-a7c6-b8e04c184ac5.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzY1NjE0OTE5LTA3MzQtNGRjOC05NDYwLTcwMzRmZDk3OTM0NlwvZGJnOHFxZC0wZmIwYWNlZC1kMDVjLTRkZjYtYTdjNi1iOGUwNGMxODRhYzUucG5nIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.9IQbxC3HC3uuJLf8V9Ridq005b2_-4zFg6Cb9rJ2tbw";
var wall = new Image();
wall.src = "data:image/png;base64,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";
window.onload = function() {
gameCanvas = document.getElementById("game");
gameContext = gameCanvas.getContext("2d");
gameCanvas.width = window.innerWidth / 2;
gameCanvas.height = window.innerWidth / 2;
/*gameContext = document.getElementById('game').getContext("2d");
gameContext.font = "bold 10pt sans-serif";*/
requestAnimationFrame(drawGame);
};
function drawGame() {
var groundPattern = gameContext.createPattern(ground, "repeat");
var wallPattern = gameContext.createPattern(wall, "repeat");
if (gameContext == null) {
return;
}
var sec = Math.floor(Date.now() / 1000);
if (sec != currentSecond) {
currentSecond = sec;
framesLastSecond = frameCount;
frameCount = 1;
} else {
frameCount++;
}
for (var y = 0; y < mapH; ++y) {
for (var x = 0; x < mapW; ++x) {
switch (gameMap[y][x]) {
case 0:
gameContext.fillStyle = wallPattern;
break;
default:
gameContext.fillStyle = groundPattern;
//gameContext.fillStyle = "#5aa457";
}
gameContext.fillRect(x * tileW, y * tileH, tileW, tileH);
}
}
//gameContext.fillStyle = "#ff0000";
//gameContext.fillText("FPS: " + framesLastSecond, 10, 20);
requestAnimationFrame(drawGame);
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body style="background-color:powderblue;">
<script src="script.js"></script>
<canvas id="game"></canvas>
</body>
</html>
您可以将图块绘制为缩放图像而不是图案:
ctx.drawImage(
imgAsset.img,
col * tile.width,
row * tile.height,
tile.width,
tile.height
);
此示例使用 CanvasRenderingContext2D.drawImage()
的第二个构造函数:
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
在下面的示例中,我添加了资产查找地图以提高效率。您可以添加额外的图像资源并相应地更新您的瓷砖地图。该代码仍然有效。
const assets = {
images: {
wall: {
id: 0,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850378944653164604/wall.png'
},
ground: {
id: 1,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850378948168384562/ground.png'
},
water: {
id: 2,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850398765726302298/water.png'
}
}
};
const imgKeyLookup = Object.entries(assets.images)
.reduce((acc, [key, { id }]) => acc.set(id, key), new Map);
const getImageAsset = id => assets.images[imgKeyLookup.get(id)];
let currentSecond = 0, frameCount = 0, framesLastSecond = 0;
const tileMap = [
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 2, 2, 2, 1, 1, 0],
[0, 1, 0, 1, 2, 2, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
const ctx = document.querySelector('#game').getContext('2d');
const grid = { rows: tileMap.length, cols: tileMap[0].length };
const boxEdge = window.innerWidth / grid.cols / 2;
const tile = { width: boxEdge, height: boxEdge };
const loadImage = (url) => new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.addEventListener('error', (err) => reject(err));
img.src = url;
});
const main = () => {
Object.assign(ctx.canvas, {
width: window.innerWidth / 2,
height: window.innerWidth / 2
});
requestAnimationFrame(drawGame);
};
function drawGame() {
const sec = Math.floor(Date.now() / 1000);
if (sec != currentSecond) {
currentSecond = sec;
framesLastSecond = frameCount;
frameCount = 1;
} else {
frameCount++;
}
for (let row = 0; row < grid.rows; row++) {
for (let col = 0; col < grid.cols; col++) {
const imgAsset = getImageAsset(tileMap[row][col]);
if (imgAsset) {
ctx.drawImage(imgAsset.img,
col * tile.width, row * tile.height,
tile.width, tile.height);
}
}
}
requestAnimationFrame(drawGame);
};
const imageAssets = Object.values(assets.images);
Promise.all(imageAssets.map(({ url }) => url).map(loadImage))
.then(imgArr => imgArr.forEach((img, index) => {
Object.assign(imageAssets[index], { img });
}))
.then(main);
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
background-color: powderblue;
align-items: center;
justify-content: center;
}
<canvas id="game"></canvas>
设置 Image 构造函数的 width
和 height
不会调整您的图块图像的大小(如下所示)。
const assets = {
images: {
wall: {
id: 0,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850378944653164604/wall.png'
},
ground: {
id: 1,
url: 'https://cdn.discordapp.com/attachments/808770424535777302/850378948168384562/ground.png'
}
}
};
const imgKeyLookup = Object.entries(assets.images)
.reduce((acc, [key, { id }]) => acc.set(id, key), new Map);
const getImageAsset = id => assets.images[imgKeyLookup.get(id)];
let currentSecond = 0, frameCount = 0, framesLastSecond = 0;
const tileMap = [
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
const ctx = document.querySelector('#game').getContext('2d');
const grid = { rows: tileMap.length, cols: tileMap[0].length };
const boxEdge = window.innerWidth / grid.cols / 2;
const tile = { width: boxEdge, height: boxEdge };
const loadImage = (url) => new Promise((resolve, reject) => {
const img = new Image(tile.width, tile.height);
img.addEventListener('load', () => resolve(img));
img.addEventListener('error', (err) => reject(err));
img.src = url;
});
const main = () => {
Object.entries(assets.images).forEach(([key, value]) =>
Object.assign(value, {
pattern: ctx.createPattern(value.img, 'repeat')
}));
Object.assign(ctx.canvas, {
width: window.innerWidth / 2,
height: window.innerWidth / 2
});
requestAnimationFrame(drawGame);
};
function drawGame() {
const sec = Math.floor(Date.now() / 1000);
if (sec != currentSecond) {
currentSecond = sec;
framesLastSecond = frameCount;
frameCount = 1;
} else {
frameCount++;
}
for (let row = 0; row < grid.rows; row++) {
for (let col = 0; col < grid.cols; col++) {
const imgAsset = getImageAsset(tileMap[row][col]);
if (imgAsset) {
ctx.fillStyle = imgAsset.pattern;
ctx.fillRect(col * tile.width, row * tile.height, tile.width, tile.height);
}
}
}
requestAnimationFrame(drawGame);
};
const imageAssets = Object.values(assets.images);
Promise.all(imageAssets.map(({ url }) => url).map(loadImage))
.then(imgArr => imgArr.forEach((img, index) => {
Object.assign(imageAssets[index], { img });
}))
.then(main);
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
background-color: powderblue;
align-items: center;
justify-content: center;
}
<canvas id="game"></canvas>
图像的大小应该传递给构造函数。
如果你想要 10px 的 10px 图片,你需要写:
var image = new Image(10, 10)
Based on the https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image