I'm trying to make the so called fine tune thing. Basically this looks like: http://jsfiddle.net/r9KQK/1/
Later I'll have some audio player and this thing will help to select seconds when we use it on a tablet.
The problem is when you try to move the red circle it strangely drops when it passes top and bottom of the green circle, but not at 0 or PI/2, something like at -260..-269 and 181..190 degrees
Just try to move it and you'll see the bug.
What's wrong in my code?
Thanks in advance
update
Last update: http://jsfiddle.net/r9KQK/17/
In this example I get degrees in 0..360 range. But instead I should get delta degrees between the point where I start dragging and where I end it, but I can't work out the maths. I should also take into account the direction of red circle, so that delta will be + or - =\
update
Finally: http://jsfiddle.net/r9KQK/18/
But the code is really awful. Though it's 2:46 AM and I'm kind of sleepy, so...
But anyway I think it could be much more simplified
That's happening because your parameter to Math.atan goes to infinity when DeltaX is zero. I recommend using atan2, which automatically handles this corner case:
function(dx, dy, x, y)
{
var deltaY = this.oy + dy - fineTuning.ring.attr('cy');
var deltaX = this.ox + dx - fineTuning.ring.attr('cx');
var angle = Math.atan2( deltaY, deltaX );
// etcetera, etcetera
Or check the fiddle.
Related
I'm trying to scale and then rotate a triangle and then translate it to a given point in Snap SVG.
I want to rotate the triangle around the top of it not the center, so i can build something like a pie.
So I thought I scale first, then rotate and later translate.
var t = new Snap.Matrix();
t.scale(0.5);
t.rotate(45, bbox.cx, (bbox.cy-(bbox.h/2)));
But the scale and rotation somehow are allways a bit off.
I reused a jsfiddle I found and updated it, so you can see what I try:
http://jsfiddle.net/AGq9X/477/
Somehow the bbox.cx and bbox.cy are not in the center of the triangle.
On my local setup they are.
The strange thing is, just rotation without scaleing works fine,
but scaling and then roation always seems to be a bit off on the y axis, the triangle doesn't stays at the rotation point.
Any ideas how i can fix that?
EDIT:
Ok I found the Solution,thanks to lan, you were right, the center of scaleing is important, and
I thought it was useing the center of the object, but it was the upper left corner. I adjusted it
and now it works greate:
var bbox = obj.getBBox(); //get coords etc. of triangle object
var t = new Snap.Matrix();
var offset = (bbox.cy+(bbox.h)) - centerY; //translate Y to center,
//depends on scaleing factor (0.5 = bbox.h, 0.25 = bbox.h*2)
t.scale(0.5, 0.5, bbox.cx, (bbox.cy+(bbox.h/2))); //scale object
t.translate(0,-offset); //translate to center
t.rotate(45, bbox.cx, (bbox.cy+(bbox.h/2))); //rotate object
obj.transform(t); //apply transformation to object
EDIT2:
I wanted to know how to save transformation, so you don't need to apply them every time you use a new transformation. Ian recommended to use element.transform() like so to get the old transformations:
element.transform( element.transform() + 's2,2' )
This is slightly more complicated than one would expect, but you would be animating a matrix, which does some odd things sometimes.
Personally I would use Snaps alternate animate method Snap.animate() and not using a matrix. Set the scale first and then build your animation string.
Something like..
var triangle2 = p.select("#myShape2").transform('s0.5');
...
Snap.animate(0,90,function( val ) {
triangle2.transform('r'+ val + ',' + bbox.cx+','+(bbox.cy-(bbox.h/2))+'s0.5')
}, 2000)
jsfiddle
I'm trying to use brownian motion to create a group of random moving particles.
http://jsfiddle.net/J75Em/16/
So far I've got the particles moving randomly but I'm not sure how to set the forward direction to make it look more natural.
I've tried to use the change in x and y axis to calculate rotation using atan, you can see this by uncommenting rotate but this doesn't seem to perform well.
Is this the right approach for this type of movement? thanks;
This is pretty neat!
You are sort of going about it the right way but you should actually use the atan2 function. This removes the need for any 0 checks.
The atan2 function gives you an angle which is anticlockwise from the positive x vector
(1, 0) --->
The bees are 90 degrees off from this starting angle so you must subtract 90 degrees from the direction. (depending on which way round you do the dy and dx calculation, you might need to add)
You could find that the direction changes rapidly, so you could consider limiting the next change to a set of changes that cause an angle change below some threshold. This will make the movement a little smoother.
I would actually go about it by generating an angle between say -pi/8 and pi/8 radians, and a random length. Essentially using polar coordinates. Then add this new random polar offset to the x and y position like
newX = currentX + (randomLength * cos(randomAngle + currentAngle)) and
newY = currentY + (randomLength * sin(randomAngle + currentAngle))
If you work with angles you can also get more natural effects like if you want the bees to stay within a certain area, you can force a bias towards the center of the area as they get closer and closer to the edge.
Update:
So I've taken a closer look. The trouble is that you expect .rotate to set the rotation when it actually adds to the rotation
There are 2 options for fixing this.
Rotate by the difference between the previous and the current angle
Set the rotation using the .transform method
You can see solution 2 in action here http://jsfiddle.net/c5A2A/
I need to rotate objects in a smooth way like Elbert F's freeTransform does.
Please anyone review my code and help me to solve this problem.
I don't need any other code or any other plugin but some editing in my own code
I think some correct formula of angle in move function of code is responsible for smooth rotation of object.
Thanks in advance
I have done this and its a bit tricky formula of Math which helped me.
Here is updated code
var centreX = "center of rectanlge, x-coordinate", centreY = "center of rectangle, y-coordinate";
var theta = Math.atan2(centreX - dx, centreY - dy); // dx and dy are movement of mouse from the rotating element
angle = 1 * (theta * 180)/3.1415;;
element.rotate(angle, centreX, centreY);
I have a need to rotate an image in a web application. In an earlier post it was explained to me that on rotation I need to 'translate' the image because the center point changes.
I'm using the HeyGrady 2D transfrom JQuery plugin for rotating and provide it the translation as was suggested, which works fine on FF/Chrome/Safari/IE9. However, on IE8 this does not work well.
Please have a look at the following link.
If you run this on FF/Chrome/Safari/IE9 the image rotates just fine (stays within the black border). However, if you run this on IE8 it will cross the black border boundary when rotating to 90 or 270 degrees.
The plugin project page mentions that "IE also lacks support for transform-origin and translate() [...] The jQuery Transform plug-in handles these calculations automatically". However, it does not seem to do so.
Anyone has any ideas what the problem may be?
Thanks!
I also ran into this same issue in IE 8 using HeyGrady's jQuery transform plugin. Here's a fix by adding this to the execMatrix function, around line 290:
Replace this line:
this.fixPosition(matrix, tx, ty);
With this:
// factor in the object's current rotation so translation remains straight up/down/left/right
// otherwise, object will be translated along the rotated axis, which produces undesirable effects
var rotation = parseInt(this.$elem.css('rotate')) * -1, // the current rotation in degrees, inverted
radians = rotation * (Math.PI / 180), // convert degrees to radians
newX = (tx * (Math.cos(radians))) - (ty * (Math.sin(radians))), // calculate new x
newY = (tx * (Math.sin(radians))) + (ty * (Math.cos(radians))); // calculate new y
this.fixPosition(matrix, newX, newY);
For example it may be used in the application of manually adjusting the hands of the clock. I guess it probably involves translating the needle (to make the end point of the needle the centre of rotation) then rotating it, then translating the needle again.
But since the needle listens to the mouse event all the time, the 1st mouse event will be captured. The result is that the needle ends up being translated and not rotated at all. Mouse event is impossible to debug too...
Any idea or code snippets that I can refer to? Using Javascript or CSS to rotate both fine.
In your example, you will want to calculate the angle between the centre of the clock face (black dot), and the current mouse position (red dot), relative to the Y axis (cardinal north if you imagine a compass).
If I remember my trig correctly, you can calculate this by using the following:
var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
// alter the angle to be relative to Y axis instead of X
angle += 90;
if(angle < 0) { angle = 360 + angle; }
In the formula, x and y are the coordinates of the two points, one of which you will know (it is the centre of the clock face), and the other you can get from the mouse move event.
Once you have the angle, you can simply translate to the the centre of the circle, rotate the canvas by the calculated amount, and draw the hand.
Update: I created a jsfiddle to illustrate the angle calculation:
http://jsfiddle.net/DAEpy/1/