cache a canvas in an object (in memory) - javascript

I am trying to cache the different states a user sets for a canvas,
The thing is that using .push and canvas.clone() when I append it later it's same size, but white; without the image that it was showing,
Any posible way to store a canvas in memory?
-EDIT-
This is how I'm trying
effectosFotos: function ($foto) {
var t;
var selector = '#'+$foto.attr('id');
var $foto = $(selector);
var $backup = $foto.clone();
var times = 0;
var cached = [];
$('.filters').show();
var img1 = document.createElement('img');
img1.onload = function () {
var width1 = $('.filters li').eq(0).width()/3;
var height1 = this.height*(width1/this.width);
console.log(width1, height1);
var canvas1 = document.createElement('canvas'),
ctx1 = canvas1.getContext('2d');
canvas1.width = width1;
canvas1.height = height1;
ctx1.drawImage(this, 0, 0, width1, height1);
var newUrl = canvas1.toDataURL('image/jpeg', 0.8);
$('.filters li a').each(function() {
$(this).append( '<img id="preview_'+$(this).data('id')+'" src="'+newUrl+'">' );
});
$('.filters li a').each(function(i) {
var $this = $(this);
t = setTimeout(function () {
var effect = $this.data('id');
var $img = $('#preview_'+effect);
//console.log('Item='+i +' About to render '+ effect +' and exists? ' + $img.length );
Caman('#preview_'+effect, function () {
this[effect]();
this.render(function(){
//console.log('rendered '+effect);
$this.parent().addClass('rendered');
});
});
}, 1*i)
});
}
img1.src = $foto.attr('src');
$('.filters').on('click', 'li:not(.active) a', function(e){
var start = new Date().getTime();
var $this = $(this).addClass('loading');
$this.parent().addClass('loading');
e.preventDefault();
var effect = $(this).data('id');
var parent = $(selector).parent();
//console.log('f'+$(selector).length, effect,times,$(selector).prop("tagName"),$backup.prop("tagName"));
/*if(times == 0){
$backup = $foto.clone();
}
times++;*/
$(selector).remove();
parent.append($backup);
console.log(cached);
var found = -1;
for ( var c = 0; c < cached.length; c++ ) {
var item = cached[c];
if ( item.effect == effect ) {
found = c;
}
}
if (effect == 'normal'){
$(selector).css('opacity',1);
$this.parent().addClass('active').removeClass('loading').siblings().removeClass('active');
} else if ( found > -1 ) {
console.log('Cargamos caché ' + effect + ' a '+width +'x'+height);
var canvas = document.getElementById($foto.attr('id'))
canvas.width = width;
canvas.height = height;
var ctx3 = canvas.getContext('2d');
ctx3.clearRect( 0, 0, width, height );
ctx3.drawImage( cached[found].canvas, 0, 0);
$this.parent().addClass('active').removeClass('loading').siblings().removeClass('active');
} else {
$(selector).remove();
parent.append($backup);
$(selector).css('opacity',0.3);
$('.takePictureHolder').addClass('caming');
Caman(selector, function () {
this[effect]();
this.render(function(){
$(selector).css('opacity',1);
$this.parent().addClass('active').removeClass('loading').siblings().removeClass('active');
$('.takePictureHolder').removeClass('caming');
if (found == -1) {
var canvas = document.getElementById($foto.attr('id'));
var clone = canvas.cloneNode(true);
clone.getContext('2d').drawImage(canvas, 0,0);
cached.push({ 'effect' :effect, "canvas":clone });
/*var ctx4 = document.getElementById($foto.attr('id')).getContext('2d');
console.log('Cacheamos ' + effect + ' a '+width +'x'+height);
cached.push({ 'effect' :effect, "canvas":ctx4.getImageData(0,0,width, height) });*/
}
var end = new Date().getTime();
var time = end - start;
console.log('Execution time: ' + time);
});
});
}
});
}

The easiest and way more efficient than export methods is to draw your to-be-saved canvas on a clone, using clonedCtx.drawImage(canvas, 0,0). You will then be able to store the cloned canvas in an array :
Andreas' snippet with modified code :
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
states = [];
console.log('setup states...');
setupState();
function rndColor() {
var rgb = [];
for (var i = 0; i < 3; i++) {
rgb.push(Math.floor(Math.random() * 255));
}
return "rgb(" + rgb.join(",") + ")";
}
function setupState() {
canvas.width = 50 + Math.floor(Math.random() * 100);
canvas.height = 50 + Math.floor(Math.random() * 100);
context.fillStyle = rndColor();
context.fillRect(0, 0, canvas.width, canvas.height);
var clone = canvas.cloneNode(true);
clone.getContext('2d').drawImage(canvas, 0,0);
states.push(clone)
if (states.length < 5) {
setTimeout(setupState, 1000);
} else {
console.log("restore states...");
setTimeout(restoreStates, 2000);
}
}
function restoreStates() {
var state = states.shift();
canvas.width = state.width;
canvas.height = state.height;
context.clearRect(0, 0, state.width, state.height);
context.drawImage(state, 0, 0);
if (states.length) {
setTimeout(restoreStates, 1000);
}
}
canvas { border: solid 5px blue }
<canvas></canvas>
But, as pointed out by #markE, if you need to store a lot of these states (e.g if you want to implement an undo/redo feature), it can quickly fill all your memory.
Then the recommended way is to save all drawing operations and reapply them. Still using Andreas' snippet, a minimal implementation could be :
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
states = [];
console.log('setup states...');
setupState();
function rndColor() {
var rgb = [];
for (var i = 0; i < 3; i++) {
rgb.push(Math.floor(Math.random() * 255));
}
return "rgb(" + rgb.join(",") + ")";
}
function setupState() {
// create an object with all our states settings and operations
var state = {fillStyle: rndColor(), width: Math.floor(Math.random() * 100), height:Math.floor(Math.random() * 100)};
// save the operations in an array
state.operations = [{name:'fillRect',arguments: [0,0,state.width, state.height]}];
// save the state
states.push(state);
// parse it a first time;
parse(state);
if (states.length < 5) {
setTimeout(setupState, 1000);
} else {
console.log("restore states...");
setTimeout(restoreStates, 2000);
}
}
function parse(state){
// restore our canvas and context's properties
// this could be improved by creating canvas and context objects in our state and then restore the corresponding with a for(x in y) loop
canvas.width = state.width;
canvas.height = state.height;
context.fillStyle = state.fillStyle;
// retrieve the operations we applied
var op = state.operations;
// loop through them
for(var i=0; i<op.length; i++){
// check it actually exists as a function
if(typeof context[op[i].name]==='function')
// apply the saved arguments
context[op[i].name].apply(context, op[i].arguments);
}
}
function restoreStates() {
var state = states.shift();
parse(state);
if (states.length) {
setTimeout(restoreStates, 1000);
}
}
canvas { border: solid 1px blue }
<canvas></canvas>

You could save the content of the canvas with .getImageData().
And .putImageData() for restoring the old content.
var data = [];
// store canvas/image
data.push(context.getImageData(0, 0, canvas.width, canvas.height));
// restore canvas/image
var oldData = data.pop();
canvas.width = oldData.width;
canvas.height = oldData.height;
context.clearRect(oldData, 0, 0, canvas.width, canvas.height);
context.putImageData(oldData, 0, 0);
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
states = [],
img;
console.log("setup states...");
setupState();
function rndColor() {
var rgb = [];
for (var i = 0; i < 3; i++) {
rgb.push(Math.floor(Math.random() * 255));
}
return "rgb(" + rgb.join(",") + ")";
}
function setupState() {
canvas.width = 50 + Math.floor(Math.random() * 100);
canvas.height = 50 + Math.floor(Math.random() * 100);
context.fillStyle = rndColor();
context.fillRect(0, 0, canvas.width, canvas.height);
states.push(context.getImageData(0, 0, canvas.width, canvas.height));
if (states.length < 5) {
setTimeout(setupState, 1000);
} else {
console.log("restore states...");
setTimeout(restoreStates, 2000);
}
}
function restoreStates() {
var state = states.shift();
canvas.width = state.width;
canvas.height = state.height;
context.clearRect(0, 0, state.width, state.height);
context.putImageData(state, 0, 0);
if (states.length) {
setTimeout(restoreStates, 1000);
}
}
canvas { border: solid 5px blue }
<canvas></canvas>
The same would be possible with .toDataUrl()
and .drawImage()
But this would be the slower approach: jsperf (at least in chrome)
var images = [];
// store canvas/image
var img = new Image();
img.src = canvas.toDataURL();
images.push(img);
// restore canvas/image
var oldImage = images.pop();
canvas.width = oldImage.width;
canvas.height = oldImage.height;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(oldImage, 0, 0);
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
states = [],
img;
console.log("setup states...");
setupState();
function rndColor() {
var rgb = [];
for (var i = 0; i < 3; i++) {
rgb.push(Math.floor(Math.random() * 255));
}
return "rgb(" + rgb.join(",") + ")";
}
function setupState() {
canvas.width = 50 + Math.floor(Math.random() * 100);
canvas.height = 50 + Math.floor(Math.random() * 100);
context.fillStyle = rndColor();
context.fillRect(0, 0, canvas.width, canvas.height);
img = new Image();
img.src = canvas.toDataURL();
states.push(img);
if (states.length < 5) {
setTimeout(setupState, 1000);
} else {
console.log("restore states...");
setTimeout(restoreStates, 2000);
}
}
function restoreStates() {
var state = states.shift();
canvas.width = state.width;
canvas.height = state.height;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(state, 0, 0);
if (states.length) {
setTimeout(restoreStates, 1000);
}
}
canvas { border: solid 5px blue }
<canvas></canvas>

Related

Return true when user click a bug

I am making a bug smasher game, and want Boolean value(isOnCircle) to return 'true' when a user clicks the bug. However, it always returns 'false'. Although when I tested it as a circle instead of a bug image (with 'context.arc'), it returned 'true'.
*I also inserted an image into the canvas background.
bug.r=32 is the bug image's correct radius size.
var Bug = (function () {
function Bug() {
}
return Bug;
}());
var jumpInterval;
var interval = 4000;
var bug = new Bug();
var canvas = document.getElementById('canvas');
canvas.width =727
canvas.height = 483;
var context = canvas.getContext('2d');
var background = new Image();
background.src = "images/lawn.jpg";
background.onload = function () {
context.drawImage(background, 0, 0);
}
function handleClick(evt) {
console.log(evt.x + ',' + evt.y);
var x = evt.x - 50;
var y = evt.y - 100;
// (x - center_x)^2 + (y - center_y)^2 < radius^2
var isOnCircle = Math.pow(x - bug.x, 2) + Math.pow(y - bug.y, 2) < Math.pow(bug.r, 2);
console.log(isOnCircle);
if (interval > 500) {
interval -= 300;
} else {
interval = 500;
}
console.log(interval);
}
function jump() {
bug.x = ((Math.random() * 10324897) % 500) + 1;
bug.y = ((Math.random() * 10324897) % 500) + 1;
bug.r = 32;
context.clearRect(0, 0, canvas.width, canvas.height);
var background = new Image();
background.src = "images/lawn.jpg";
background.onload = function () {
context.drawImage(background, 0, 0);
}
console.log(bug.x);
console.log(bug.y);
context.beginPath();
//context.arc(bug.x, bug.y, bug.r, 0, 2 * Math.PI);
var bugImage = new Image();
bugImage.src = "images/bug.PNG";
bugImage.onload = function () {
context.drawImage(bugImage, bug.x, bug.y);
}
context.stroke();
clearInterval(jumpInterval);
jumpInterval = setInterval(jump, interval);
}
jumpInterval = setInterval(jump, interval);
canvas.addEventListener("click", handleClick);

Stopping animated rain in Canvas smmoothly

Rain Picture HereSo my issue isn't stopping the rain its stopping the making of the rain so the already rendered rain completes its animation off the screen.
I tried setInterval and setTimeout in JS but it just freezes.
And using JQuery to remove canvas tag takes off all drops at once.
Any ideas or direction would be great!
var canvas = document.getElementById("rainCanvas");
var ctx = canvas.getContext("2d");
var canvasW = window.innerWidth;
var canvasH = window.innerHeight;
canvas.height = canvasH;
canvas.width = canvasW;
var mf = 70;
var drops = [];
for(var i = 0; i < mf; i++){
drops.push({
x: Math.random()*canvasW,
y: Math.random()*canvasH,
r: Math.random()*5+2,
d: Math.random() + 1
})
}
function fill() {
ctx.fill();
}
function drawRain(){
ctx.clearRect(0, 0, canvasW, canvasH);
ctx.fillStyle = "rgba(255, 255, 255, .5)";
ctx.beginPath();
for(var i = 0; i < mf; i++){
var f = drops[i];
ctx.moveTo(f.x-5, f.y);
ctx.lineTo(f.x, f.y-15);
ctx.lineTo(f.x+5, f.y);
ctx.arc(f.x, f.y + f.r*.7,5, 0, Math.PI, false);
}
fill();
moveRain();
}
function moveRain(){
for(var i = 0; i < mf; i++){
var f = drops[i];
f.y += Math.pow(f.d, 2) + 1;
if(f.y > canvasH){
drops[i] = {x: Math.random()*canvasW, y: 0, r: f.r, d: f.d};
}
}
}
var i = setInterval(drawRain, 20);
setTimeout(function( ) { clearInterval(); }, 2000);
canvas{ background-color: black }
<canvas id="rainCanvas"></canvas>
What you want to do is set a flag to stop the rain from wrapping back to the top in your function to stop raining:
var stopRain = false;
...
setTimeout(function( ) { stopRain = true; }, 2000);
Now inside moveRain when that variable is true instead of moving it back to the top remove it from the array. Once we removed all the drops we can then clear the interval as it's no longer needed:
function moveRain(){
for(var i = 0; i < mf; i++){
var f = drops[i];
f.y += Math.pow(f.d, 2) + 1;
if(f.y > canvasH){
if(stopRain) { // When we stop raining
drops.splice(i, 1); // Remove drop from array
mf--; // Make sure to update the "length"
if(mf<1) clearInterval(i); // If there are not more drops clear the interval
} else drops[i] = {x: Math.random()*canvasW, y: 0, r: f.r, d: f.d};
}
}
}
Fiddle Example
You could also use drops.length instead of using mf, this way you don't need to do mf--.
Here I fixed some of the code and added a rainDensity variable which controls the count of new raindrops. The original code was designed to have a fixed amount of raindrops, it had to be changed to achieve the desired effect.
window.onload = function(){
var canvas = document.getElementById("rainCanvas");
var ctx = canvas.getContext("2d");
var canvasW = window.innerWidth;
var canvasH = window.innerHeight;
canvas.height = canvasH;
canvas.width = canvasW;
var drops = [];
function makeDrop() {
drops.push({
x: Math.random()*canvasW,
y: -10,
r: Math.random()*4+1,
d: Math.pow(Math.random() + 1, 2) + 1
})
}
function drawRain(){
ctx.clearRect(0, 0, canvasW, canvasH);
ctx.fillStyle = "rgba(128, 128, 255, .5)";
for(var f of drops){
ctx.beginPath();
ctx.moveTo(f.x-5, f.y);
ctx.lineTo(f.x, f.y-15);
ctx.lineTo(f.x+5, f.y);
ctx.arc(f.x, f.y + f.r*.7,5, 0, Math.PI, false);
ctx.fill();
}
}
function handleFrame() {
drawRain();
updateRain();
}
function updateRain() {
moveRain();
makeNewDrops();
}
var dropPerFrameCounter = 0;
var startTime = Date.now();
function makeNewDrops() {
var elapsedTime = (Date.now() - startTime) / 1000;
// rainDensity: set it to 0 to stop rain
var rainDensity = Math.max(0, Math.sin(elapsedTime / 3) + 0.5);
dropPerFrameCounter += rainDensity;
while (dropPerFrameCounter >= 1) {
dropPerFrameCounter--;
makeDrop();
}
}
function moveRain() {
for(var f of drops){
f.y += f.d;
}
drops = drops.filter(d => d.y < canvasH);
}
var intervalRender = setInterval(handleFrame, 20);
}
<canvas id="rainCanvas"></canvas>
Had to add an answer because the example all used setInterval to do the animation which looks awful. Use requestAnimationFrame to animate. Also fixed some other problems with the code.
I have added a pause the pauses the animation when you click on the canvas. Clicking again will continue.
var canvas = document.getElementById("rainCanvas");
var ctx = canvas.getContext("2d");
var canvasW = window.innerWidth;
var canvasH = window.innerHeight;
canvas.height = canvasH;
canvas.width = canvasW;
var mf = 70;
var drops = [];
var paused = false;
for(var i = 0; i < mf; i++){
drops.push({
x: Math.random()*canvasW,
y: Math.random()*canvasH,
r: Math.random()*5+2,
d: Math.random() + 1
})
}
function drawRain(){
if(!paused){
ctx.clearRect(0, 0, canvasW, canvasH);
ctx.fillStyle = "rgba(255, 255, 255, .5)";
ctx.beginPath();
for(var i = 0; i < mf; i++){
var f = drops[i];
ctx.moveTo(f.x - 2.5 * f.d, f.y);
ctx.lineTo(f.x, f.y - 7.5 * f.d);
ctx.lineTo(f.x + 2.5 * f.d, f.y);
ctx.arc(f.x, f.y + f.r * 0.7, 2.5 * f.d, 0, Math.PI, false);
}
ctx.fill();
for(var i = 0; i < mf; i++){
var f = drops[i];
f.y += Math.pow(f.d, 2) + 1;
if(f.y > canvasH + 15){ // make sure completely off the bottom
// dont create a new drop reuse it will stop GC from
// having to interrupt the code.
f.x = Math.random()*canvasW;
f.y = -6; // move off top
}
}
}
requestAnimationFrame(drawRain);
}
requestAnimationFrame(drawRain);
canvas.addEventListener("click",()=>{paused = ! paused});
canvas{
background-color: black;
position : absolute;
top : 0px;
left : 0px;
}
<canvas id="rainCanvas"></canvas>

Canvas rotation - fixed background, moving foreground

Goal
The stripes in the background remain fixed while the cones rotate about the center.
Current State
live demo:
https://codepen.io/WallyNally/pen/yamGYB
/*
The loop function is around line 79.
Uncomment it to start the animation.
*/
var c = document.getElementById('canv');
var ctx = c.getContext('2d');
var W = c.width = window.innerWidth;
var H = c.height = window.innerHeight;
var Line = function() {
this.ctx = ctx;
this.startX = 0;
this.startY = 0;
this.endX = 0;
this.endY = 0;
this.direction = 0;
this.color = 'blue';
this.draw = function() {
this.ctx.beginPath();
this.ctx.lineWidth = .1;
this.ctx.strokeStlye = this.color;
this.ctx.moveTo(this.startX, this.startY);
this.ctx.lineTo(this.endX, this.endY);
this.ctx.closePath();
this.ctx.stroke();
}
this.update = function() {
//for fun
if (this.direction == 1) {
this.ctx.translate(W/2, H/2);
this.ctx.rotate(-Math.PI/(180));
}
}//this.update()
}//Line();
objects=[];
function initLines() {
for (var i =0; i < 200; i++) {
var line = new Line();
line.direction = (i % 2);
if (line.direction == 0) {
line.startX = 0;
line.startY = -H + i * H/100;
line.endX = W + line.startX;
line.endY = H + line.startY;
}
if (line.direction == 1) {
line.startX = 0;
line.startY = H - i * H/100;
line.endX = W - line.startX;
line.endY = H - line.startY;
}
objects.push(line);
line.draw();
}
}
initLines();
function render(c) {
c.clearRect(0, 0, W, H);
for (var i = 0; i < objects.length; i++)
{
objects[i].update();
objects[i].draw();
}
}
function loop() {
render(ctx);
window.requestAnimationFrame(loop);
}
//loop();
What I have tried
The translate(W/2, H/2) should place the context at the center of the page, then this.ctx.rotate(-Math.PI/(180)) should rotate it one degree at a time. This is the part that is not working.
Using save()and restore() is the proper way to keep some parts of an animation static while others move. I placed the save and restore in different parts of the code to no avail. There are one of two types of result : Either a new entirely static image is produced, or some erratic animation happens (in the same vein of where it is now).
Here is the changed pen: http://codepen.io/samcarlinone/pen/LRwqNg
You needed a couple of changes:
var c = document.getElementById('canv');
var ctx = c.getContext('2d');
var W = c.width = window.innerWidth;
var H = c.height = window.innerHeight;
var angle = 0;
var Line = function() {
this.ctx = ctx;
this.startX = 0;
this.startY = 0;
this.endX = 0;
this.endY = 0;
this.direction = 0;
this.color = 'blue';
this.draw = function() {
this.ctx.beginPath();
this.ctx.lineWidth = .1;
this.ctx.strokeStlye = this.color;
this.ctx.moveTo(this.startX, this.startY);
this.ctx.lineTo(this.endX, this.endY);
this.ctx.closePath();
this.ctx.stroke();
}
this.update = function() {
//for fun
if (this.direction == 1) {
this.ctx.translate(W/2, H/2);
this.ctx.rotate(angle);
this.ctx.translate(-W/2, -H/2);
}
}//this.update()
}//Line();
objects=[];
function initLines() {
for (var i =0; i < 200; i++) {
var line = new Line();
line.direction = (i % 2);
if (line.direction == 0) {
line.startX = 0;
line.startY = -H + i * H/100;
line.endX = W + line.startX;
line.endY = H + line.startY;
}
if (line.direction == 1) {
line.startX = 0;
line.startY = H - i * H/100;
line.endX = W - line.startX;
line.endY = H - line.startY;
}
objects.push(line);
line.draw();
}
}
initLines();
function render(c) {
c.clearRect(0, 0, W, H);
for (var i = 0; i < objects.length; i++)
{
ctx.save();
objects[i].update();
objects[i].draw();
ctx.restore();
}
}
function loop() {
render(ctx);
window.requestAnimationFrame(loop);
angle += Math.PI/360;
}
loop();
First I added a variable to keep track of rotation and increment it in the loop
Second I save and restore for each individual line, alternatively if all lines were going to perform the same transformation you could move that code before and after the drawing loop
Third to get the desired affect I translate so the center point is in the middle of the screen, then I rotate so that the lines are rotated, then I translate back because all the lines have coordinates on the interval [0, H]. Instead of translating back before drawing another option would be to use coordinates on the interval [-(H/2), (H/2)] etc.

HTML Canvas - Draw multiple rectangles in a loop

'm working on a project that calculates the number of pieces out of a sheet of paper.
I want to display the results using HTML Canvas.
So far I'm able to set the sheet size via canvas size, and also the piece size with a rectangle. These are set from text boxes #a0, #a1, #c & #d.
I'm after a result that draws the rectangles inside the canvas. The following is the code I have so far but is not working ...
function drawShapes(){
var canvas = document.getElementById('mycanvas');
canvas.width = (document.piecesForm.a0.value) /3;
canvas.height = (document.piecesForm.a1.value) /3;
var pieceWidth = (document.getElementById('c').value) / 3;
var pieceHeight = (document.getElementById('d').value) / 3;
var numAcross = canvas.width / pieceWidth;
var numDown = canvas.height / pieceHeight;
// Make sure we don't execute when canvas isn't supported
if (canvas.getContext){
// use getContext to use the canvas for drawing
var ctx = canvas.getContext('2d');
for(i = 0; i < numAcross; i++){
ctx.lineWidth = 1;
ctx.beginPath();
ctx.strokeRect(0,0,pieceWidth,pieceHeight);
ctx.moveTo(i*pieceWidth,0);
}
}
}
This will need another loop to display number of pieces down, any help would be great
I updated your code and it works now :
http://jsfiddle.net/gamealchemist/2cKm3/5/
var sheetSetup = {
layout: {
flipped: false,
piecePerRow: 0,
piecePerLine: 0
},
sheet: {
sizeX: 0,
sizeY: 0
},
piece: {
sizeX: 0,
sizeY: 0
}
};
function getSheetSizeX() {
return parseInt(document.piecesForm.a0.value);
}
function getSheetSizeY() {
return parseInt(document.piecesForm.a1.value);
}
function getfinalSizeX() {
return parseInt(document.piecesForm.c.value);
}
function getfinalSizeY() {
return parseInt(document.piecesForm.d.value);
}
function postMessage(dst, msg) {
document.getElementById(dst).innerHTML = msg;
}
function piecesCalc() {
var error = false;
// If the value of the sheet size textboxes is empty, then show an alert
if (!getSheetSizeX() || !getSheetSizeY()) {
postMessage("message1", "Sheet Size can't be empty!");
document.piecesForm.a0.focus();
error = true;
} else {
postMessage("message1", "");
}
// If the value of the final size textboxes is empty, then show an alert
if (!getfinalSizeX() || !getfinalSizeY()) {
postMessage("message2", "Final Size can't be empty!");
document.piecesForm.c.focus();
error = true;
} else {
postMessage("message2", "");
}
if (error) {
postMessage("answer", "---");
return;
}
var total1 = Math.floor(getSheetSizeX() / getfinalSizeX()) * Math.floor(getSheetSizeY() / getfinalSizeY());
var total2 = Math.floor(getSheetSizeY() / getfinalSizeX()) * Math.floor(getSheetSizeX() / getfinalSizeY());
if (total2 <= total1) {
sheetSetup.layout.flipped = false;
sheetSetup.layout.piecePerRow = Math.floor(getSheetSizeX() / getfinalSizeX());
sheetSetup.layout.piecePerLine = Math.floor(getSheetSizeY() / getfinalSizeY());
} else {
sheetSetup.layout.flipped = true;
sheetSetup.layout.piecePerRow = Math.floor(getSheetSizeY() / getfinalSizeX());
sheetSetup.layout.piecePerLine = Math.floor(getSheetSizeX() / getfinalSizeY());
}
sheetSetup.sheet.sizeX = getSheetSizeX();
sheetSetup.sheet.sizeY = getSheetSizeY();
sheetSetup.piece.sizeX = getfinalSizeX();
sheetSetup.piece.sizeY = getfinalSizeY();
var total = Math.max(total1, total2);
postMessage("answer", total + " per sheet");
// document.piecesForm.nbpieces.value = total;
}
function drawShapes() {
console.log(sheetSetup);
var displayRatio = 5;
// get the canvas element using the DOM
var canvas = document.getElementById('mycanvas');
canvas.width = Math.floor( sheetSetup.sheet.sizeX / displayRatio );
canvas.height = Math.floor( sheetSetup.sheet.sizeY / displayRatio );
// Make sure we don't execute when canvas isn't supported
if (canvas.getContext) {
// use getContext to use the canvas for drawing
var ctx = canvas.getContext('2d');
var usedWidth = sheetSetup.layout.flipped ? sheetSetup.piece.sizeY : sheetSetup.piece.sizeX;
var usedHeight = sheetSetup.layout.flipped ? sheetSetup.piece.sizeX : sheetSetup.piece.sizeY;
usedWidth /= displayRatio;
usedHeight /= displayRatio;
for (var line = 0; line < sheetSetup.layout.piecePerLine; line++) {
for (var row = 0; row < sheetSetup.layout.piecePerRow; row++) {
ctx.strokeRect(row * usedWidth, line * usedHeight, usedWidth, usedHeight);
}
}
}
}
Make
var total=0 as Global variable
The code is
for (i = 0; i < numAcross; i++) {
ctx.lineWidth = 1;
ctx.beginPath();
ctx.strokeRect(i*pieceWidth, 0, pieceWidth, pieceHeight);
ctx.moveTo(i * pieceWidth, 5);
}
for (i = 0; i < total-numAcross; i++) {
ctx.lineWidth = 1;
ctx.beginPath();
ctx.strokeRect(i*pieceWidth, pieceHeight, pieceWidth, pieceHeight);
ctx.moveTo(i * pieceWidth, 5);
}
Fiddle:
Fiddle

For-Loop not running when called

Code:
function SnakeGame() {
"use strict";
/***** Constant & Global Variables ***********************************/
var canvas = $("#canvas")[0];
var ctx = canvas.getContext('2d');
var width = $("#canvas").width();
var height = $("#canvas").height();
var snake, food;
function Snake() {
var startLength = 5; // default for starting size of snake
this.body = [];
this.chgStartLength = function(length) {
startLength = length;
};
this.create = function() {
var i;
for(i=0; i>5; i++) {
this.body.push({x:i, y:0});
}
};
}
var paintCanvas = function() {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, width, height);
ctx.strokeStyle = 'black';
ctx.strokeRect(0, 0, width, height);
};
var paintFrame = function() {
var i, length = snake.body.length;
for(i=0; i<length; i++) {
var cell = snake.body[i];
ctx.fillStyle = 'black';
ctx.fillRect(cell.x*10, cell.y*10, 10, 10);
ctx.strokeStyle = 'white';
ctx.strokeRect(cell.x*10, cell.y*10, 10, 10);
}
};
this.start = function() {
snake = new Snake();
snake.create();
paintCanvas();
paintFrame();
console.log(snake.body); //for testing
};
}
For some reason snake.body is an empty array even after start is executed.
for(i=0; i>5; i++) {
That > is facing in the wrong direction, I believe.
for(i = 0; i < 5; i++) {

Categories

Resources