I'm using Velocity.js for animation.
What's the proper way to move an SVG image, while rotating it around the center at the same time?
You do not need to do per frame animation if you can define the motion using combination of rotations and linear movements.
As it comes out, your issue is that you are not able to fully manage the origin of rotation.
NOTE : The following is applicable to not only velocity but all css transformations in general.
The origin of rotation is the top-left corner of the item to be rotated
Now, if you want to move the object without moving the origin, you can use the translateX, translateY properties. eg
.velocity({ translateX: "+=200", translateY: "25%"})
In order to move the object as well as the origin, you need to set or move its x and y position parameters. eg
.velocity({ x: "+=200", y: "25%" })
Rotation around center
As an example, if you want to rotate an object on its center,you need to
Translate the object by -w/2 and -h/2 where the width and height is w and h.
Rotate the object
Rotation around an external point
In case where you need to rotate the object around an item, simply first translate the object away from its origin by a suitable distance and then rotate it.
This PEN shows both examples where the green rectangle is rotated around its center and the blue one around an external point by combining translation and position correctly.
Velocity.js uses CSS transforms to do it's rotation. Because of this, all you actually need to do is set transform-origin: center; in your CSS. This changes the point around which all actions will happen.
Trying to match the rotational movement and shifting your X and Y accordingly will be a slower animation and more prone to bugs.
More information about transform-origin can be found here.
Related
I've already asked this same question months ago, but no one was able to answer me, even after making a fully functional example on Plunker, then, I am going to ask it again, and yes, I still have the same problem.
My problem: find the centre of an element who have some rotation in it, after resizing it, to use it as the new pivot of rotation.
In my practical example, it is possible to see the problem in action; I have created two circles to show the problem better. After rotating and resizing the element, it's possible to see how the red and blue circles are apart from each other.
Blue Circle: the "correct" position of the centre, achieved by setting the cx/cy coordinates as the calculated element centre, plus, applying the transform rotate in it. The transform translates the circle to the correct position.
Red Circle: same as the blue circle, minus the transform rotate, these values are the ones used as the rotation pivot for the transform rotate().
My assumptions until here: By applying the transform rotate() in the blue circle, I'm considering the rotation angle in the calculated centre, so all I have to do is replicate the matrix calculations made by the rotate() function. I'm already doing this with the four handles that the user can click to make a rotation, what could go wrong?
My goal: Resize an element with rotation keeping the pivot of rotation in the centre.
I think this answer gave me some info, the math here helped me with the rotation handles starting position, but still, I can't find the right way to calculate the new centre after the resize.
The example was made using D3js + AngularJS v1. I work actively with both, but I am new to the geometry math world.
Again, this is the project on Plunker.
To get the centre of the transformed and rotated element, the most accurate way would probably be to get the browser to calculate it for you.
First create an SVGPoint object to hold our original centre point.
var centre = svg.createSVGPoint();
Initialize this point with the centre of the original object. You can get that by calling getBBox() on the element, and performing a smiple calculation.
var bbox = obj.getBBox();
centre.x = bbox.x + bbox.width / 2;
centre.y = bbox.y + bbox.height / 2;
Next, get the transform matrix from the transform attribute of the transformed object
var matrix = transformedObj.transform.baseVal.consolidate().matrix
Now we can transform our SVGPoint object with this matrix.
var transformedCentre = centre.matrixTransform(matrix);
After this, the x and y properties of transformedCentre should be your transformed centre point.
This should work, but I haven't tested it.
How does one get and set the following values using Javascript in Adobe Photoshop CS6+:
Canvas Rotation
Canvas Zoom (https://forums.adobe.com/thread/1016213)
Horizontal Window Offset (Panning)
Vertical Window Offset (Panning)
I see that there is an app.activeDocument.rotateCanvas() function, but beyond that...
I'm not entirely sure what you mean by offset.
As for rotation. It's quite simple. The amount of rotation desired is measured in degrees & is placed between the brackets. So if you wanted to rotate counter clockwise that would be -90.
e.g.
app.activeDocument.rotateCanvas(-90.0);
I am working on a page where I can view images. I want to create a rotation tool. I've done that, but, it's not working consistently. When I set up the centre point to rotate by, the image jumps slightly, and it gets worse each time. I was experimenting, and, I have code to add a wedge to the top left corner of my top level group ( so, at 0,0 ). If I rotate the image by 45 degrees and drag it so that half of it is off the left edge of my canvas, then I call getAbsolutePosition on the wedge and on the group, I get these values:
layer.getAbsolutePosition()
Object {x: 104.66479545850302, y: 279.2748571151325}
wedge.getAbsolutePosition()
Object {x: 180.2684127179338, y: -73.48773356791764}
I think this means my y position is actually the bottom of the image, which is off screen.
What I want to do, is calculate the absolute position of the middle of my image, when the mouse moves over it, regardless of it's rotation. I have some code that works out points with rotation, which seems like it works at first, almost, but it just gets more and more broken the more I use the tool. I feel like there's something about how Kinetic is tracking these things and what it's reporting, that I am missing. Any hints would be most appreciated. Tutorials I can read are even better ( yes, I've read everything linked from the KineticJS site and searched the web ).
In a nutshell, the question is, if I have an image inside a group, and it's rotated, how do I work out the centre point of the image, taking the rotation in to account, and how do I set the offset so it will rotate from that point, and stay in the same place ?
Thanks
As you've discovered about KinetiJS:
rotation is easy
dragging is easy
dragging+rotation is difficult
After you drag your image you must reset its rotation point (offsetX/offsetY).
KineticJS makes dragging+rotation more difficult than it has to be.
Resetting the offset points of your image will cause KineticJS to automatically move your image (Noooo!!).
That's what's causing your jumping.
The solution to the "jumping" problem:
When you reset the image's rotation point (offsetX/OffsetY) you must also reset the image's X/Y position.
This code resets both XY and Offsets for an image after dragging:
A Demo: http://jsfiddle.net/m1erickson/m9Nw7/
// calc new position and offset
var pos=rect.getPosition();
var size=rect.getSize();
var offset=rect.getOffset();
var newX=pos.x-offset.x+size.width/2;
var newY=pos.y-offset.y+size.height/2;
// reset both position and offset
rect.setPosition([newX,newY]);
rect.setOffset(size.width/2,size.height/2);
I have a large circle with smaller ones inside made using two.js.
My problem is that these two do not rotate in their own place but in the top left axis.
I want the group of circles (circlesGroup) rotate only inside the large one in a static position. The circlesGroup and the large circle are grouped together as rotatoGroup.
two.bind('update', function(frameCount, timeDelta) {
circlesGroup.rotation = frameCount / 120;
});
two.bind('update', function(frameCount, timeDelta) {
rotatoGroup.rotation = frameCount / 60;
});
The whole code is in CodePen.
All visible shapes when invoked with two.make... ( circles, rectangles, polygons, and lines ) are oriented in the center like this Adobe Illustrator example:
When this shape's translation, rotation, or scale change those changes will be reflected as transformations about the center of the shape.
Two.Groups however do not behave this way. Think of them as display-less rectangles. They're origin, i.e group.translation vector, always begins at (0, 0). In your case you can deal with this by normalizing the translation your defining on all your circles.
Example 1: Predefined in normalized space
In this codepen example we're defining the position of all the circles around -100, 100, effectively half the radius in both positive-and-negative x-and-y directions. Once we've defined the circles within these constraints we can move the whole group with group.translation.set to place it in the center of the screen. Now when the circles rotate they are perceived as rotating around themselves.
Example 2: Normalizing after the fact
In this codepen example we're working with what we already have. A Two.Group that contains all of our shapes ( the bigger circle as well as the array of the smaller circles ). By using the method group.center(); ( line 31 ) we can normalize the children of the group to be around (0, 0). We can then change the translation of the group in order to be in the desired position.
N.B: This example is a bit complicated because it invokes underscore's defer method which forces the centering of the group after all the changes have been registered. I'm in the process of fixing this.
I have a rounded rectangle at a specific x, y, w, h on a canvas. I first do a context.translate to get the object where I want it, then when it comes to rotating it, this is where I'm having issues working out the math needed.
I can do a simple context.rotate(Math.PI/180 * 25) to rotate it 25degs but it rotates from the x,y. I really want to shift the rotating point to like x + (w/2) and y + (w/2).
I'm not sure how to tell the rotate method to rotate it around a different point. I think I have to rotate it like normal but recalculate x,y perhaps based on the rotation maybe?
The canvas always rotates about the origin (0,0). The ctx.translate command can be thought of as shifting the origin, so you must translate by (x+w/2, y+h/2) before you rotate if you wish to rotate about the center of the rectangle.
(and of course, translate back after, or use save and restore)