PDA

View Full Version : Help with javascript & <canvas> tag.



newshound
07-28-2008, 01:08 PM
curcanvas is a <canvas> element.



function firefoxrotate(rotnum) {
var tempimg = new Image();
var curcanvas = document.getElementById(curmover);
curcanvasctx = curcanvas.getContext("2d");
tempimg.src = curcanvas.toDataURL();

curcanvasctx.clearRect(0, 0, curcanvas.width, curcanvas.height)

curcanvasctx.translate(100, 100);
curcanvasctx.rotate(rotnum/180 * Math.PI);
curcanvasctx.translate(-100, -100);

curcanvasctx.drawImage(tempimg,0,0);
}


This code rotates the image once, but any future calls of the ffrot() function result in it exiting the function at the red line.

I can find little to no help on the web since <canvas> is not a very common tag. What gives? Anybody know what I'm doing wrong here?

jscheuer1
07-28-2008, 01:52 PM
I think because the second time around, their no longer is the type of data expected in curcanvas to act upon via the toDataURL() method. I've worked with the canvas tag before, and I believe this same thing happens, even when toDataURL() isn't used. Since you are rotating 180 degrees anyway, the second call should put the image back the way it was. So why not save it and just make it the src (or whatever) of the canvas the second time. You would need a flag or some other way to determine the current state of the canvas. To be more specific, I would need a link to the page:

Please post a link to the page on your site that contains the problematic code so we can check it out.

newshound
07-28-2008, 02:38 PM
I think because the second time around, their no longer is the type of data expected in curcanvas to act upon via the toDataURL() method. I've worked with the canvas tag before, and I believe this same thing happens, even when toDataURL() isn't used. Since you are rotating 180 degrees anyway, the second call should put the image back the way it was. So why not save it and just make it the src (or whatever) of the canvas the second time. You would need a flag or some other way to determine the current state of the canvas. To be more specific, I would need a link to the page:

The rotate() function's parameter is in radians, which means that 2*pi is a full rotation.

Since 2*pi is equal to 360 degrees, then 180 degrees is 1*pi. Thus, if you want to rotate by 45 degrees, you divide by 180 and multiply by pi, in order to get .25 * pi, which will be 1/8th of a full rotation.

Anyways, my point is that I'm not rotating by 180 degrees each time... I'm rotating by a variable amount of degrees.


Please post a link to the page on your site that contains the problematic code so we can check it out.

Unfortunately, I'm just tinkering on my computer and have no site. After "yourimage.png" is replaced with the name of an actual image, the following code should make this run correctly though.




<html>
<head>
<title>Web Site Thing</title>

<script>
function firefoxrotate(rotnum) {
var tempimg = new Image();
var curcanvas = document.getElementById(curmover);
curcanvasctx = curcanvas.getContext("2d");

alert('1');

tempimg.src = curcanvas.toDataURL();

alert('2');

curcanvasctx.clearRect(0, 0, curcanvas.width, curcanvas.height);

curcanvasctx.translate(100, 100);
curcanvasctx.rotate(rotnum/180 * Math.PI);
curcanvasctx.translate(-100, -100);


alert('3');
curcanvasctx.drawImage(tempimg,0,0);
alert('4');
}
</script>


</head>





<body id="mybody">

<script>
var ni = document.getElementById('mybody');
var divIdName = "img1";
i = new Image();
i.src = "yourimage.png";
var newdiv = document.createElement('canvas');
newdiv.setAttribute('id',divIdName);
newdiv.setAttribute('width', '200');
newdiv.setAttribute('height', '200');
newdiv.getContext("2d").drawImage(i,0,0);
ni.appendChild(newdiv);
curmover="img1";
</script>

<div align=right>
<button onclick="firefoxrotate(-15)">FF Rot-15</button>
<button onclick="firefoxrotate(15)">FF Rot15</button>
<button onclick="firefoxrotate(45)">FF Rot45</button>
<button onclick="firefoxrotate(135)">FF Rot135</button>
</div>

</body>
</html>

newshound
07-28-2008, 03:55 PM
Ok, well, I ended up just detecting what the image is through the canvas' id, so I guess even though I didn't figure out how to get the image from the canvas more than once, I've gotten the code to work.

jscheuer1
07-28-2008, 04:01 PM
OK, I got it. There were a few problems. First of all, before the image is cached, it wouldn't even load without error on the line:


newdiv.getContext("2d").drawImage(i,0,0);

This problem would be more dramatic on a live page. Also, I just didn't like the idea of drawing to the canvas before it was appended to the page, so I switched things around there and made the initial drawing contingent upon the load event of the image. There were a number of undeclared variables, I declared them.

Now this business of:


tempimg.src = curcanvas.toDataURL();

In testing here, the code never executed that line, there was always an error.

I think it's just wrong. The src of an image object is an image file. Here there is either a data mismatch (toDataURL of the canvas tag is not the same as toDataURL of an actual image would be, and perhaps is null) or you are feeding it the raw image data when it expects a file containing the image data, or more likely there is a security violation. Further, since all you are doing is rotating the canvas, there is no need to use data for the image updated from the last rotation. The very same image originally used will suffice, and guess what? - It's already loaded. This allows a number of steps to be skipped.

This can probably be simplified further, and definitely be written so as to not expose so many global variables, as well as to use valid HTML code, but it works:


<html>
<head>
<title>Web Site Thing</title>


<script type="text/javascript">
function firefoxrotate(rotnum) {
var curcanvas = document.getElementById(curmover);
var curcanvasctx = curcanvas.getContext("2d");

curcanvasctx.clearRect(0, 0, curcanvas.width, curcanvas.height);

curcanvasctx.translate(100, 100);
curcanvasctx.rotate(rotnum/180 * Math.PI);
curcanvasctx.translate(-100, -100);

curcanvasctx.drawImage(i,0,0);
}
</script>



</head>





<body id="mybody">

<script type="text/javascript">

var ni = document.getElementById('mybody');
var divIdName = "img1";
var i = new Image();
var newdiv = document.createElement('canvas');
newdiv.setAttribute('id',divIdName);
newdiv.setAttribute('width', '200');
newdiv.setAttribute('height', '200');
var ctx = newdiv.getContext("2d");
ni.appendChild(newdiv);
i.onload = function(){ctx.drawImage(i,0,0);};
i.src = "yourimage.png";
var curmover="img1";

</script>

<div align=right>
<button onclick="firefoxrotate(-15)">FF Rot-15</button>
<button onclick="firefoxrotate(15)">FF Rot15</button>
<button onclick="firefoxrotate(45)">FF Rot45</button>
<button onclick="firefoxrotate(135)">FF Rot135</button>
</div>

</body>
</html>

magicyte
07-28-2008, 08:10 PM
Are you saying this script only works in FF?

-magicyte

jscheuer1
07-29-2008, 03:57 AM
Are you saying this script only works in FF?

-magicyte

It works in all browsers that support the canvas tag. Currently that includes Opera 9.5, FF 3, Safari 3, probably others. In fact, I wouldn't be surprised if it wasn't a situation where IE is about the only browser it doesn't work in.

Here is a version I striped down (to, I think the essentials) then beefed up to validate, and have only one exposed global, the main function's name:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Canvas Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function firefoxrotate(rotnum) {
var f = firefoxrotate;
f.ctx.clearRect(0, 0, f.newdiv.width, f.newdiv.height);

f.ctx.translate(100, 100);
f.ctx.rotate(rotnum/180 * Math.PI);
f.ctx.translate(-100, -100);

f.ctx.drawImage(f.i,0,0);
}
</script>
</head>
<body>
<script type="text/javascript">
;(function(){
var f = firefoxrotate;
f.i = new Image();
f.newdiv = document.createElement('canvas');
f.newdiv.setAttribute('width', '200');
f.newdiv.setAttribute('height', '200');
if(!f.newdiv.getContext){
firefoxrotate = function(){return;};
return;
}
f.ctx = f.newdiv.getContext("2d");
document.body.appendChild(f.newdiv);
f.i.onload = function(){f.ctx.drawImage(f.i,0,0);};
f.i.src = "yourimage.png";
})();
</script>
<div align=right>
<button onclick="firefoxrotate(-15)">FF Rot-15</button>
<button onclick="firefoxrotate(15)">FF Rot15</button>
<button onclick="firefoxrotate(45)">FF Rot45</button>
<button onclick="firefoxrotate(135)">FF Rot135</button>
</div>
</body>
</html>