konvajs / konva

Konva.js is an HTML5 Canvas JavaScript framework that extends the 2d context by enabling canvas interactivity for desktop and mobile applications.
http://konvajs.org/
Other
11.37k stars 916 forks source link

Rotation Origin #26

Closed BlackScorp closed 9 years ago

BlackScorp commented 9 years ago

Hello guys,

is there any way to define a rotation origin? right now i can setup an offset and when i call rotate method my image is rotated around the offset. the Problem is that the offset also changes the x/y positions.

http://onlinetowerdefense.github.io/Client/ the towers and units are not on their original positions and i could not figure out where i can setup a rotation origin.

hope you can help me,

cheers

confile commented 9 years ago

Use offsetX and offsetY

BlackScorp commented 9 years ago

@confile i did, as i told, offset changes also the x/y position of the node

lavrton commented 9 years ago

@confile is right. You have to use offset. Then change {x,y} to what you need. Like this

// let's go rotate image relative to it's center!
// we need to set offset to define new "center" of image
image.offsetX(image.width() / 2);
image.offsetY(image.height() / 2);
// when we are setting {x,y} properties we are setting position of top left corner of image.
// but after applying offset when we are setting {x,y}
// properties we are setting position of central point of image.
// so we also need to move the image to see previous result
image.x(image.x() + image.width() / 2);
image.y(image.y() + image.height() / 2);

image.rotation(90);
BlackScorp commented 9 years ago

@lavrton thx going to try this afternoon

For-me commented 8 years ago

@lavrton @confile Hi,thx to answer this quesition.But if i want to repeat rotation more time. how can i set the rotation origin?

lavrton commented 8 years ago

@For-me what do you mean by "repeat rotation more time"? Rotate is much as you want.

For-me commented 8 years ago

@lavrton For example,I want to make a image to rotate 360deg,Only once every 90 deg of rotation.How to confirm every rotation center.

For-me commented 8 years ago

@lavrton I fix it .thx

diegolato commented 7 years ago

@For-me How did you fix it? I have the same problem. I want to rotate an object more time by clicking on it. Can you show the code?

abdullah1971 commented 6 years ago

To rotate an image for multiple times after setting the origin, please run this piece of code for once, not every time you want to rotate.

" image.x(image.x() + image.width() / 2); image.y(image.y() + image.height() / 2);

"

I solved my problem by this way.

waifutech commented 5 years ago

Code rotates node around center without messing with offsets.

const degToRad = Math.PI / 180

const rotatePoint = ({x, y}, deg) => {
    const rcos = Math.cos(deg * degToRad), rsin = Math.sin(deg * degToRad)
    return {x: x*rcos - y*rsin, y: y*rcos + x*rsin}
}

//current rotation origin (0, 0) relative to desired origin - center (node.width()/2, node.height()/2)
const topLeft = {x:-node.width()/2, y:-node.height()/2}
const current = rotatePoint(topLeft, node.rotation())
const rotated = rotatePoint(topLeft, rotation)
const dx = rotated.x - current.x, dy = rotated.y - current.y

node.rotation(rotation)
node.x(node.x() + dx)
node.y(node.y() + dy)
adam-t-b commented 5 years ago

Code rotates node around center without messing with offsets.

const degToRad = Math.PI / 180

const rotatePoint = ({x, y}, deg) => {
    const rcos = Math.cos(deg * degToRad), rsin = Math.sin(deg * degToRad)
    return {x: x*rcos - y*rsin, y: y*rcos + x*rsin}
}

//current rotation origin (0, 0) relative to desired origin - center (node.width()/2, node.height()/2)
const topLeft = {x:-node.width()/2, y:-node.height()/2}
const current = rotatePoint(topLeft, node.rotation())
const rotated = rotatePoint(topLeft, rotation)
const dx = rotated.x - current.x, dy = rotated.y - current.y

node.rotation(rotation)
node.x(node.x() + dx)
node.y(node.y() + dy)

This is exactly what I was looking for. I noticed that the Transformer would always rotate around the center of the node without setting offsets, and it was driving me nuts trying to figure out how to do it better.

JoachimDorchies commented 4 years ago

Code rotates node around center without messing with offsets.

const degToRad = Math.PI / 180

const rotatePoint = ({x, y}, deg) => {
    const rcos = Math.cos(deg * degToRad), rsin = Math.sin(deg * degToRad)
    return {x: x*rcos - y*rsin, y: y*rcos + x*rsin}
}

//current rotation origin (0, 0) relative to desired origin - center (node.width()/2, node.height()/2)
const displayedWidth = image.width() * image.scaleX();
const displayedHeight = image.height() * image.scaleY();
const topLeft = {x:-displayWidth/2, y:-displayedHeight/2}
const current = rotatePoint(topLeft, node.rotation())
const rotated = rotatePoint(topLeft, rotation)
const dx = rotated.x - current.x, dy = rotated.y - current.y

node.rotation(rotation)
node.x(node.x() + dx)
node.y(node.y() + dy)

Added a multiplication by scale so that it's the displayed width and not the original one. If you use a transformer and rescale, not taking scale into account will result in undesired behaviour.

Dhwanil-Shah commented 2 years ago

Code rotates node around center without messing with offsets.

const degToRad = Math.PI / 180

const rotatePoint = ({x, y}, deg) => {
    const rcos = Math.cos(deg * degToRad), rsin = Math.sin(deg * degToRad)
    return {x: x*rcos - y*rsin, y: y*rcos + x*rsin}
}

//current rotation origin (0, 0) relative to desired origin - center (node.width()/2, node.height()/2)
const topLeft = {x:-node.width()/2, y:-node.height()/2}
const current = rotatePoint(topLeft, node.rotation())
const rotated = rotatePoint(topLeft, rotation)
const dx = rotated.x - current.x, dy = rotated.y - current.y

node.rotation(rotation)
node.x(node.x() + dx)
node.y(node.y() + dy)

@waifutech Can you explain the Math behind this calculation, really appreciate it! Thanks in advance! 😄