Isis
Isis

Reputation: 4666

javascript circle moves around a point

My element does circling around a point. JSFiddle

HTML

<div class="center-dot">
    <div class="dot"></div>
    <div class="one"></div>
    <div class="two"></div>
</div>

CSS:

.center-dot {position:relative;top:200px;left:200px;}
.dot {width:3px;height:3px;background:blue;}
.one {width:40px;height:40px;border-radius:40px;background:red;position:absolute;}
.two {width:40px;height:40px;border-radius:40px;background:green;position:absolute;}

JS:

var one = $('.one'),
    two = $('.two');

var one_start = 0,
    two_start = 0;

setInterval(function(){
    ++one_start;
    var one_css = {
        'left': Math.sin(one_start * 0.0010) * 100 ,
        'top': Math.cos(one_start * 0.0010) * 100
    }
    one.css(one_css);

    ++two_start;
    var two_css = {
        'left': Math.sin(two_start * 0.0025) * 200 ,
        'top': Math.cos(two_start * 0.0025) * 200
    }
    two.css(two_css);
}, 1);

But he does not do it exactly, but like it a zigzag.

How to make sure that the element did clean circle?

Upvotes: 2

Views: 1648

Answers (3)

user1693593
user1693593

Reputation:

This is in part caused by rounding-errors as plain CSS only deals with integer positions (see kolink's or Jonas' transform examples to enable fractional values).

If transform is not an option you can improve the rounding error by reducing the problem a little by "helping" the browser to round off correctly, either by adding 0.5 at the end:

'left': Math.sin(one_start * 0.001) * 100 +0.5,
'top': Math.cos(one_start * 0.001) * 100 +0.5

or using Math.round():

'left': Math.round(Math.sin(one_start * 0.001) * 100),
'top': Math.round(Math.cos(one_start * 0.001) * 100)

See here for modified fiddle.

Optionally you can also use a canvas element which supports sub-pixeling. This means your fractional positions will be rendered (interpolated/anti-aliased) and show a much smoother result (as with transformations) but with the flexibility that comes with the territory. However, CSS will be faster at rendering so if you don't need the (artistic) flexibility CSS is a better choice.

PS: the center is off. You can adjust: x - radius, y - radius and they will be in the correct position.

Upvotes: 3

Jonas Grumann
Jonas Grumann

Reputation: 10786

It's because of the sub-pixel rendering, using transforms instead of "top" and "left" should solve the issue:

http://jsfiddle.net/jonigiuro/HDhn4/2/

var one_css = {
    'transform': "translateX(" + (Math.sin(one_start * 0.0025) * 100) + 'px) translateY('+ Math.cos(one_start * 0.0025) * 100 + "px)"
}

This solution is not yet cross-browser, you might need to add css prefixed for that.

Also, read this:

http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/

PS: note that I only applied it to the red ball, so you can see the difference

Upvotes: 3

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324640

Don't use jQuery.

The problem is that positions are rounded to the nearest pixel, meaning the shapes cannot follow an exact circle.

Here is a CSS3-only reproduction of your animation. By using a transform, the effect is not constrained to integer pixel values and can therefore follow your circle perfectly.

Upvotes: 9

Related Questions