How do i load any number of images onto the canvas. The number can be 5,6... how can i do that.So far i am only able to load 2 images but this code will not work for dynamic number of images.The code should be such that it should load many images.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var availableTags = <?php echo json_encode($img_arr1) ?>;
var sources = {
darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg',
yoda: 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg'
};
loadImages(sources, function(images) {
context.drawImage(images.darthVader, 100, 30, 200, 137);
context.drawImage(images.yoda, 350, 55, 93, 104);
});
</script>
</body>
</html>
Save relevant data as list of objects and loop through them:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var availableTags = <?php echo json_encode($img_arr1) ?>;
var sourceSets = [];
var sources = {};
//Draw function
function draw() {
//Clear board
context.clearRect(-10, -10, 4000, 4000);
//Loop through images and draw each one
for (var i = 0; i < sourceSets.length; i++) {
context.drawImage(sourceSets[i].img, sourceSets[i].x, sourceSets[i].y, sourceSets[i].w, sourceSets[i].h);
}
}
function loadSource(src, x, y, w, h) {
//Setting defaults
if (src === void 0) {
src = '';
}
if (x === void 0) {
x = 0;
}
if (y === void 0) {
y = 0;
}
if (w === void 0) {
w = 100;
}
if (h === void 0) {
h = 100;
}
//Creating image and loading from src
if(sources[src] === void 0) {
sources[src] = new Image();
sources[src].onload = function () {
draw();
};
sources[src].src = src;
}
var img = sources[src];
img.src = src;
//Save all relevant data in an object
sourceSets.push({
src : src,
x : x,
y : y,
w : w,
h : h,
img : img
});
}
//Add whatever amount of images here
var amount = parseInt(prompt("amount",4));
for(var i = 0; i < amount; i++) {
if(i%2 === 0) {
loadSource('http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg', Math.random() * 400, Math.random() * 400, 200, 137);
} else {
loadSource('http://www.html5canvastutorials.com/demos/assets/yoda.jpg', Math.random() * 400, Math.random() * 400, 93, 104);
}
}
<canvas id="myCanvas" width="600" height="540"></canvas>
Related
So I'm making a game with canvas and my object for one of the characters aren't showing up. My console didn't show any errors so I just decided to check my asteroidList object. I checked it and saw that the first character in the object's height was undefined, but I already defined it. Can someone tell me what the problem is? Here is my code:
var c = document.getElementById("game");
var ctx = c.getContext("2d");
//variables
pX = 1;
pY = 40;
pW = 54.6;
pH = 52.6;
hw = 100;
hh = 10;
asteroidSpeed = 0.05;
//load image sprites
var player = new Image();
var aster = new Image();
var enemy = new Image();
var max = new Image();
var animatedPlayer = new Image();
player.src = "player.png";
aster.src = "aster.png";
enemy.src = "enemy.png";
max.src = "max.png";
animatedPlayer.src = "animatedPlayer.png";
//keys
document.addEventListener("keydown",function (e) {
if (e.keyCode === 83) {
moveDown();
}
else if(e.keyCode === 87) {
moveUp();
}
})
function moveDown() {
pY += 2;
}
function moveUp() {
pY -= 2;
}
//asteroid constructor
asteroidList = {};
function asteroid(id,x,y,img,width,height) {
var asteroid = {
x:x,
y:y,
width:width,
height:height,
id:id
};
asteroidList['A1'] = asteroid;
}
function updateAsteroid(asteroid) {
asteroid.x -= asteroidSpeed;
ctx.drawImage(aster, asteroid.x, asteroid.y, asteroid.width, asteroid.height);
}
function draw() {
ctx.clearRect(0,0,c.width,c.height);
//characters
asteroid('A1', 250, 40, 29.6, 29.3);
ctx.drawImage(player,pX,pY,pW,pH);
setInterval(update, 40);
function update() {
//map collision
if(pY < 0) {
pY = 0;
}
if(pY > 100) {
pY = 100;
}
//enemy loop
for(var key in asteroidList) {
updateAsteroid(asteroidList[key]);
}
}
//hp
ctx.fillStyle = 'green';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.fillRect(199,139,hw,hh);
ctx.strokeRect(199,139,100,10);
//animation call
requestAnimationFrame(draw);
}
</script>
You have an extra param called img in your asteroid function definition:
function asteroid(id, x, y, img, width, height) {
var asteroid = {
x:x,
y:y,
width:width,
height:height,
id:id
};
asteroidList['A1'] = asteroid;
}
So when you call it like:
asteroid('A1', 250, 40, 29.6, 29.3);
// asteroid(id, x, y, img, width);
you are missing to set up the height value and thus getting undefined.
Here is the code I have for now:
<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 2px solid; }
</style>
</head>
<body>
<canvas id="canvas1" width="1650" height="825" style="width: 650px; height: 330px;"></canvas>
<script>
var canvas,ctx,x,y,w,e;
var slikeURL = [
"https://www.a1smallbusinessmarketing.com/images/prosbo_hires.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Wiktionary_small.svg/350px-Wiktionary_small.svg.png",
"http://www.jasonjsmith.com/img/small-business-seo.jpg",
"https://g.twimg.com/business/page/image/11TwitterForSmallBusiness-300_1.png"
]
var slike = slikeURL.map(url=>{var img = new Image(); img.src = url; return img});
function start_canvas()
{
var brojac = 0;
function draw()
{
ctx.drawImage(slike[brojac], x, y);
};
function draw1(w, e)
{
ctx.drawImage(slike[brojac], w, e);
};
function update(time)
{
ctx.clearRect(0,0,canvas.width,canvas.height);
if(w >= x)
{
e += 8;
y += 8;
}
else
{
x -= 4;
w += 4;
};
if(slike){
ctx.drawImage(slike[brojac], x, y);
ctx.drawImage(slike[brojac], w, e);
}
if (e > canvas.height)
{
brojac = (brojac + 1) % slike.length;
x = canvas.width-190;
y = 15;
w = 1;
e = 15;
}
requestAnimationFrame(update)
};
canvas = document.getElementById('canvas1');
x = canvas.width-190;
y = 15;
w = 1;
e = 15;
ctx = canvas.getContext('2d');
requestAnimationFrame(update)
}
window.addEventListener("load",start_canvas);
document.write(brojac);
</script>
</body>
</html>
What I want to happen is that the last two images in the cycle start to slowly disappear (NOT fade out). Here are a few simple images of what I had in mind.
I want the two images to move towards each other like they normally move in the code, but the moment a part of an image crosses the invisible line, that part gets deleted until the whole image disappears, and then the cycle starts over.
I did try to crop the image while it is moving, but I wasn't able to make that work. Any ideas how I can make this?
Simply add an extra clearRect() for the region you want to hide when the criteria (image index) is fulfilled.
var canvas,ctx,x,y,w,e;
var slikeURL = [
"https://www.a1smallbusinessmarketing.com/images/prosbo_hires.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Wiktionary_small.svg/350px-Wiktionary_small.svg.png",
"http://www.jasonjsmith.com/img/small-business-seo.jpg",
"https://g.twimg.com/business/page/image/11TwitterForSmallBusiness-300_1.png"
]
var slike = slikeURL.map(url=>{var img = new Image(); img.src = url; return img});
function start_canvas()
{
var brojac = 0;
function draw()
{
ctx.drawImage(slike[brojac], x, y);
};
function draw1(w, e)
{
ctx.drawImage(slike[brojac], w, e);
};
function update(time)
{
ctx.clearRect(0,0,canvas.width,canvas.height);
if(w >= x)
{
e += 8;
y += 8;
}
else
{
x -= 4;
w += 4;
};
if(slike){
ctx.drawImage(slike[brojac], x, y);
ctx.drawImage(slike[brojac], w, e);
if (brojac > 0) ctx.clearRect(412,0,824,ctx.canvas.height);
}
if (e > canvas.height)
{
brojac = (brojac + 1) % slike.length;
x = canvas.width-190;
y = 15;
w = 1;
e = 15;
}
requestAnimationFrame(update)
};
canvas = document.getElementById('canvas1');
x = canvas.width-190;
y = 15;
w = 1;
e = 15;
ctx = canvas.getContext('2d');
requestAnimationFrame(update)
}
window.addEventListener("load",start_canvas);
document.write(brojac);
canvas{border:#666 2px solid; }
<canvas id="canvas1" width="1650" height="825" style="width: 650px; height: 330px;"></canvas>
(adjust region as needed).
I am developing application in phonegap. When i am running HTML code in browser, image loading in canvas properly but when i am trying to load canvas in android device, not getting always proper result.
HTML Code :
<canvas id="canvas1" width="65" height="300" style="background: #003AFF;"></canvas>
JAVASCRIPT Code :
<script type="text/javascript">
var IMAGE_HEIGHT = 100;
var IMAGE_TOP_MARGIN=0;
var SLOT_SEPARATOR_HEIGHT = 0;
var SLOT_HEIGHT=100;
var ITEM_COUNT=5;
$(document).ready( function() {
document.addEventListener("deviceready", onDeviceReady, true);
});
function onDeviceReady() {
LaodImages();
}
function preloadImages( images, callback ) {
function _preload( asset ) {
asset.img = new Image();
asset.img.src = 'img/' + asset.id+'.png';
asset.img.addEventListener("load", function() {
_check();
}, false);
asset.img.addEventListener("error", function(err) {
_check(err, asset.id);
}, false);
}
var loadc = 0;
function _check( err, id ) {
if ( err ) {
}
loadc++;
if ( images.length == loadc ){
return callback()
}
}
images.forEach(function(asset) {
_preload( asset );
});
}
function LaodImages() {
var game = new Game();
var items = [{id: '10'},{id: '1'},{id: '1'},{id: '1'},{id: '2'},];
$('canvas').attr('height', IMAGE_HEIGHT * ITEM_COUNT * 2);
$('canvas').css('height', IMAGE_HEIGHT * ITEM_COUNT * 2);
preloadImages( items, function() {
function _fill_canvas( canvas, items , can_num) {
ctx = canvas.getContext('2d');
ctx.fillStyle = '#ddd';
for (var i = 0 ; i < ITEM_COUNT ; i++) {
var asset = items[i];
ctx.save();
ctx.shadowColor = "rgba(0,0,0,0.5)";
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 5;
ctx.drawImage(asset.img, 5, i * SLOT_HEIGHT + IMAGE_TOP_MARGIN);
ctx.drawImage(asset.img, 5, (i + ITEM_COUNT) * SLOT_HEIGHT + IMAGE_TOP_MARGIN);
ctx.restore();
ctx.fillRect(0, i * SLOT_HEIGHT, 100, SLOT_SEPARATOR_HEIGHT);
ctx.fillRect(0, (i + ITEM_COUNT) * SLOT_HEIGHT, 100, SLOT_SEPARATOR_HEIGHT);
}
}
_fill_canvas(game.c1[0], items,1);
});
function Game() {
this.c1 = $('#canvas1');
}
}
</script>
Using NodeJS and Socket.io, I'm making a quick canvas app that moves a shape across the screen. This data will appear on all clients. Each square is timestamped to determine draw order.
Below is client.html. It says that I "cannot set property lastUpdate" of undefined. How is it considered undefined? I tried defining it so many times at the top. What's wrong?
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
"use strict";
var canvas;
var ctx;
var socket;
//var lastUpdate = new Date().getTime();
/*var square = {
lastUpdate: new Date().getTime(),
x: 0,
y: 0,
height: 100,
width: 100
};*/
//
//var person = {name: 'user' + (Math.floor((Math.random() * 1000)) + 1)};
//var user = 'user' + (Math.floor((Math.random() * 1000)) + 1);
//var user = Object.keys(something about name);
//var user = Object.keys(user);
//function person(name) {
//this.name = name;
//}
//var user = Object.keys(person);
//lets try using a prototype
/*function user(lastUpdate, x, y, width, height) {
this.lastUpdate = lastUpdate;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}*/
var name = {lastUpdate: new Date().getTime(), x: 0, y: 0, width: 100, height: 100};
var user = Object.keys(name);
var draws = {};
function updatePosition() {
var message = {
xUpdate: 10,
yUpdate: 5
}
socket.emit('movementUpdate', message);
}
/*function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(square.x, square.y, square.width, square.height);
}*/
//
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var keys = Object.keys(draws);
for(var i = 0; i < keys.length; i++)
{
var drawCall = draws[keys[i]];
//order to draw
//gets drawcalls instead of var square
ctx.fillRect(drawCall.x, drawCall.y, drawCall.width, drawCall.height);
}
}
//
function setup() {
var time = new Date().getTime();
//console.log(time);
var x = Math.floor(Math.random()*(300-10) + 10); //random x position
var x = Math.floor(Math.random()*(300-10) + 10); //random y position
draws[user] = {lastUpdate: time, x: x, y: y, width: 100, height: 100};
}
/*function update(data) {
square = data;
redraw();
}*/
//
function handleMessage(data) {
if(!draws[data.name])
{
draws[data.name] = data.coords;
}
else if(data.coords.lastUpdate > draws[data.name].lastUpdate)
{
draws[data.name] = data.coords;
}
draw(); //redraw after updates
}
function init() {
canvas = document.querySelector("#canvas");
ctx = canvas.getContext("2d");
socket = io.connect();
socket.on('connect', function () {
//setInterval(updatePosition, 1000);
setInterval(function()
{
var time = new Date().getTime();
//console.log(time);
console.log(draws);
**draws[user].lastUpdate = time; //lastUpdate is UNDEFINED**
draws[user].x += 5;
socket.emit('draw', {name: user, coords: draws[user]});
draw();
}, 3000);
});
socket.on('updatedDraw', handleMessage);
//socket.on('updatedMovement', updatePosition); //UNDEFINED, used to be 'update'. Could it be 'handleMessage'?
}
window.onload = init;
</script>
</head>
<body>
<canvas id="canvas" height="500" width="500">Please use an HTML 5 browser</canvas>
</body>
</html>
I want to animate 2 figures on my page. Therefore I use Javascript. The problem is that I can't define which "sprite" he has to take. Because I can't add some Parameters like the object "animation" to the gameLoop()-method, because of the requestAnimationFrame. Any idea how I can solve this?
var animation,
image,
canvas,
stopAtLastFrame = false,
amountAnimation = 0,
amountAnimated = 1;
image = new Image();
function sprite (options) {
var that = {},
frameIndex = 0,
currentRow = 0,
currentColumn = 0,
tickCount = 0,
rowOfLastFrame = 0,
columnOfLastFrame = 0,
ticksPerFrame = options.ticksPerFrame,
numberOfFrames = options.numberOfFrames,
numberOfColumns = options.totalColumns,
numberOfRows = options.totalRows,
widthOfOneFrame = options.width/numberOfColumns,
heightOfOneFrame = options.height/numberOfRows;
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
rowOfLastFrame = numberOfRows-1;
columnOfLastFrame = numberOfColumns - 1 - ((numberOfRows *numberOfColumns) - numberOfFrames);
that.render = function () {
that.context.save();
that.context.scale(0.5,0.5);
// Clear the canvas
that.context.clearRect(0, 0, that.width, that.height);
// Draw the animation
that.context.drawImage(
that.image,
currentColumn * widthOfOneFrame,
currentRow * heightOfOneFrame,
widthOfOneFrame,
heightOfOneFrame,
0,
0,
widthOfOneFrame,
heightOfOneFrame);
that.context.restore();
if(rowOfLastFrame==currentRow && columnOfLastFrame==currentColumn && amountAnimated==amountAnimation)
{
stopAtLastFrame=true;
}
};
that.update = function () {
tickCount += 1;
if (tickCount > ticksPerFrame) {
tickCount = 0;
if (frameIndex < numberOfFrames-1) {
frameIndex++;
currentColumn++;
if (currentColumn == numberOfColumns) {
currentRow++;
currentColumn = 0;
}
}else{
amountAnimated++;
frameIndex=0;
currentColumn=0;
currentRow=0;
}
}
};
return that;
}
function gameLoop () {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
window.requestAnimationFrame(gameLoop);
animation.update();
animation.render();
}
}
function startAnimation(canvas, imageUrl, amount){
canvas = document.getElementById(canvas);
canvas.width = 7680/4;
canvas.height = 2880/4;
image.src = imageUrl;
amountAnimation=amount;
animation = sprite({
context: canvas.getContext("2d"),
width: 7684,
height: 2880,
image: image,
numberOfFrames:16,
totalRows : 4,
totalColumns: 4,
ticksPerFrame: 5
});
gameLoop();
}
startAnimation("imageAnimation", "img/16.png", 3);
startAnimation("imageAnimation2", "img/32.png", 5);
In this example I pretend that my spritesheets are the same size and columns, just to test the code.
This doesn't work of course, but this is what I need:
function gameLoop (animation) {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
window.requestAnimationFrame(gameLoop(animation));
animation.update();
animation.render();
}
}
requestAnimationFrame function is not allowed to pass your own parameter, one solution/trick is bound that gameLoop function to sprite object, so that we can access this as sprite object.
as example: http://jsfiddle.net/XQpzU/6110/
Your code can be modified as:
var animation,
image,
canvas,
stopAtLastFrame = false,
amountAnimation = 0,
amountAnimated = 1;
image = new Image();
function sprite (options) {
var that = {},
frameIndex = 0,
currentRow = 0,
currentColumn = 0,
tickCount = 0,
rowOfLastFrame = 0,
columnOfLastFrame = 0,
ticksPerFrame = options.ticksPerFrame,
numberOfFrames = options.numberOfFrames,
numberOfColumns = options.totalColumns,
numberOfRows = options.totalRows,
widthOfOneFrame = options.width/numberOfColumns,
heightOfOneFrame = options.height/numberOfRows;
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
rowOfLastFrame = numberOfRows-1;
columnOfLastFrame = numberOfColumns - 1 - ((numberOfRows *numberOfColumns) - numberOfFrames);
that.render = function () {
that.context.save();
that.context.scale(0.5,0.5);
// Clear the canvas
that.context.clearRect(0, 0, that.width, that.height);
// Draw the animation
that.context.drawImage(
that.image,
currentColumn * widthOfOneFrame,
currentRow * heightOfOneFrame,
widthOfOneFrame,
heightOfOneFrame,
0,
0,
widthOfOneFrame,
heightOfOneFrame);
that.context.restore();
if(rowOfLastFrame==currentRow && columnOfLastFrame==currentColumn && amountAnimated==amountAnimation)
{
stopAtLastFrame=true;
}
};
that.update = function () {
tickCount += 1;
if (tickCount > ticksPerFrame) {
tickCount = 0;
if (frameIndex < numberOfFrames-1) {
frameIndex++;
currentColumn++;
if (currentColumn == numberOfColumns) {
currentRow++;
currentColumn = 0;
}
}else{
amountAnimated++;
frameIndex=0;
currentColumn=0;
currentRow=0;
}
}
};
that.gameLoop = gameLoop.bind(that);
return that;
}
function gameLoop () {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
// this will be your sprite
window.requestAnimationFrame(this.gameLoop);
animation.update();
animation.render();
}
}
function startAnimation(canvas, imageUrl, amount){
canvas = document.getElementById(canvas);
canvas.width = 7680/4;
canvas.height = 2880/4;
image.src = imageUrl;
amountAnimation=amount;
animation = sprite({
context: canvas.getContext("2d"),
width: 7684,
height: 2880,
image: image,
numberOfFrames:16,
totalRows : 4,
totalColumns: 4,
ticksPerFrame: 5
});
animation.gameLoop();
}
startAnimation("imageAnimation", "img/16.png", 3);
startAnimation("imageAnimation2", "img/32.png", 5);