I would like to know the best way to animate an element in a circular motion around a central point?
I couldn't quite figure it out... :(
Thanks in advance.
Neuroflux.
Use the jquery.path plugin, and here is a demo.
(found it from another question: How would you animate something so that it follows a curve?)
easiest i can think of is:
make the central point position relative
make the animated element to be child of above
calculate the top, left using:
math.sin(time * (angle /second)) * distance
math.cos(....)
simple demo:
var elem = $('h1:eq(0)')
.append('<span id="round" style="position:absolute;background-color:red;"> </span>')
.css('position','relative')
.find('span#round');
var i = 0;
setInterval(function(){
++i;
elem.css({'left': Math.sin(i * 0.02) * 100, 'top': Math.cos(i * 0.02) * 100});}, 100);
See it in action at jsfiddle.
Related
I want to to add custom control(div) to Fabric js object something like this:
I found this question but it has bug on rotation please see jsfiddle
I'm trying to find solution already few days, any suggestions are welcomed.
http://jsfiddle.net/86bTc/94/
var btnLeft = ((e.target.width / 2) -10 )* cos(angle) + ((e.target.height / 2) +25) * sin(angle);
var btnTop = -((e.target.height / 2) +25 )* cos(angle) + ((e.target.width / 2) -10 ) * sin(angle);
You have to add the rotation effect to LEFT and TOP of your absolute positioned element.
I changed the positioned element with a small div, so you do not get tricked by the baseline of text that makes the 'p' element look in wrong position.
Might be that solution is good for you? Fabric js custom controls
I have a somewhat simple script I'm trying to get working where an image will rotate to point at your cursor, and then move the image to follow the mouse once the cursor has stopped. The problem I'm having is that the rotate function which I have borrowed from another solution will not update the location of the image. Once the image moves across the screen, it still compares the original location of the image to the mouse location when calculating the rotation.
Here's my rotate function:
function rotate(){
var offset = img.offset();
function mouse(evt) {
var center_x = (offset.left);//(img.width() / 2);
var center_y = (offset.top);//(img.height() / 2);
var mouse_x = evt.pageX;
var mouse_y = evt.pageY;
var radians = Math.atan2(mouse_x - center_x, mouse_y - center_y);
var degree = (radians * (180 / Math.PI) * -1) + -90;
img.css('-moz-transform', 'rotate(' + degree + 'deg)');
img.css('-moz-transform-origin', '0% 11%');
img.css('-webkit-transform', 'rotate(' + degree + 'deg)');
img.css('-webkit-transform-origin', '0% 13%');
img.css('-o-transform', 'rotate(' + degree + 'deg)');
img.css('-o-transform-origin', '0% 11%');
img.css('-ms-transform', 'rotate(' + degree + 'deg)');
}
$(document).mousemove(mouse);
}
I also have the entire project on jsfiddle here: http://jsfiddle.net/joshbox/t8kfyxec/3/
The problem is that you are calculating the angle of your image based on the position it has on load of the page, and not the current position (that may be different after it has moved).
This should be easily fixed by fetching the actual position each time you calculate the rotation angle. All you need to do is move var offset = img.offset(); inside your mouse() function and it should work fine.
While you are at it, I noticed you are setting the transform origin of your image along with the angle, while the origin actually remains fixed. May I suggest you move that to your css in stead.
I went ahead and updated your fiddle with my suggestion, along with some minor readability updates: http://jsfiddle.net/t8kfyxec/6/
A few notes on the changes I made:
It should be clearTimeout, not clearInterval
always include the w3c standard versions (as last option), not just the ones with the browser prefixes.
I removed the inner move function, as I could not see a good reason for it.
All events are now bound inside a single event handler, and the functions that get triggered only receive the data they require, not the entire event (which makes it easier to test, debug and reuse your code)
I hope this all makes sense. Feel free to ask if you want me to explain further.
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.
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 sprite animation, a small cannon rendered using a 3D app. I have exactly 360 frames for a 360 degree turn. Each image has a 100x100 pixel size.
So basically what I am trying todo is when I click anywhere in the page, the barrel of the cannon needs to rotate to point at the mouse cursor, sound simple maybe but I can't really get it to work very well, perhaps cause my math skills is lacking :P
What I currently have is something like this
/* This is my div with the cannon background image (360 images stitched into one) each "image area" is 100x100px */
obj.cannon = $('#cannon');
/* Get the X/Y of the cannon loc in the dom */
var cannonX = $(obj.cannon).offset().left;
var cannonY = $(obj.cannon).offset().top;
/* Get radians using atan2 */
var radians = Math.atan2(e.pageY-cannonY, e.pageX-cannonX);
/* Convert to degrees */
var degrees = radians * (180/Math.PI);
And this is where I am, I mean since the image width is 100px and I need to move the background-position by 100px to move the cannon one degree right, because 360 images * 100px = 36000px in total. So the stitched sprite is like 36000px wide.
So
Insert weird calculation here based on the current backgroundPosition of the image-sprite and apply new backgroundPosition based on where you click with the mouse cursor, then use some sort of setTimeout(animateIt, speed); to "animate" the background position to the new position.
function animateIt(){
if(newpos!=targetpos) { //Use < > here if we need to add or remove
newpos+=100; //Until we arrive at the new backgroundPosition
$(obj.cannon).css({backgroundPosition: newpos+'px' });
setTimeout(animateIt, speed);
}
}
Am I at all on the right track here, am I thinking correctly about this? I feel stupid, this should be a simple thing but right now I am having a brain meltdown I think =P. My problem is I don't know how to properly arrive at the "new target backgroundposition" and then animate it ++ or -- based on the current background position :/
Well, here is a simplified working example with 10 images.
I'll post the code and jsFiddle now, and I might come back later to cover it in depth. But basically you just order your images correctly, and then you pick the segment by using (Segments - Math.floor(degree / (360 / segments))). You may have to adjust your 0 degree. For example, I made my 0 equal to what would normal by 90.
Pay attention to the fact that the screen coordinates, x and y, increase right and down. This makes the degrees of atan work clockwise instead of the usual counter clockwise in coordinate systems where x and y increase right and up.
I added in some text output that shows the degrees and image segment being shown.
jQuery handles normalizing the x and y position nicely. Just take care that your CSS setup is cross browser.
Working jsFiddle example
Here's our image:
Here's our HTML:
<div id="main"><div id="img"></div></div>
<div id="info">
<span></span><br/>
<span></span>
</div>
CSS:
div#main {
width:500px;
height:500px;
border:2px #000 solid; }
div#img {
width:94px;
height:119px;
overflow:hidden;
top:50%;
left:50%;
margin-left:-45px;
margin-top:-60px;
position:relative;
background-image:url('http://imgur.com/3UPki.png');
background-position:0;}
div#info {
position: absolute;
bottom:0;
left:0; }
Javascript / jQuery:
$(function() {
var position = $("div#img").position(),
mouseX, mouseY, imgX, imgY, degree;
imgX = position.left;
imgY = position.top;
$("#main").mousemove(function(e) {
// degree is arctan y over x (soh,cah,toa)
degree = Math.atan2((e.pageY - imgY),(e.pageX - imgX))*(180 / Math.PI);
degree = (degree - 90) % 360;
// jQuery normalizes pageX and pageY
// transfrom from -180 to 180 ==> 0 to 360
if (degree < 0) degree = 180 + (180 - (Math.abs(degree)));
rotate(degree);
$("span:first").html("Segment: " + (9 - Math.floor(degree / 36)));
$("span:last").html("Degree: " + Math.floor(degree));
});
function rotate(degree) {
var off = 9 - Math.floor(degree / 36);
$("div#img").css("background-position",-off*94);
}
});
Working jsFiddle example
Keep in mind that the degrees you get from atan will start pointing right for zero degrees and go clockwise from there (-90 is up, 90 is down).
Each position of your image should correspond to a specific angle. Once you have the degrees measured (it looks like you have that part right), use some type of mapping to translate your degrees to the proper image offset. I don't know what your image looks like so I can't help with that. Assuming your image starts pointing right, and goes around clockwise from there, the degrees will correspond directly the the offset for the right image. (I suggest you arrange your frames like this for ease...)