Fabric.js remnants of old canvas remain - javascript

I want to display the content of a canvas as the background of another canvas and draw a bunch of rectangles on there. I need to dynamically change:
the canvas from which to load the background image for my finalcanvas
which rectangles to draw
It's easiest if I start this process from scratch. I have imitated starting from scratch with a simple button. However, after redrawing my canvas, previous information from fabric.js remains present after dragging an item of a canvas a bit. This means that the old canvas was not cleared properly. I tried playing around with .clear() and .depose(), but to no avail.
In case the description is vague, here an image:
And an small reproducible example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js" type="text/javascript"></script>
<script>
function load_plane_onto_active_canvas() {
var c = document.getElementById('backgroundcanvas');
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
var canvas = new fabric.Canvas('finalcanvas', {
width: 333,
height: 333
});
canvas.setBackgroundImage(bg, canvas.renderAll.bind(canvas));
canvas.on("mouse:over", function(e) {
console.log(e.target)
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: 'green',
})
canvas.add(rect);
}
}
}
window.onload = function() {
// fill the background canvas with red
(function() {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
}())
load_plane_onto_active_canvas()
}
</script>
<button onclick="load_plane_onto_active_canvas()">click me</button>
</body>
</html>
I hope someone can help me!

Notice that you're creating a new instance of fabric.Canvas in your load_plane_onto_active_canvas() function. So when you're clicking the button, the existing canvases stay intact, and you're actually calling clear() on your freshly created canvas. The DOM becomes messed up at this point, with several nested canvases inside of each other - you can take a peek at the DOM inspector to see that.
What you can do instead is create the canvas instance just once, then work with a reference to it later in your other functions.
const finalCanvas = new fabric.Canvas("finalcanvas", {
width: 333,
height: 333
});
// finalCanvas now exists in the global (window) scope
function load_plane_onto_active_canvas() {
var c = document.getElementById("backgroundcanvas");
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
finalCanvas.clear();
finalCanvas.setBackgroundImage(bg, finalCanvas.renderAll.bind(finalCanvas));
finalCanvas.on("mouse:over", function (e) {
// console.log(e.target);
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: "green"
});
finalCanvas.add(rect);
}
}
}
window.onload = function () {
// fill the background canvas with red
(function () {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
})();
load_plane_onto_active_canvas();
};
document.querySelector("#b1").onclick = () => load_plane_onto_active_canvas();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.js"></script>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<button id="b1">start from scratch</button>

Related

Fabricjs - Rendering multiple canvases in one document

I'm having a problem dynamically creating and setting canvas backgrounds.
I want the user to be able to annotate the images with text and shapes, thats why I am doing stuff this way.
I would like to know why is this code producing such output
The idea
Send a get request to an endpoint which returns json data containing
image urls.
Convert that data into a javascript array.
Dynamically create fabric js canvases based on the length of above
array.
Set the canvas backgrounds to the images using their urls. (i.e each canvas will have a different background taken from the url)
The problem
Only the last canvas has a background image.
code
<!DOCTYPE html>
<html>
<head>
<style>
body {
}
</style>
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"
></script>
</head>
<body>
<script src="fabric.js"></script>
<!--new start-->
<script>
//procedurally load images from a given source
//endpoint with image links
var end_point = "http://localhost:8080/endpoint.php";
var settings = {
url: "http://localhost:8080/endpoint.php",
method: "GET",
};
//get the images array from end point
$.ajax(settings).done(function (images_json) {
var images = JSON.parse(images_json);
//procedurally create farbric.js canvas for each image element in the html document and set their background as the corresponding image.
//for each item in the images array, create a fabric.js canvas with its background set as the image itself
var canvas_array = [];
for (var i = 0, len = images.length; i < len; i++) {
//console.log(images[i]);
//create canvas and then make it a fabric canvas
document.body.innerHTML += `<canvas
id=${[i]}
width="1000"
height="200"
style="border-style: solid;">
</canvas>`;
//canvases stored in canvas_array
canvas_array[i] = new fabric.Canvas(`${[i]}`);
console.log(canvas_array[i]);
//set canvas background as the image
canvas_array[i].setBackgroundImage(
`${images[i]}`,
canvas_array[i].renderAll.bind(canvas_array[i]),
{
backgroundImageOpacity: 1,
backgroundImageStretch: false,
}
);
}
});
</script>
<!--new end-->
</body>
</html>
result
result
note
The code is generating correct number of canvases. However the background image does not seem to work
Desired result would have 10 canvases with different backgrounds corresponding to the image urls.
I'm new to fabric.js, this may be a dumb mistake.
Using remote source was a strict requirement. I tried several stuff and this finally worked.
code
//c global variable
var n_can_arr = [];
var f_can_arr = [];
var img_arr = [];
//c procedurally load images from a given source
$.ajax({
url: "http://localhost:8080/endpoint.php",
type: "GET",
dataType: "json", //c added data type
success: function (res) {
for (var index = 0; index < res.length; index++) {
//c create canvas
var setHtml = `<canvas
id=${index}
width="1000"
height="800"
style="border-style: solid;">
</canvas>`;
document.body.innerHTML += setHtml;
//c update canvas and image arrays
n_can_arr.push(index);
img_arr.push(res[index]);
}
//c call image set after the loop is over
$(document).trigger("images_set");
},
});
//c on image_set called
$(document).bind("images_set", () => {
//c for each element of normal canvas array, create a fabric js canvas and set its background
for (var i = 0; i < n_can_arr.length; i++) {
create_canvas(i);
}
//c for each element of fabric canvas array, apply the extend canvas function
extend_canvas();
});
function create_canvas(i) {
//c create fabric js canvases with normal canvas id from canvas arrray
var canvas = new fabric.Canvas(`${i}`);
f_can_arr.push(canvas);
//c set canvas background using image array
canvas.setBackgroundImage(img_arr[i], canvas.renderAll.bind(canvas), {
backgroundImageOpacity: 1,
backgroundImageStretch: false,
});
}
function extend_canvas() {
f_can_arr.forEach((canvas) => {
var origX, origY, isDown, mode_rect, mode_uline, mode_free, pointer;
//c setting keypress listener
$(window).on("keypress", (e) => {
console.log(e.key);
//c drawing rectangles
if (e.key == 1) {
var rect;
console.log("Box");
isDown = true;
mode_free = false;
mode_uline = false;
mode_rect = true;
//c canvas event listners
canvas.on("mouse:down", function (o) {
isDown = true;
if (mode_rect) {
pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
console.log(origX + "," + origY);
rect = new fabric.Rect({
left: origX,
top: origY,
originX: "left",
originY: "top",
width: pointer.x - origX,
height: pointer.y - origY,
fill: "red",
angle: 0,
fill: "rgba(255,0,0,0.0)",
stroke: "black",
strokeWidth: 1,
});
canvas.add(rect);
}
});
canvas.on("mouse:move", function (o) {
if (mode_rect) {
if (isDown) {
var pointer = canvas.getPointer(o.e);
if (origX > pointer.x) {
rect.set({ left: Math.abs(pointer.x) });
}
if (origY > pointer.y) {
rect.set({ top: Math.abs(pointer.y) });
}
rect.set({ width: Math.abs(origX - pointer.x) });
rect.set({ height: Math.abs(origY - pointer.y) });
canvas.renderAll();
}
}
});
}
//c freehand drawing/Highlighter
if (e.key == 2) {
console.log("freehand");
isDown = true;
mode_free = true;
mode_uline = false;
mode_rect = false;
canvas.isDrawingMode = 1;
canvas.freeDrawingBrush.color = "rgba(255,0,0,0.2)";
canvas.freeDrawingBrush.width = 20;
//c canvas event listners
canvas.on("mouse:down", function (o) {
isDown = true;
if (mode_free) {
canvas.renderAll();
}
});
}
//c line mode
if (e.key == 3) {
var line;
console.log("line");
isDown = true;
mode_free = false;
mode_uline = true;
mode_rect = false;
//c canvas event listners
canvas.on("mouse:down", function (o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
var points = [pointer.x, pointer.y, pointer.x, pointer.y];
if (mode_uline) {
line = new fabric.Line(points, {
strokeWidth: 3,
fill: "red",
stroke: "red",
originX: "center",
originY: "center",
targetFindTolerance: true,
});
canvas.add(line);
}
});
canvas.on("mouse:move", function (o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (mode_uline) {
line.set({ x2: pointer.x, y2: pointer.y });
canvas.renderAll();
}
});
}
//c deleting a selected shape
if (e.key == 4) {
var activeObject = canvas.getActiveObject();
if (activeObject) {
canvas.remove(activeObject);
}
}
//c cancling freehand drawing mode
if (e.key == "x") {
console.log("freehand mode cancled");
canvas.isDrawingMode = 0;
}
});
//c removing previous event listeners and resetting some global variables
canvas.on("mouse:up", function (o) {
isDown = false;
mode_free = false;
mode_uline = false;
mode_rect = false;
canvas.off("mouse:down");
canvas.off("mouse:move");
});
});
}
function save_canvas() {}
function load_canvas() {}
solution
I setup a custom trigger event after the ajax call is made. When the trigger event is fired, only then I create fabricjs canvases.
(apparently even with promises, the fabric code was not running in correct order. Which was probably due to bad syntax. Custom triggers solve this issue.)
results
-Each image appear separately in its own fabric.js canvas as background.
-Each canvas is independent.
Have create for you just copy code and then use your own images in local to get actual full result in output div( images will generated) .
let CANVAS_LIST = [];
let imageList = [
'https://homepages.cae.wisc.edu/~ece533/images/airplane.png',
'https://homepages.cae.wisc.edu/~ece533/images/arctichare.png',
'https://homepages.cae.wisc.edu/~ece533/images/baboon.png',
]
imageList.forEach(element => {
let canvasElement = document.createElement("canvas");
canvasElement.width = '300';
canvasElement.height = '300';
$("#canvas_container").append(canvasElement);
let canvas = new fabric.Canvas(canvasElement);
// Adding Example Text here.
canvas.add(new fabric.Text('This text is added', {
fontFamily: 'Delicious_500',
color: 'red',
left: 10,
top: 100
}));
// Setting up Background to dynamic generated Canvas
canvas.setBackgroundImage(
`${element}`,
canvas.renderAll.bind(canvas),
{
backgroundImageOpacity: 1,
backgroundImageStretch: false,
}
);
CANVAS_LIST.push(canvas);
});
setTimeout(() => {
generateOutput();
}, 3000);
function generateOutput() {
$("#output").empty();
CANVAS_LIST.forEach(canvas => {
let image = $("<img>").attr({
width: 200,
height: 200,
src: canvas.toDataURL()
});
image.css({ marginLeft: '20px' });
$("#output").append(image);
})
}
<!DOCTYPE html>
<html>
<head>
<style>
body {}
</style>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div id="canvas_container">
</div>
<button onclick="generateOutput()"> Show output</button>
<div id="output">
</div>
</div>
</body>
</html>
Thanks

Using variable font inside WEBGL canvas, p5 js

I have a WEBGL canvas in which I am loading a 3d model. I also have a text in variable font which I create with createP. The problem is that I need the text to be between the background and the 3d model. But I can only have the text in front of the canvas (on top of 3d model). Is there any way I can achieve this?
Ps. Creating the text with text() does not allow me to have variable weight value.
let kalameh;
var cnv;
let img;
function preload(){
img = loadImage('assets/lines.png');
kalameh = loadModel('kalameh.obj');
}
function setup() {
cnv = createCanvas(700, 700, WEBGL);
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
wordA = createP('my text');
}
function draw() {
background(220, 220, 220);
wordA.style('font-size', '110px');
wordA.style('font-weight', '200');
wordA.style('font-stretch', '200%');
wordA.style('align', 'center');
wordA.position(40,25);
image(img, -1*windowWidth/2, -1*windowHeight/2, windowWidth, windowHeight);
translate (0,0,100);
pointLight(255,255,255, -350,0,400);
pointLight(255,255,255, 350,0,400);
ambientMaterial(255);
noStroke();
scale (0.25);
model(kalameh);
}
You could create two sketches (and thus two canvases) and assign z-index properties of -1 and 1 to make them foreground and background sketches, respectively. You can then sandwich the paragraph element that you created between the two canvases by giving it a z-index of 0. You can then make the foreground sketch transparent by calling clear() at the beginning of the draw loop.
In the code snippet below, the 3D object is in front of the text paragraph, whereas the white square of the "background" is behind the text.
let testP;
new p5(function(p){
p.setup = function() {
const foregroundCanvas = p.createCanvas(400, 400, p.WEBGL);
foregroundCanvas.id("foregroundSketch");
foregroundCanvas.position(0, 0);
p.normalMaterial();
testP = p.createP("In front of background / behind object ")
testP.position(95, 115);
testP.id("sandwichedParagraph")
p.angleMode(p.RADIANS)
}
p.draw = function() {
p.clear();
//drag to move the world.
// p.orbitControl();
p.push();
let rotateAngle = p.sin(p.frameCount/50);
p.rotateX(rotateAngle/2);
p.rotateY(-rotateAngle);
p.rotateZ(rotateAngle);
p.box(200, 100, 40);
p.pop();
}
}, "foregroundSketch");
new p5(function(p){
p.setup = function() {
const backgroundCanvas = p.createCanvas(400, 400);
// backgroundCanvas.parent("wrapper")
backgroundCanvas.position(0, 0);
backgroundCanvas.id("backgroundSketch")
p.noStroke();
}
p.draw = function() {
p.background(200);
let shiftAmount = p.map(p.sin(p.frameCount/60), -1, 1, 80, 310);
p.rect(shiftAmount, 120, 40, 40);
}
}, "backgroundSketch");
html, body {
margin: 0;
padding: 0;
}
/* The sketch with the white square has z-index of -1 (background!) */
#backgroundSketch {
z-index: -1;
position: absolute;
}
/* The <p> has z-index of 0 (sandwiched between both sketches)*/
#sandwichedParagraph {
z-index: 0;
position: absolute;
}
/* The sketch with the object has z-index of 1 (foreground!)*/
#foregroundSketch {
z-index: 1;
position: absolute;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>

Optimise HTML5 canvas

Why does html5 canvas become very slow when I draw 2000 images and more ?
How can I optimise it?
Here's a demo that I've made, disable the "safe mode" by left clicking on the canvas and start moving your mouse until you get ~2000 images drawn
var img = new Image()
img.src = "http://i.imgur.com/oVOibrL.png";
img.onload = Draw;
var canvas = $("canvas")[0];
var ctx = canvas.getContext("2d")
var cnv = $("canvas");
var draw = [];
$("canvas").mousemove(add)
function add(event) {
draw.push({x: event.clientX, y: event.clientY})
}
canvas.width = cnv.width();
canvas.height = cnv.height();
var safe = true;
cnv.contextmenu(function(e) { e.preventDefault() })
cnv.mousedown(function(event) {
if(event.which == 1) safe = !safe;
if(event.which == 3) draw = []
});
function Draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
requestAnimationFrame(Draw);
for(var i of draw) {
ctx.drawImage(img, i.x, i.y)
}
if(safe && draw.length > 300) draw = []
ctx.fillText("Images count: "+ draw.length,10, 50);
ctx.fillText("Left click to toggle the 300 images limit",10, 70);
ctx.fillText("Right click to clear canvas",10, 90);
}
Draw();
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
position: absolute;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
z-index: 99999999999;
cursor: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas></canvas>
Codepen: http://codepen.io/anon/pen/PpeNme
The simple way with the actual code :
Don't redraw all your images at this rate.
Since in your example, the images are static, you actually don't need to redraw everything every frame : Just draw the latest ones.
Also, if you've got other drawings occurring (e.g your texts), you may want to use an offscreen canvas for only the images, that you'll redraw on the onscreen canvas + other drawings.
var img = new Image()
img.src = "http://i.imgur.com/oVOibrL.png";
img.onload = Draw;
var canvas = $("canvas")[0];
var ctx = canvas.getContext("2d")
var cnv = $("canvas");
var draw = [];
$("canvas").mousemove(add)
function add(event) {
draw.push({
x: event.clientX,
y: event.clientY
})
}
canvas.width = cnv.width();
canvas.height = cnv.height();
// create an offscreen clone of our canvas for the images
var imgCan = canvas.cloneNode();
var imgCtx = imgCan.getContext('2d');
var drawn = 0; // a counter to know how much image we've to draw
var safe = true;
cnv.contextmenu(function(e) {
e.preventDefault()
})
cnv.mousedown(function(event) {
if (event.which == 1) safe = !safe;
if (event.which == 3) draw = []
});
function Draw() {
// clear the visible canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
requestAnimationFrame(Draw);
if (draw.length) { // onmy if we've got some objects to draw
for (drawn; drawn < draw.length; drawn++) { // only the latest ones
let i = draw[drawn];
// draw it on the offscreen canvas
imgCtx.drawImage(img, i.x, i.y)
}
}
// should not be needed anymore but...
if (safe && draw.length > 300) {
draw = [];
drawn = 0; // reset our counter
// clear the offscren canvas
imgCtx.clearRect(0, 0, canvas.width, canvas.height);
}
// draw the offscreen canvas on the visible one
ctx.drawImage(imgCan, 0, 0);
// do the other drawings
ctx.fillText("Images count: " + draw.length, 10, 50);
ctx.fillText("Left click to toggle the 300 images limit", 10, 70);
ctx.fillText("Right click to clear canvas", 10, 90);
}
Draw();
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
position: absolute;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
z-index: 99999999999;
cursor: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas></canvas>
Now, if you need these images to be dynamic (i.e move at every frame), you may consider using imageDatas.
You can see this original post by user #Loktar, which explains how to parse your drawn image imageData, and then redraw it pixel per pixel on the visible canvas' imageData. You can also see this follow-up Q/A, which provides a color implementation of Loktar's idea.
On small images, this actually improves drastically the performances, but it has the huge inconvenient to not support alpha channel multiplication. You will only have fully transparent and fully opaque pixels. An other cons is that it may be harder to implement, but this is just your problem ;-)

Toggle Onclick Issue in Javascript

Simply put, I'm trying to toggle a button to make a line bold (or not). I read a few questions here similar to this problem, but the solutions haven't helped me. Here's my code:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="DrawLineDiv">
<canvas id="DrawLineCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('DrawLineCanvas');
var context = canvas.getContext('2d');
// Use beginPath() to declare that a new path is to be drawn
context.beginPath();
// Place the drawing cursor at the desired point
context.moveTo(100, 150);
// Determine where to stop drawing
context.lineTo(450,50);
//Draw the line
context.stroke();
</script>
</div>
<script>
var canvas = document.getElementById("DrawLineCanvas");
//var context = canvas.getContext('2d');
function toggleLineBold(button) {
var button;
if (button == "BoldNow") {
context.lineWidth = 15;
context.stroke();
document.getElementById("BoldLineButton").onclick = function(){
toggleLineBold('Regular');
};
} else {
context.lineWidth = 1;
context.stroke();
document.getElementById("BoldLineButton").onclick = function(){
toggleLineBold('BoldNow');
};
return;
};
};
</script>
<div id="BoldLineButton" style="height:50px; width:120px; border:2px solid #6495ed; background-color:#bcd2ee; border-radius:10px; margin-left: 5px; text-align:center" onclick="toggleLineBold('BoldNow')">
<br/>Toggle Bold Line<br/>
</div>
</body>
</html>
The line changes to bold, but triggers an error in the javascript at the line trying to change the onclick event. I know I've got something wrong, I'm just not sure what.
Thank's in advance for your assistance.
LIVE DEMO
HTML:
<canvas id="DrawLineCanvas" width="578" height="200"></canvas>
<button id="BoldLineButton">Line size: <b>1</b></button>
JS:
var doc = document,
canvas = doc.querySelector('#DrawLineCanvas'),
boldBtn = doc.querySelector('#BoldLineButton'),
ctx = canvas.getContext('2d'),
size = [1, 3, 5, 10, 15], // use only [1, 15] if you want
currSize = 0; // size[0] = 1 // Index pointer to get the value out of the
// size Array
function draw(){
canvas.width = canvas.width;
ctx.beginPath();
ctx.moveTo(100, 150);
ctx.lineTo(450,50);
ctx.lineWidth = size[currSize]; // Use currSize Array index
ctx.stroke();
}
draw();
function toggleLineBold() {
++currSize; // Increase size and
currSize %= size.length; // loop if needed.
boldBtn.getElementsByTagName('b')[0].innerHTML = size[currSize];
draw();
}
boldBtn.addEventListener("click", toggleLineBold);

draw array images in canvas?

I am trying to draw an array of images on a canvas, but nothing is getting drawn! following is my code! Also i am trying to learn about phonegap and javascript
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Minecraft Background Check</title>
</head>
<body>
<canvas id="mycanvas" style="position:fixed; top:0; left:0; border:1px solid #c3c3c3; width: 100%; height: 100%;"></canvas>
<script type="text/javascript" src="cordova-2.5.0.js"></script>
<script type="text/javascript">
document.addEventListener("deviceready",ondeviceReady,false);
function onDeviceReady () {}
//get element by id
var c = document.getElementById("mycanvas");
var ctx = c.getContext("2d");
//array image which need to draw in canvas
var image = ["img/image12","img/image13","img/image14","img/image15","img/image10"];
var m_arrImages = {};
for (var src in image) {
m_arrImages[src] = new Image();
m_arrImages[src].src = image[src];
}
var imagePositionsX = [20, 80, 140, 200, 260, 320, 380, 440, 500, 560];
var imagePositionsY = [20, 60, 100, 140, 180, 220, 260, 300, 340, 380];
var i, x, y;
for (i = 0; i < m_arrImages.length; i++) {
x = imagePositionsX[ Math.floor(Math.random()*10) ];
y = imagePositionsY[ Math.floor(Math.random()*10) ];
ctx.drawImage(m_arrImages[i], x, y, 50, 50);
}
</script>
</body>
</html>
You have set the function ondeviceReady to run at the deviceready event but that function isn't defined. You have defined a function called onDeviceReady. Javascript variable and function names are case sensitive, so nothing will run at the deviceready event.
Change:
document.addEventListener("deviceready",ondeviceReady,false);
to
document.addEventListener("deviceready",onDeviceReady,false);
May be I am wrong, but.. "m_arrImages" - it's just array with strings, not images, isn't it?
I thing, it sould be something like that:
var m_arrImages = {};
for (var src in image) {
m_arrImages[src] = new Image();
m_arrImages[src].src = image[src];
}

Categories