I am using the KineticJS library on my website, to add some functionality to an HTML5 canvas game I'm making.
I am drawing a number of images to the canvas using the library, but it's not quite drawing the images as I had hoped.
The images I'm drawing are all stored in an array, and are currently all being drawn to the canvas. However, they are all being drawn on top of each other, in the same location. This is fine in theory, since the user can drag and drop the images around the canvas, so they would be able to view them all by doing that. However, it's not particularly user friendly, since I am drawing roughly 30 images to the canvas, so for the user to have to move them all individually in order to be able to see them all at the same time is not particularly helpful.
I am using a version of the KineticJS library that I have saved locally, since there are one or two changes I wanted to make to the functionality it provided.
The function in the library that I'm using to draw the images looks like this:
drawImage: function() {
var context = arguments[0];
context.save();
var a = Array.prototype.slice.call(arguments);
if(a.length === 6 || a.length === 10) {
if(a.length === 6) {
context.drawImage(a[1], a[2], a[3], a[4], a[5]);
}
else {
context.drawImage(a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
}
}
context.restore();
}
and this function draws all of the images on top of each other, all in the same location (top left hand corner of the canvas).
I want to edit this function, to create a 'grid' of locations at which the images in the array will be drawn. It doesn't matter if more than one image is drawn to the same grid cell, but at least there would images in more than one location.
I had tried doing this using a function I wrote- my function worked when used on its own, however when I tried to use it alongside the library, it then didn't work. So, I was wondering if I could potentially edit the drawImage function in the library, to include the code I wrote to create the 'grid' layout to draw the images to.
The function I wrote for drawing the images in a grid layout looks like this:
function drawImage(imageObj) {
/* Create variables to select the array position randomly*/
var randomXPosition = function getRandomXPosition(minX, maxX){
return Math.floor(Math.random()*(maxX - minX +1)) +minX;
}
var randomYPosition = function getRandomYPosition(minY, maxY){
return Math.floor(Math.random()*(maxY - minY +1)) +minY;
}
/* Create arrays of X & Y coordinates, and select the array elements randomly for use as
coordinates at which to draw the images*/
var xPos = new Array();
xPos[0] = 10;
xPos[1] = 70;
xPos[2] = 130;
xPos[3] = 190;
xPos[4] = 250;
xPos[5] = 310;
xPos[6] = 370;
xPos[7] = 430;
xPos[8] = 490;
xPos[9] = 550;
xPos[10] = 610;
xPos[11] = 670;
xPos[12] = 730;
xPos[13] = 790;
xPos[14] = 850;
xPos[15] = 910;
var yPos = new Array();
yPos[0] = 40;
yPos[1] = 100;
yPos[2] = 160;
yPos[3] = 220;
yPos[4] = 280;
yPos[5] = 340;
yPos[6] = 400;
yPos[7] = 460;
var canvasImage = new Kinetic.Image({
image: imageObj,
width: 50,
height: 50,
/* Now select a random X & Y position from the arrays to draw the images to */
x: xPos[randomXPosition()],
y: yPos[randomYPosition()],
draggable: true
/* puts the images in random locations on the canvas
x: stage.getWidth() / 20*Math.floor(Math.random()*20),
y: stage.getHeight() / 15*Math.floor(Math.random()*8+2),
draggable: true */
});
// add cursor styling
canvasImage.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
canvasImage.on('mouseout', function() {
document.body.style.cursor = 'default';
});
imagesLayer.add(canvasImage);
}
This function creates the grid layout of canvas coordinates using the X and Y positions, and then assigns a random element from the X and Y coordinate arrays to each image's X and Y values when they are drawn to the canvas- ensuring that each image is drawn on the canvas at a random location within the list of possible locations that I have determined.
What I want to know is how I can add the functionality that the function I've written provides, to the drawImage
function in the library?
I tried copying and pasting my code into the function in the library, so for example:
drawImage: function() {
var context = arguments[0];
context.save();
var a = Array.prototype.slice.call(arguments);
if(a.length === 6 || a.length === 10) {
if(a.length === 6) {
context.drawImage(a[1], a[2], a[3], a[4], a[5]);
}
else {
context.drawImage(a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
}
}
/* Create variables to select the array position randomly*/
var randomXPosition = function getRandomXPosition(minX, maxX){
return Math.floor(Math.random()*(maxX - minX +1)) +minX;
}
var randomYPosition = function getRandomYPosition(minY, maxY){
return Math.floor(Math.random()*(maxY - minY +1)) +minY;
}
/* Create arrays of X & Y coordinates, and select the array elements randomly for use as
coordinates at which to draw the images*/
var xPos = new Array();
xPos[0] = 10;
xPos[1] = 70;
xPos[2] = 130;
xPos[3] = 190;
xPos[4] = 250;
xPos[5] = 310;
xPos[6] = 370;
xPos[7] = 430;
xPos[8] = 490;
xPos[9] = 550;
xPos[10] = 610;
xPos[11] = 670;
xPos[12] = 730;
xPos[13] = 790;
xPos[14] = 850;
xPos[15] = 910;
var yPos = new Array();
yPos[0] = 40;
yPos[1] = 100;
yPos[2] = 160;
yPos[3] = 220;
yPos[4] = 280;
yPos[5] = 340;
yPos[6] = 400;
yPos[7] = 460;
var canvasImage = new Kinetic.Image({
image: imageObj,
width: 50,
height: 50,
/* Now select a random X & Y position from the arrays to draw the images to */
x: xPos[randomXPosition()],
y: yPos[randomYPosition()],
draggable: true
/* puts the images in random locations on the canvas
x: stage.getWidth() / 20*Math.floor(Math.random()*20),
y: stage.getHeight() / 15*Math.floor(Math.random()*8+2),
draggable: true */
});
// add cursor styling
canvasImage.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
canvasImage.on('mouseout', function() {
document.body.style.cursor = 'default';
});
imagesLayer.add(canvasImage);
context.restore();
}
But when viewing the page in the browser after doing this, the canvas no longer appears on the page, and I'm given the console error: "ReferenceError: imageObj is not defined" on the line image: imageObj,
.
I can't figure out why this is, or how to fix it. Does anyone have any suggestions?
Edit 30/01/2013 @ 16:10
I've tried editing the code as suggested, and the drawImage function now looks like this:
drawImage: function() {
var context = arguments[0];
context.save();
var a = Array.prototype.slice.call(arguments);
/*Create the arrays to hold the grid coordinates I want to use */
/* Create variables to select the array position randomly*/
var randomXPosition = function getRandomXPosition(minX, maxX){
return Math.floor(Math.random()*(maxX - minX +1)) +minX;
}
var randomYPosition = function getRandomYPosition(minY, maxY){
return Math.floor(Math.random()*(maxY - minY +1)) +minY;
}
/* Create arrays of X & Y coordinates, and select the array elements randomly for use as
coordinates at which to draw the images*/
var xPos = new Array();
xPos[0] = 10;
xPos[1] = 70;
xPos[2] = 130;
xPos[3] = 190;
xPos[4] = 250;
xPos[5] = 310;
xPos[6] = 370;
xPos[7] = 430;
xPos[8] = 490;
xPos[9] = 550;
xPos[10] = 610;
xPos[11] = 670;
xPos[12] = 730;
xPos[13] = 790;
xPos[14] = 850;
xPos[15] = 910;
var yPos = new Array();
yPos[0] = 40;
yPos[1] = 100;
yPos[2] = 160;
yPos[3] = 220;
yPos[4] = 280;
yPos[5] = 340;
yPos[6] = 400;
yPos[7] = 460;
var canvasImage = new Kinetic.Image({
image: a[1],
width: 50,
height: 50,
x: xPos[randomXPosition()],
y: yPos[randomYPosition()],
draggable: true
});
canvasImage.on('mouseover', function(){/*Define any handlers I want*/});
imagesLayer.add(canvasImage);
}
However, although the canvas is now displayed, the images are not- there is a square 'outline' where the images were previously appearing (when they were all being drawn to the one location), so I assume that's the images, but they're not displaying as images- just a square, and they're still all in the same location.
When I try to drag and drop the square around the canvas (assuming that it is an image), everything else that has been drawn to the canvas moves with the image, and it has all become very slow and unresponsive.
For example, here's a screenshot of my page:
Is there something I've done wrong with how I edited the code?
Your error is caused by the fact that imageObj, the javascript object you are referencing, is not defined anywhere in your code (that you have shown).
Notes:
var canvasImage = new Kinetic.Image({
image: imageObj, // <--- imageObj needs to be created somewhere, it is expecting something like: var imageObj = new Image();
width: 50,
height: 50,
x: xPos[randomXPosition()],
y: yPos[randomYPosition()],
draggable: true
});
Now, for the fix: You need to reference wherever your images are stored; an array?
var canvasImage = new Kinetic.Image({
image: a[0],
width: 50,
height: 50,
x: xPos[randomXPosition()],
y: yPos[randomYPosition()],
draggable: true
});
New Stuff: This is your function:
drawImage: function() {
var context = arguments[0];
context.save();
var a = Array.prototype.slice.call(arguments);
if(a.length === 6 || a.length === 10) {
if(a.length === 6) {
context.drawImage(a[1], a[2], a[3], a[4], a[5]); //a[1] contains the image object reference
}
else {
context.drawImage(a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
}
}
context.restore();
}
try:
drawImage: function() {
var context = arguments[0];
context.save();
var a = Array.prototype.slice.call(arguments);
var randomSpot = randomGridPosition();
var canvasImage = new Kinetic.Image({
image: a[1],
width: 50,
height: 50,
x: randomSpot.x,
y: randomSpot.y,
draggable: true
});
canvasImage.on('mouseover', function(){/*define any handlers you want*/};
layer.add(canvasImage); //or whatever your layer is called
}
Random Grid Position:
function randomGridPosition(){ //10x10 grid
var width= .9*stage.getWidth()/10;
var height= .9*stage.getHeight()/10;
var randomX = Math.floor(10*Math.random()*width); //select random x position dependent on width
var randomY = Math.floor(10*Math.random()*height); //select random y position dependent on height
return {x: randomX, y: randomY};
}