I have an HTML canvas. Inside it I've drawn a hexagon. The hexagon rotates in place.
Well now I want this rotating hexagon to move along a set path. I want to be able to track it's location.
Normally when you want to move an object you say: (object.x+howmuchtomove) and it will simply
move by that much, and you can track it's whereabouts by just adding object.x+howmuchtomove to get the x coord.
Well in this case I'm using translate and rotate to give it the rotating effect. So adding +2 to it's x location simply makes it rotate in a bigger circle.
Here is what I've got, thanks!
retObject.draw = function() {
// Wipe the canvas
ctx.fillStyle = "rgba(0, 0, 0, 1)";
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw rotating shape
ctx.save(); // Don't rotate everything
ctx.strokeStyle="red"; // Set Color
ctx.translate(356.5, 700); // Center pivot inside hexagon
ctx.rotate(rotValue*(Math.PI/180)); // Rotate
ctx.translate(-356.5, -700); // Un-Translate
for (i=0;i<3;i++) {
ctx.beginPath();
ctx.moveTo(300, 700);
ctx.lineTo(330, 650);
ctx.lineTo(383, 650);
ctx.lineTo(413, 700);
ctx.lineTo(383, 750);
ctx.lineTo(330, 750);
ctx.lineTo(300, 700);
ctx.stroke(); // Draw Hexagon
}
ctx.restore(); // Get back normal
}
Note that draw() is inside of a loop so that it gets called every frame.
So, for simplicity sake, say I just want this rotating hexagon to drop straight down.
Basically I'm wanting to add +1 to it's y coordinate every frame.
Well I figured it out and I feel stupid.
You simply add the desired move amount to the first translate ONLY.
So:
ctx.translate(356.5, 700);
Becomes:
ctx.translate(356.5, 700+moveAmount);
That will make it move straight down by "moveAmount" per frame.
Maybe this will help someone lol
Related
I'm making a Zelda-like game on canvas + js and I don't how to do (or even if it can be done) to apply a filter to a sprite.
I have a scenario drawn, I have multiple characters (enemies, npcs and the player) and I'm trying to do an animation when the player kills an enemy. I'd like to make them "tilt" before I change the enemy sprite with an explosion animation. I'd like to change the whole color of the enemy sprite something like "enemy sprite -> red enemy sprite -> enemy sprite -> red enemy sprite -> explosion".
My question, can I apply a color filter to an image drawn with canvas drawImage? The code to draw the enemy into the canvas scenario is pretty simple:
ctx.drawImage(img, posX, posY, img.width, img.height);
And I have also tried this (as suggested in this other question):
ctx.globalAlpha = 0.62;
ctx.globalCompositeOperation = 'source-atop';
ctx.fillStyle = 'red';
ctx.fillRect(posX, posY, img.width, img.height);
But it applies a mask to a rectangle and not just the sprite (in this picture I applied the above code to every sprite just to watch if it worked):
Any suggestions or help? Thanks!!
I'm playing around with Canvas Code. I wrote a function that draws out a path
function draw_faces() {
var canvas = document.getElementById("faces_bkgd");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
var happy_face = new Path2D();
happy_face.rect(10,10,100,100);
ctx.fillStyle = "rgb(0,0,200)";
ctx.fill(happy_face);
happy_face.moveTo(50,50);
happy_face.lineTo(90,90);
happy_face.lineTo(90,50);
ctx.fillStyle = "rgb(200,0,0)";
ctx.fill(happy_face);
ctx.save();
ctx.translate(50,50);
ctx.fillStyle="rgb(0,200,0)";
ctx.fill(happy_face);
ctx.restore();
}
fiddle demo
It gives me the following output at the top left of the page, there is a red square with a blue triangle in it. To the bottom of the red square, there is a overlapping green square with a triangle cutout.
Why is it a green square with a triangle cutout instead of a green square with a blue triangle in it?
Also, what do you guys use to debug Canvas on Web Inspector for Safari?
EDIT: I created some images explaining step by step what is happening. If you would like me to go into more detail please let me know. If there are certain parts you do not understand please let me know. If there are terms (methods, etc) that don't make sense let me know. Anything vague let me know. :)
Here are the important parts of you code with comments on what really is happening.
First part of your code draws a blue square with an instance of Path2D that you have defined as a rect.
var happy_face = new Path2D();
happy_face.rect(10, 10, 100, 100);
ctx.fillStyle = "rgb(0,0,200)";
ctx.fill(happy_face);
Then instead of creating a new instance of Path2D, you use your previous variable, happy_face, that is still defined as a rect and now you cut out a triangle and set the color to red and draw it.
//The moveTo and lineTo cut out a triangle in your square.
happy_face.moveTo(50, 50);
happy_face.lineTo(90, 90);
happy_face.lineTo(90, 50);
ctx.fillStyle = "rgb(200,0,0)";
ctx.fill(happy_face);
Since you didn't move this square with a triangle cut out in it, you draw on top of your blue square. This gives the impression the triangle you cut out is blue, but that's just the old square underneath.
Going to ignore the save and restore methods since they don't do anything worthwhile. You then do a tanslate.. which just moves the pointer from where you start drawing from (0,0) to (50, 50). At ths point you change colors from red to green and you start drawing at (50, 50) happy_face ( the old square with a triangle cut out in it ).
ctx.save();
ctx.translate(50,50);
ctx.fillStyle="rgb(0,200,0)";
ctx.fill(happy_face);
ctx.restore();
Unfortunately you can't debut "canvas". Because when you draw something, you can't just move it. It's literally drawn on the canvas. If you draw a square on top of the other square, well the previous square is lost.
I am trying to flip an image using the scale() method.
I have this code:
ctx.save();
ctx.scale(-1, 1);
ctx.drawImage(Img, 0, 0, 100, 100);
ctx.restore();
When I put 1, 1 into the scale parameter, or any other real number, the scale function works fine. But once I put a negative parameter such as -1 (to flip image horizontally) the image doesn't draw at all. The code is in a function with a 12 fps setInterval. I've looked everywhere but can't seem to find a solution. Any help or suggestions would be appreciated. Thanks!
as being said by markE, whenever you scale, rotate or transform the canvas, the coordinates you are using will react to the change in the canvas transformation - in your case sending the image off the canvas. In order to flip the image in place, you should consider using translate with the width of the image as first parameter:
ctx.save();
//The scale will flip the whole canvas, and will move the image
//to the left (by the image width size)
ctx.scale(-1, 1);
//Using translate to move the image back to it's original origin
ctx.translate(Img.width, 0)
ctx.drawImage(Img, 0, 0, 100, 100);
ctx.restore();
I'm new to canvas in html5 and would like to know how to animate a custom shape with lots of coordinates. I searched the web but with n o results. I'm only seeing results for circles or squares.
Here's an example of a random drawing. I would like it to move around the screen without setting coordinates for each point. http://jsfiddle.net/ZJdus/
var drawing = function(){
// rand drawing drawing
context.strokeStyle = "red";
context.beginPath();
context.moveTo(318, 200);
context.lineTo(183, 87);
context.lineTo(446, 125);
context.lineTo(446, 202);
context.lineTo(383, 236);
context.lineTo(318, 202);
context.lineTo(318, 125);
context.lineTo(446, 125);
context.lineTo(183, 236);
context.lineTo(318, 125);
context.lineTo(383, 187);
context.lineTo(383, 125);
context.lineTo(613, 180);
context.lineTo(446,400);
context.lineTo(413, 180);
context.lineTo(350, 180);
context.lineTo(318, 202);
context.lineTo(350, 180);
context.lineTo(183, 125);
context.stroke();
};
Is there a way to achieve this?
I'm also fairly new to Javascript so please explain as much as possible if you can.
Thanks
You can use translate() before you redraw the shape:
/// clear canvas before each redraw
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
/// translate canvas (move origin)
context.translate(deltaX, deltaY);
... draw points here...
/// reset translate (faster than save()/restore())
context.translate(-deltaX, -deltaY);
Modified fiddle here
Optionally, instead of resetting the translate just use it as delta values directly instead of the absolute delta as now.
You can also add the delta values directly on your coordinates but that is slower than using the translate approach.
Hope this helps.
If your shape doesn't change, you should absolutely not redraw it every frame. Instead draw the shape once to a buffer canvas and then use drawImage at the location to animate the shape.
var drawing = //same as your code above only context is a buffer canvas...
contextOfDisplayedCanvas.drawImage(canvasWithShape, shape.x, shape.y);
Let me know if that doesn't make sense and I can expand.
I wish to draw a rectangle on my canvas but stretching the start point. but how do i erase the previous rectangles drawn during the process. I mean if my background color is red and i want to draw a black rectangle over it. while erasing the intermediate rectangles drawn during rubber banding, i wish to retain the background.
The question is a little hard to understand, but I'm assuming what you want to do is the following using getImageData and putImageData:
// save the entire canvas (in this example, its 500 x 500) to be restored later
image = context.getImageData(0, 0, 500, 500);
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height); // clear entire canvas
context.putImageData(image, 0, 0); // restore entire canvas saved previously
/** Now, draw other stuff on top of the canvas **/
}
You need to redraw the portion of the background the black rectangle previously occupied. It may be simpler to just redraw the entire background.
You simply have to keep track of every single object you want to draw and redraw every single one of them each frame.
You can optimize the process a bit, but you must keep track of each thing drawn so you can redraw.