Rotating image via javascript - javascript

I'm trying to rotate a image using javascript and it should be simple but I can't figure how to draw the image rotated at specific coordinate on the canvas.
Here's the code I found and am trying to use:
ctx.save();
// Translate to the center point of our image
ctx.translate(selectedImg.width * 0.5, selectedImg.height * 0.5);
// Perform the rotation
ctx.rotate( rotAngle * 0.01745 );
// Translate back to the top left of our image
ctx.translate(-selectedImg.width * 0.5, -selectedImg.height * 0.5);
// Finally we draw the image
ctx.drawImage(selectedImg, 0, 0);
// And restore the context ready for the next loop
ctx.restore();
it just rotates the image on top-left corner. how can I draw the image to let's say bottom-right?

As it is documented on MSDN.
The function drawImage has three signatures.
void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
Where d stands for destination and s stands for source.
The solution here should be calculating the image resolution and canvas resolution and make sure to feet the image inside the canvas, then calculate the x,y axes where we should to draw the image.
ctx.save();
// Translate to the center point of our image
ctx.translate(selectedImg.width * 0.5, selectedImg.height * 0.5);
// Perform the rotation
ctx.rotate(rotAngle * 0.01745);
// Translate back to the top left of our image
ctx.translate(-selectedImg.width * 0.5, -selectedImg.height * 0.5);
// Finally we calculate the destination and draw the image
var selectedImgWidth = selectedImg.width;
var selectedImgHeight = selectedImg.height;
var xOffset = selectedImgWidth < canvas.width ? (canvas.width - selectedImgWidth) : 0;
var yOffset = selectedImgHeight < canvas.height ? (canvas.height - selectedImgHeight) : 0;
ctx.drawImage(selectedImg, xOffset, yOffset);
// instead of ctx.drawImage(selectedImg, 0, 0);
// And restore the context ready for the next loop
ctx.restore();
I hope that resolve your issue.
Edit 1: Chenged destination target

This function works for me:
CanvasRenderingContext2D.prototype.drawImageRotated = function (img,x,y,angle)
{
this.save();
var cposX = x + img.width / 2;
var cposY = y + img.height / 2;
this.translate(cposX,cposY); // move canvas center
this.rotate(degToRad(angle));
this.translate(-cposX,-cposY);
this.drawImage(img, x, y);
this.restore();
}

Related

How to make object orbit from behind to front?

Is it possible to make an object orbit around another object that goes from behind and then to the front?
I've seen it being done with rotation animations that do a full 360 around the perimeter, but was wondering if it was possible to do it at an angle.
I couldn't find any resources that could do this, so I've included an image example of what I want to accomplish. The red line would be an object orbiting the blue circle.
Thanks so much - I really appreciate the help!
I figured I'd just write up a solution using the <canvas>
var x, y, scale, state, // Variables we'll use later.
canvas = document.getElementById("canvas"), // Get the canvas,
ctx = canvas.getContext("2d"), // And it's context.
counter = 0, // Counter to increment for the sin / cos functions.
width = 350, // Canvas width.
height = 200, // Canvas height.
centerX = width / 2, // X-axis center position.
centerY = height / 2, // Y-axis center position.
orbit = { // Settings for the orbiting planet:
width: 150, // Orbit width,
height: 50, // Orbit height,
size: 10 // Orbiting planet's size.
};
canvas.width = width; // Set the width and height of the canvas.
canvas.height = height;
function update(){
state = counter / 75; // Decrease the speed of the planet for a nice smooth animation.
x = centerX + Math.sin(state) * orbit.width; // Orbiting planet x position.
y = centerY + Math.cos(state) * orbit.height; // Orbiting planet y position.
scale = (Math.cos(state) + 2) * orbit.size; // Orbiting planet size.
ctx.clearRect(0, 0, width, height); // Clear the canvas
// If the orbiting planet is before the center one, draw the center one first.
(y > centerY) && drawPlanet();
drawPlanet("#f00", x, y, scale); // Draw the orbiting planet.
(y <= centerY) && drawPlanet();
counter++;
}
// Draw a planet. Without parameters, this will draw a black planet at the center.
function drawPlanet(color, x, y, size){
ctx.fillStyle = color || "#000";
ctx.beginPath();
ctx.arc(x || centerX,
y || centerY,
size || 50,
0,
Math.PI * 2);
ctx.fill();
}
// Execute `update` every 10 ms.
setInterval(update, 10);
<canvas id="canvas"></canvas>
If you want to change the roation direction of the orbiting planet, just replace:
x = centerX + Math.sin(state) * orbit.width;
y = centerY + Math.cos(state) * orbit.height;
With:
x = centerX + Math.cos(state) * orbit.width;
y = centerY + Math.sin(state) * orbit.height;
// ^ Those got switched.
The speed of the orbit can be changed by modifying the 75 in:
state = counter / 75;

Canvas - How to make line pass through a point

This is what I have right now:
I want to make it like this:
The blue line as you can see passes through the center(400,400). The start of the blue line is not fixed, it moves according to data that the user enter.
How do I add this blue line and make it pass through the center?
Sorry for my bad English, working on that :)
Halfon
Use mathematics.
Let the center co-ordinates be (Cx, Cy), which in your case are (400, 400). Let the user's co-ordinates be (Ux, Uy).
The equation of the line passing through the center from (Ux, Uy) would be given by the equation:
y - Cy = slope * (x - Cx), where slope = (Cy - Uy) / (Cx - Ux).
Now, to draw the line from Ux to some x co-ordinate, say Px, simply use the equation to calculate Py = Slope * (Px - Cx) + Cy, then draw the line from (Ux, Uy) to (Px, Py).
context.beginPath();
context.moveTo(Ux, Uy);
context.lineTo(Px, Py);
context.stroke();
Simply draw the line through the center point and extend its length. It's completely unclear what the length of the line is because you failed to provide any code, so I'm just doubling it in the example.
To calculate the end points, just subtract the starting x/y coordinates from the doubled x/y coordinates of the central point.
I wrote you a dynamic example which takes the mouse coordinates as a starting position, but the same principle applies if you only have a single static point from the user input. Try it here:
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
var centerPoint;
function setSize() {
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
centerPoint = {x: canvas.width / 2, y: canvas.height / 2};
}
canvas.addEventListener('mousemove', function(e) {
canvas.width = canvas.width;
context.beginPath();
context.moveTo(e.offsetX, e.offsetY);
context.lineTo(centerPoint.x * 2 - e.offsetX, centerPoint.y * 2 - e.offsetY);
context.lineWidth = 3;
context.strokeStyle = '#0000ff';
context.stroke();
})
canvas.addEventListener('mousedown', function(e) {
centerPoint = {x: e.offsetX, y: e.offsetY};
canvas.width = canvas.width;
})
window.addEventListener('resize', setSize);
setSize()
canvas {width: 100%;height: 100%;position: absolute;}
body {margin: 0}
p {position: absolute; pointer-events: none}
<canvas id="c"></canvas>
<p>Click anywhere to set the center point (dead center by default)</p>

Canvas - Rotating my images(circles)

I currently have a bunch of circles that i fill with a image inside a "box", they are bouncing and colliding. Now I want them to rotate.
I have tried to get this to work but I only seem to be able to rotate the entire canvas, I only want the balls to rotate.
This is my render-function:
var img = new Image;
img.onload = function() {
render();
console.log("asdsad");
}
img.src = "xxx.png";
function render() {
var ball;
for (var i = 0; i <balls.length; i++) {
ball = balls[i];
ball.x = ball.nextx;
ball.y = ball.nexty;
context.drawImage(img, ball.x - (img.width/2), ball.y - (img.height/2));
}
}
GOAL: Get these balls to rotate.
EDIT: I have tried something like this, obviously I'm doing something wrong.
context.rotate(Math.PI/180); // Should this be another value? Either way, entire canvas rotates.
context.drawImage(img, ball.x - (img.width/2), ball.y - (img.height/2));
//context.rotate(-Math.PI/180)
context.restore();
You are almost there with your code. You are only forgetting the actual angle:
If you want something easy to wrap the head around and use angles in degrees you can do:
context.rotate(angle * Math.PI / 180);
a trick here is to pre-calculate Math.PI / 180 and use that to calculate:
var deg2rad = Math.PI / 180;
...
context.rotate(angle * deg2rad);
Then draw the balls.
You probably already know but just in case (as it isn't in the example you provided) - To use restore you must first use save:
context.save();
context.rotate(angle * Math.PI / 180);
context.drawImage(img, ball.x - (img.width * 0.5), ball.y - (img.height * 0.5));
context.restore();
Update:
I made an example with a single ball. Just apply the principle for many.
ONLINE DEMO HERE
The main loop goes like this:
/// pre-setup done (see demo)
function loop() {
/// change direction if at some edge
if (x < r || x > ez.width - r) {
dx = -dx;
angleDelta = -angleDelta; /// dummy bounce
}
if (y < r || y > ez.height - r) {
dy = -dy;
}
/// clear previous ball
ctx.clearRect(x - r - 2, y - r - 2, img.width + 4, img.height + 4);
/// move and rotate
x += dx;
y += dy;
angle += angleDelta;
/// save context
ctx.save();
/// move to ball's center position
ctx.translate(x, y);
/// rotate at balls center position
ctx.rotate(angle);
/// draw ball offset so center is center of image
ctx.drawImage(img, -r, -r);
/// reset translation and rotation
ctx.restore();
///again
requestAnimationFrame(loop);
}
You said you have tried:
context.rotate(Math.PI/180);
As known in mathematics PI = 180 degree and if you do PI / 180 = 1 degree it will do nothing except a little.
So if you want to rotate the canvas 90 degree you have to write:
context.rotate(Math.PI/2);
if you want 180 degree you have to:
context.rotate(Math.PI);
and carry on.
with some calculation you will be able to rotate it to any degree you want.
if this does not work you can try this alternative
this function take the arguments and buld the image for you in a simple way that you can understand it might help someone out their.
this function help you
function drawImg(img, pX, pY, oX, oY, w, h, rot , context2D) {
context2D.save();
context2D.translate(pX+oX, pY+oY);
context2D.rotate(rot * Math.PI / 180);
context2D.drawImage(img, 0, 0, w, h, -(oX), -(oY), w, h);
context2D.restore();
}
Summary:
img: the image object
pX: the x position of the image
pY: the y position of the image
oX: how far across the image that the origin is
oY: how far down the image that the origin is
w: width of the image
h: height of the image
rot: angle of rotation
context2D: the context that have been build from the canvas

How to add a drawing function to KineticJS Image

I am trying to create a function in Kinetic JS Image to redraw the image. I am trying to create a warp / curve effect and I need to redraw the image.
My approach is slicing the image and moving each slice of the image on the Y coordinate based on the equation of a circle.
I cannot get the context of the image to redraw it. This is what I got:
warp: function(wx, wy){
var width = this.getWidth(),
height = this.getHeight(),
context = this.getContext(),
image = this.getImage();
for(var n=0; n < width; n++){
var sx = n,
sy = 0,
sWidth = 1,
sHeight = height,
dx = 1,
dy = 200 * Math.cos(n * 2 * Math.PI / width);
console.log(dy);
context.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, width, height);
}
}
Please give me any suggestions you may have on how to achieve the redraw.
Thanks!

HTML Canvas: How to draw a flipped/mirrored image?

I'm trying to flip/mirror an image as I paint it on an HTML canvas; I found a game tutorial showing a sprite sheet per direction a character has to face, but this doesn't seem quite right to me. Especially since each frame has a different size.
What would be the best technique to reach this goal?
I tried to call the setScale(-1, 1); on my canvas with no success. Maybe that isn't meant for this.
Thanks
You can do this by transforming the context with myContext.scale(-1,1) before drawing your image, however
This is going to slow down your game. It's a better idea to have a separate, reversed sprite.
You need to set the scale of the canvas as well as inverting the width.
drawToCanvas : function(v, context, width, height){
context.save();
context.scale(-1, 1);
context.drawImage(v, 0, 0, width*-1, height);
context.restore();
}
There are probably some performance issues with this but for me that was not an issue.
If you just flip it horizontally it will get off of bounds... so use translate to adjust its position:
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
ctx.drawImage(img, 0, 0);
For a shorter code you can remove the translate and use the image size as negative offset in the second parameter of the drawImage (x coordinate) instead:
ctx.scale(-1, 1);
ctx.drawImage(img, canvas.width * -1, 0);
If you want to restore the context later, add save/restore before and after it all:
ctx.save();
ctx.scale(-1, 1);
ctx.drawImage(img, canvas.width * -1, 0);
ctx.restore();
You don't need to redraw the entire image when creating a reflection. An original reflection simply shows the bottom part of the image. This way you are redrawing a smaller part of the image which provides better performance and also you don't need to create linear gradient to hide the lower part of the image (since you never draw it).
var img = new Image();
img.src = "//vignette2.wikia.nocookie.net/tomandjerryfan/images/9/99/Jerry_Mouse.jpg/revision/latest?cb=20110522075610";
img.onload = function() {
var thumbWidth = 250;
var REFLECTION_HEIGHT = 50;
var c = document.getElementById("output");
var ctx = c.getContext("2d");
var x = 1;
var y = 1;
//draw the original image
ctx.drawImage(img, x, y, thumbWidth, thumbWidth);
ctx.save();
//translate to a point from where we want to redraw the new image
ctx.translate(0, y + thumbWidth + REFLECTION_HEIGHT + 10);
ctx.scale(1, -1);
ctx.globalAlpha = 0.25;
//redraw only bottom part of the image
//g.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
ctx.drawImage(img, 0, img.height - REFLECTION_HEIGHT, img.width, REFLECTION_HEIGHT, x, y, thumbWidth, REFLECTION_HEIGHT);
// Revert transform and scale
ctx.restore();
};
body {
background-color: #FFF;
text-align: center;
padding-top: 10px;
}
<canvas id="output" width="500" height="500"></canvas>

Categories