I'm trying to draw a circle and then have an image follow the circle around. Later I want to rotate and move the image around with respect to the circle drawn. The problem I'm facing is that when I try to rotate the image it won't rotate. It also doesn't show me an error in the console. I have functions allowing me to move the circle around and the image moves with it, I just can't seem to rotate the image.
Here is the code:
draw: function(){
//draw self on canvas;
//intended only to be called from update, should never
//need to be deliberately called
ctx = this.context;
ctx.save();
ctx.fillStyle="#000000";
ctx.beginPath();
//void arc(double x, double y,
// double radius, double startAngle, double endAngle,
// optional boolean anticlockwise = false);
ctx.arc(this.x,this.y,this.size,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
//ctx.translate(this.x, this.y);
ctx.rotate(this.imgAngle);
//draw the hammer
ctx.drawImage(this.hammer,this.hammerX,this.hammerY,100,100)
ctx.rotate(Math.PI/2);
ctx.restore();
},
Live Demo
Try changing your code to the following. You need to perform the rotation before drawing. You can translate the canvas to the entities position and then draw the image at x:0,y:0 to get the effect you desire. Note I did 0-50,0-50 because that puts the point of origin in the center since the width and height are 100. Meaning your image will rotate around its center rather than around its corner.
//draw the hammer
ctx.translate(this.hammerX, this.hammerY);
ctx.rotate(this.imgAngle);
ctx.drawImage(this.hammer,0-50,0-50,100,100);
The rotation will only affect drawings made AFTER the rotation is done.
You could try moving the rotate calls to just before the object that needs to be rotated?
Related
I have a roulette wheel created with HTML5 canvas and currently each slice is a plain color generated by using the fillStyle(), beginPath(), stroke(), then fill() methods.
I would like to use images that that crop appropriately in the shape of the slice, but I'm not sure how to implement this using drawImage().
Here's the jsfiddle
http://jsfiddle.net/pyD2q/2/
Any help or resources is appreciated.
Instead of filling the color in you can use it as a clipping mask instead. For each arc, set clip, draw the image and repeat.
Something like this (untested):
for (i = 0; i < s.members.length; i++) {
angle = s.startAngle + i * s.arc;
ctx.beginPath();
ctx.arc(s.width / 2, s.height / 2, s.outsideRadius, angle, angle + s.arc, false);
ctx.arc(s.width / 2, s.height / 2, s.insideRadius, angle + s.arc, angle, true);
ctx.save(); /// store current clip-state
ctx.clip(); /// set current arc as clipping mask
ctx.drawImage(someImageArray[i], x, y, width, height);
ctx.restore(); /// restore clip-state
ctx.stroke(); /// stroke arc
}
You will of course also need to place the images correctly relative to the section and if you want to rotate the image you would need to rotate it at this point.
In that regard I would recommend creating this wheel on an off-screen canvas. This way you only need to draw the off-screen canvas into the main canvas rotated and what have you (saves you the trouble of calculating each angle as well and the performance will be better).
Lets say I draw a rectangle on the html canvas:
draw.rect(x, y, w, h, color); // color red
After I draw the rectangle I will draw a circle on the same canvas:
draw.circle(x, y, d, color); // color green
I have to randomly generate the coordinates for the circle.
Both draw functions are inside a loop - set interval - and a clear canvas function.
I am wondering if there is a way to make sure I won't draw the circle over the rectangle.
In a normal situation that would be easy, just remember the last coordinates of the rectangle and choose different ones for the circle - but for other reasons I cannot do it.
Would it be possible to check the canvas for the color of the rectangle which was drew on it, and make sure the circle will not be drawn over that color?
I know how to analyze the color of a background image, but I don't know if the above is possible.
For background images I use:
ctx.getImageData()
You will always be able to store the last drawn coordinates.
At least by using a glval var. which you can make not-so ugly
by using a namespace :
window.myApp = {};
myApp.lastDrawnRect = { x:-1, y:0, w:0, h:0 };
myApp.storeRect= function(x,y,w,h) {
var rect = myApp.lastDrawnRect;
rect.x = x; rect.y = y; rect.w = w;
}
and when you draw your rect you can store the coordinates :
raw.rect(x, y, w, h, color); // color red
myApp.storeRect(x,y,w,h);
You might want to store that the rectangle is not drawn by
taking the convention that x==-1 ===> rectangle cleared.
Then you can use that data when you draw your circle, with
classic boundary checking.
Whatever is drawn on the canvas is accessible using getImageData.
A canvas is a pixel matrix with drawing helpers attached.
Before drawing the circle you can ctx.getImageData(x, y, 1, 1) and check if it's red.
You most probably have to check the pixels on the edge of the circle, not the center.
Start from the circle equation.
It's been discussed before.
I've got a canvas that includes images, I'm re-drawing 1 pixel lower each time to give the effect of falling. I've got the images in an array and I just place them 1 pixel lower without recreating the image.
Is it possible to add a border dynamically to images that reach a certain point and if so, how?
Yes, all you have to do is draw a path outside the image and call ctx.stroke() to make the border.
So say the image has the coordinates x and y, with a width and height of w and h, you just do:
ctx.rect(x, y, w, h);
ctx.stroke();
Want a different colored border?
ctx.strokeStyle = 'blue';
Thicker?
ctx.lineWidth = 5;
If you know your images' size and location and as you draw them you probably do, You can use the .rect canvas method to draw a rectangle around the image.
I have found similar questions out there, but no answer. I have sketched a circle like so
ctx.strokeStyle='rgb(0,0,0)';
ctx.lineWidth=10;
ctx.beginPath();
ctx.arc(100,100,45,0,Math.PI*2,true);
ctx.closePath();
ctx.stroke();
which gives a circle situated at (100,100) with radius 45, plus 5 for the linewidth, making it a circle of radius 50. Now, I want to sketch the exact same circle, but another color, and only 1/4 of the original circumfrance (think the XBOX 360 red ring of doom). So I tried this
ctx.strokeStyle='rgb(0,250,0)';
ctx.lineWidth=10;
ctx.beginPath();
ctx.arc(100,100,45,0,Math.PI/2,true); //use 1/4 of original angle
ctx.closePath();
ctx.stroke();
But that has the really annoying aspect of connecting the first and last points (sometimes I wonder who created the canvas element, like when embedding text, but don't get me started on that...)
I've commented out the line you don't want. By calling closePath(), you are closing the path of your arc.
Example
JavaScript
ctx.strokeStyle='rgb(0,250,0)';
ctx.lineWidth=10;
ctx.beginPath();
ctx.arc(100,100,45,0,Math.PI/2,true); //use 1/4 of original angle
//ctx.closePath();
ctx.stroke();
jsFiddle.
I am using an HTML canvas and javascript and I need to clear all of the pixels underneath a shape created by closing a path (for example, I am using flot, and I want to make rounded corners, and to do this, I first need to remove the square corners by drawing a curve on top of the corner to remove the desired pixels).
Right now, I am doing this by just filling the shape with the same color as the background, which can imitate what I want to do, but, it is not ideal as it makes it impossible to place the chart on top of non-solid backgrounds without seeing the square corners. I know that there is a clearRect method that would do what I want to do, but with only rectangles, I need to do it with any closed shape. Is it possible, and if so, how would I do it?
brainjam's code was heading in the right direction, but didn't fully solve the problem. Here's the solution:
context.save();
context.globalCompositeOperation = 'copy';
context.fillStyle = 'rgba(0,0,0,0)';
//draw shape to cover up stuff underneath
context.fill();
context.restore();
Here's an example of a function that will clear a circle from a canvas:
var clearCircle = function(x, y, radius)
{
context.save();
context.globalCompositeOperation = 'destination-out';
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.fill();
context.restore();
};
I think what you want is a clipping region, defined by the clip() function. The latter takes a bunch of paths. Here's an example.
This is a little different from what you are specifically asking (which is to remove pixels after drawing them), but actually not drawing the pixels in the first place is probably better, if I understand your requirements correctly.
Edit: I now think I understand that what you want to do is clear pixels to transparent black. To do that, after having defined your paths, do something like this:
context.fillStyle = 'rgba(0,0,0,0)';
context.fill();
The first statement sets the fill color to transparent black.
Use globalCompositeOperation = 'destination-out' instead of 'copy', it will erase all pixels of the shape in the canvas.
See all kinds of composition here
very usefull !