Scale command applying to multiple shapes - html

Wondering why the scale parameter of the variable ´ell´ is applying to the next two circles I have created as well:
var ell=canvas.getContext("2d")
ell.beginPath()
ell.lineWidth=2
ell.fillStyle="#FFFFFF"
ell.strokeStyle="#000000"
ell.scale(1.2,0.5)
ell.arc(125,190,30,0,2*Math.PI,false)
ell.fill()
ell.stroke()
var circ=canvas.getContext("2d")
circ.beginPath()
circ.lineWidth=1
circ.fillStyle="#FFFFFF"
circ.strokeStyle="#000000"
circ.arc(150,95,15,0,2*Math.PI,false)
circ.fill()
circ.stroke()
var circ2=canvas.getContext("2d")
circ2.beginPath()
circ2.fillStyle="#1d1d1d"
circ2.arc(155,90,4,0,2*Math.PI,false)
circ2.fill()
It's supposed to be an eyeball, the first shape is an oval and the next two are supposed to be circles, however they are getting squished by the scale command, and their positions are thrown off as well.
Any help appreciated, thanks!!

You could either use setTransform and reset the scale manualy or
call save() before applying the scale and call restore() when your done with it.
var ctx=canvas.getContext("2d")
ctx.save(); // save the context state
ctx.beginPath();
ctx.lineWidth=2;
ctx.fillStyle="#FFFFFF";
ctx.strokeStyle="#000000";
ctx.scale(1.2,0.5);
ctx.arc(125,190,30,0,2*Math.PI,false);
ctx.fill();
ctx.stroke();
ctx.restore(); // restore the state to the last save()
// you can reuse the same context
ctx.save();
ctx.beginPath();
draw the second circle...
take a look at
https://developer.mozilla.org/en/Canvas_tutorial/Transformations

Related

Drawing rectangle on the canvas in html 5

I am using html5 canvas and drawing rectangles on the canvas with the following code,
function drawRectangle(mouseX,mouseY)
{
ctx.beginPath();
ctx.rect(25,25,100,100);
ctx.fill();
ctx.stroke();
}
I am getting rectangle on the canvas,but the problem is
Within that rectangle multiple lines is coming as the border.I dont want those lines.
Please suggest me.
Why dont you just use fillRect?
function drawRectangle(mouseX,mouseY)
{
ctx.beginPath();
ctx.fillRect(25,25,100,100);
}

HTML5 Canvas clip overlaps previous clip

I have this weird issue where setting up multiple clip rectangles in HTML5 causes the drawing to bleed/overlap into the previous clip boxes, even when each one is contained in a ctx.save() - ctx.restore().
Here is the code example:
var c=document.getElementById("myCanvas2");
var ctx=c.getContext("2d");
// 1st clip
ctx.save();
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.clip();
// draw red rectangle after 1st clip()
ctx.fillStyle="red";
ctx.fillRect(0,0,300,140);
ctx.restore();
// 2nd clip
ctx.save();
ctx.rect(140,20,100,100);
ctx.stroke();
ctx.clip();
// draw blue rectangle after 2nd clip
ctx.fillStyle="blue";
ctx.fillRect(0,0,300,140);
ctx.restore();
And a jsfiddle:
http://jsfiddle.net/4eXw9/1/
Is there a way to stop a clip call from bleeding/overlapping previous clips?
You are missing a beginPath() on the second clip:
// 2nd clip
ctx.save();
ctx.beginPath()
ctx.rect(140,20,100,100);
ctx.stroke();
ctx.clip();
Modified fiddle
What happens is that your new rect is merged with the first one since stroking/filling does not clear the path - so both are stroked/filled again. To clear the path you must explicitly clear it using beginPath(). As the path also is the basis for clip()..

Eraser tool in html5 canvas

Hi i am building a windows store app with html5 and javascript in my app i am trying to implement an eraser tool but this is problematic because if the user moves an image or another layer to where they've previously erased, they see the white drawing where they erased.
i have been trying to do the eraser tool from different ways for example i have changed the default globalCompositeOperation to "destination-out" like this code
//Here is the error.
if (clickTool[j] == "eraser") {
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = 'rgba(255,0,0,0.5);';
ctx.strokeStyle = 'rgba(255,0,0,0.5);';
}
else {
ctx.globalCompositeOperation = "source-over";
ctx.strokeStyle = clickColor[j];
}
but unfortunately it doesn´t work for me. i have uploaded all my code to this link:
My code
Please i would like to somebody could help me.
Thanks and i'm sorry for my speech , i'm mexican.
Use multiple layers. Have one canvas for the background image and another for the drawing; that why you never erase any of the background image.
If you need to, you can have multiple layers as they don't generally impact performance.
And of course if you can combine layers, say the last drawn squiggle to the background layer, if you deem a drawing to be "permanent".
Maintain a array of mid points. Use the globalCompositeOperation as 'destination-out' first and 'source-over' later to make a transparent eraser trail .
Following is the code that you need to use with a mouse move function
var handleMouseMove = function (event) {
midPt = new createjs.Point(oldPt.x + stage.mouseX>>1, oldPt.y+stage.mouseY>>1);
if(curTool.type=="eraser"){
var tempcanvas = document.getElementById('drawcanvas');
var tempctx=tempcanvas.getContext("2d");
tempctx.beginPath();
tempctx.globalCompositeOperation = "destination-out";
tempctx.arc(midPt.x, midPt.y, 20, 0, Math.PI * 2, false);
tempctx.fill();
tempctx.closePath();
tempctx.globalCompositeOperation = "source-over";
drawingCanvas.graphics.clear();
// keep updating the array for points
arrMidPtx.push(midPt.x);
arrMidPty.push(midPt.y);
stage.addChild(drawingCanvas);
stage.update();
}
};
I use this code to make a eraser that behaves like pen and fills up transparent color instead of white

Canvas Animation Not Rendering

I'm new to the canvas tag and am playing around with some animation. Basically, I'm trying to setup a "ground" section composed of multiple images (similar to an 8bit side scroller game like Mario Brothers). The ground will be composed of multiple images, which I've built a constructor function to load these and tile them across the bottom.
function Ground(context,ImageName,ImgX,ImgY,ImgW,ImgH){
this.width=ImgW;
this.height=ImgH;
this.x=ImgX;
this.y=ImgY;
img=new Image();
img.onload=function(){context.drawImage(img,ImgX,ImgY,ImgW,ImgH);};
img.src='images/'+ImageName;};
This seems to work out just fine. I've then setup the rest of the animation, including a basic setup for Key Left/Right events, like so:
window.onload=function(){
var canvas=document.getElementById('canvas'),
context=canvas.getContext('2d'),
Grounds=[],
ImgX=-150; // INITIAL STARTING X FOR FIRST GROUND TILE
// INSERT GROUND ELEMENTS
for(var i=0,l=8; i<l; i++){
var ImgX+=150;
Grounds[i]=new Ground(context,"ground.png",ImgX,650,150,150);
};
// ASSIGN LEFT/RIGHT KEYS
window.addEventListener('keyup',function(event){
switch(event.keyCode){
case 37:
for(var i=0,l=Grounds.length; i<l; i++){
Grounds[i].x+=10;
};
break;
case 39:break;
};
});
// ANIMATION LOOP
(function drawFrame(){
window.mozRequestAnimationFrame(drawFrame,canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
}());
};
I know exactly what my problem is, but don't know how to solve it. The animation loop is clearing the canvas every frame, but not redrawing the updated position (if any) when the user presses the left arrow key.
I'm missing the redraw part here and I'm not exactly sure how to handle this or if I'm approaching this entirely wrong. Any help is very appreciated! Thanks!
First of all you're incrementing the property x of the ground tiles but that property is not even used anywhere in your code. Modify your code so that the onload event of those image objects draws the image according to their own x property so changes to it will actually affect what is drawn. Also add the image object as a property of the Ground object so you can access it later on from outside.
Your approach is really not so good but if you want to do it without going back to 0 do it as follows:
function Ground(context,ImageName,ImgX,ImgY,ImgW,ImgH){
this.width=ImgW;
this.height=ImgH;
this.x=ImgX;
this.y=ImgY;
var self = this; // Add local reference to this Ground instance
this.img=new Image(); // img is now a property too
this.img.onload=function(){context.drawImage(this, self.x, self.y,self.width,self.height);};
this.img.src='images/'+ImageName;};
Ok so now you can change the property x of the ground tiles and call the draw function of it again (which is the onload event).
Grounds[i].x+=10;
Grounds[i].img.dispatchEvent(new Event("load"));
Please note that you should really make the updates of all the values first and then all the draw calls separately.
Can you not just add a draw method? You usually so something like this:
init -> update -> clear, redraw -> update -> clear, redraw -> ...
// ANIMATION LOOP
(function drawFrame(){
window.mozRequestAnimationFrame(drawFrame,canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
contect.drawImage(...);
}());

HTML5 Canvas - Different Strokes

I have to draw a graph with 3 different lines. A line graph.
I tried doing this:
function draw()
{
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.lineWidth=10;
ctx.strokeStyle="teal";
ctx.moveTo(10,CompanyA[0]);
ctx.lineTo(110,CompanyA[1]);
ctx.lineTo(210,CompanyA[2]);
ctx.stroke();
ctx.strokeStyle="green";
ctx.moveTo(10,CompanyB[0]);
ctx.lineTo(110,CompanyB[1]);
ctx.lineTo(210,CompanyB[2]);
ctx.stroke();
ctx.strokeStyle="yellow";
ctx.moveTo(10,CompanyC[0]);
ctx.lineTo(110,CompanyC[1]);
ctx.lineTo(210,CompanyC[2]);
ctx.stroke();
}
But apparently, the last stroke draws for all the lines. So I get 3 yellow lines, instead of a Teal, a Green and a Yellow one.
I tried creating three different Context (ctx1, ctx2 and ctx3), but for some reason, all were drawn with the "ctx3.stroke()" call.
What would be the correct way to do this?
Add a ctx.beginPath() call before every line, and also a ctx.closePath() after every ctx.stroke()
If you don't, every time you call the stroke() method, not only the new line will be drawn but also all the previous lines will be drawn again (with the new strokeStyle), since it's the same line path that is still open.
Although there is a functional answer here, I'd just like to add this.
var ctx1 = canvas.getContext("2d");
var ctx2 = canvas.getContext("2d");
var ctx3 = canvas.getContext("2d");
They all refer to the same object. It does not create a new context, it uses the one that's already attached to the canvas element. Delta is totally right in saying that it strokes yellow over the entire path because you did not begin a new path. ctx.beginPath() will solve your troubles.