53

Edit: since chrome has updated the browser - this question is some what redundant as they have fixed an internal bug which means this problem no longer occurs.

I have an animation of a circle anchored to the center of the canvas.

The larger the circle becomes the less stable the motion is. But not only that, for me at least it is significantly worse in Chrome to Firefox.

The math is done in this function:

function update(deltaTime){
    var centerX = canvas.width/2;
    var centerY = canvas.height/2;
        i.currentAngle = (i.currentAngle || 0) + (deltaTime/1000 * i.rotationSpeed);

    if(i.currentAngle>2*Math.PI){
        i.currentAngle-=2*Math.PI;
    }
        i.x = centerX + (i.radius*i.factor) * Math.cos(i.currentAngle);
        i.y = centerY + (i.radius*i.factor) * Math.sin(i.currentAngle);  
}

This is the code in working example:

http://jsfiddle.net/96QDK/

Chrome outputs:

Firefox Outputs:

enter image description here

Firefox seems to be closest to what I am aiming for yet Chrome is just wacky.

Why do I get such different results? I should mention I've asked a few people what they see, and everyone is seeing different amounts of inaccuracy.

Sir
  • 8,135
  • 17
  • 83
  • 146
  • looks fine in chrome(Iron) on windows 8 and arch linux – VeXii Nov 16 '13 at 03:38
  • Seems to work fine on Chrome 31 and IE 11 here. Which version of Chrome are you using? – Nick Nov 16 '13 at 03:40
  • I am on `Version 33.0.1707.0 m` – Sir Nov 16 '13 at 03:41
  • I see a circle rotating around a dot in jsfiddle, I see lines rotating around a dot in this page. I am on chrome 31.0.1650.57 win 7. – yasar Nov 16 '13 at 03:45
  • @yasar11732 my bad i posted wrong fiddle please visit the new fiddle :) – Sir Nov 16 '13 at 03:46
  • 2yasar : In that fiddle it should be scaled up to 80 to get 'lines'. I have same strange effect, Chrome 30.0.1599.114 on Ubuntu 13.04 – ProdoElmit Nov 16 '13 at 04:02
  • 1
    Looks like the problem is in canvas functions (maybe implementations of them in browsers), as math functions give almost zero error on sum of cos^2 and sin^2, even with such a scale : http://jsfiddle.net/9Gt2L/ – ProdoElmit Nov 16 '13 at 04:05
  • @morodeer so does that mean FireFox's implementation is more accurate or something :S ? – Sir Nov 16 '13 at 04:06
  • @Dave, looks so... I think, this should be posted somewhere to google's bugtracker. – ProdoElmit Nov 16 '13 at 04:08
  • 1
    @morodeer i shall do that right away :) – Sir Nov 16 '13 at 04:10
  • Really what is with the down voting =/ Edit: they removed it. – Sir Nov 16 '13 at 04:37
  • 1
    30.0.1599.101 on Windows, works just fine. Not seeing the tiniest amount of the line bouncing, not even as much as in your Firefox sample – Jani Hartikainen Nov 16 '13 at 12:34
  • I was just going to comment the same as @Jani. I don't see any issue with the fiddle on Chrome either (same version /OS). – Martin Smith Nov 16 '13 at 12:35
  • Why does the line itself stretch when it moves sideways? Or alternatively, why does it shrink when it goes vertical? – Joe Nov 16 '13 at 12:53
  • @Joe, it is displayed inside the area, which is a rectangle. The line doesn't stretch. And for the info, on my chrome (31.0.1650.57, osx) i have the same prob as you. But on safari 6.1, it works like a charm! – leMoisela Nov 16 '13 at 12:55
  • Yeah, it has to be a chrome bug… even when printing the distance of the center of the circle (which should always be equal to the radius if there is no error) its giving me the right result (var dist = Math.sqrt(Math.pow(i.x - canvas.width/2,2) + Math.pow(i.y - canvas.height/2,2)); == always equal to radius * factor). Oh btw, there is a small error in your code; it is not Math.Pi, but Math.PI (when you check the currentAngle) – leMoisela Nov 16 '13 at 13:45
  • The line bounces with Chrome 31.0.1650.48 on ubuntu 12.04 LTS – Alessandro Jacopson Nov 16 '13 at 13:59
  • 2
    Just updated from Chrome 30 to 31 and this bug came out – Danilo Valente Nov 16 '13 at 14:32
  • The changes are smooth (you can't see it clearly from the pictures, but that's how they are) so it's not a conventional rounding bug; is there some kind of horrible problem in the trig functions? (Problem seen in Chrome on OSX, but Safari is rock-steady.) – Donal Fellows Nov 16 '13 at 16:46
  • Yeh the frame rate of the gifs are low to keep file size down :) – Sir Nov 16 '13 at 16:47
  • Upgraded to 31.0.1650.57 on Windows and now see it. – Martin Smith Nov 16 '13 at 18:03
  • It works fine on version 31? Cos im on version 33.. – Sir Nov 16 '13 at 18:04
  • @Dave - Not for me. It worked fine earlier when I was on 30.0.1599.101 but after upgrading to 31.0.1650.57 I see the problem. Same as Mark Linus reports. – Martin Smith Nov 16 '13 at 18:06
  • I see the problem. Chrome 30, Ubuntu 12.04. – Paul Draper Nov 16 '13 at 20:18
  • @Joe the line stratches in my .gifs because the image shape is only a snipper of the actual canvas size. – Sir Nov 16 '13 at 21:09
  • Like others here, it works fine for me in Chrome 30.0.1599.101, but not in 31.0.1650.57 (both on Windows 8.1). – Moshe Katz Nov 20 '13 at 03:53
  • To update everyone - chrome has updated the bug report. – Sir Dec 17 '13 at 04:11
  • Secondary update - it is now fixed. – Sir Jul 07 '15 at 21:45

2 Answers2

28

The problem is not with the Javascript math; it's with the canvas.

http://jsfiddle.net/LDWBX/

function bigCircle(angle) {
    var radius = 5000; //the bigger, the worse
    var x = canvas.width/2 + radius*Math.cos(angle);
    var y = canvas.height/2 + radius*Math.sin(angle);

    ctx.beginPath();
    ctx.arc(x, y, radius, 0, 2 * Math.PI);
    ctx.lineWidth = 2;
    ctx.stroke();
}

Notice that numbers appear exactly the same as in Firefox, but the red arc is obviously drawn incorrectly in Chrome.

screenshot

Interestingly, this works for all angles that are multiples of Math.PI / 4 but is off for values between those (hence the undulating behavior in the OP's example).

I've logged Chromium bug #320335.

EDIT: It looks like it was first reported in May 2012, and was caused by a bug in the Skia library.

It has now been resolved as fixed.

Paul Draper
  • 78,542
  • 46
  • 206
  • 285
  • 5
    Nice findings, i have noticed `IE` is most accurate, and `FF` is slightly off but not as bad as Chrome. Odd for IE to come out trumps here! – Sir Nov 16 '13 at 21:03
2

Doesn't give you an answer, but Interestingly on Chrome there is a issue with the maths

i.currentAngle => 0.0;
(deltaTime/1000 * i.rotationSpeed) = 0.025;

i.currentAngle + (deltaTime/1000 * i.rotationSpeed) = 2215385637.025;

If you get the individual parts into variables out of Update() and into draw() so that you can use

var current = i.currentAngle;
var delta = (deltaTime/1000 * i.rotationSpeed);

ctx.fillText(("angle == " + current+ " delta " + delta),10,50);

you get (0.025 and 0) printed out

if you then change to

var current = i.currentAngle;
var delta = (deltaTime/1000 * i.rotationSpeed);

i.currentAngle = current + delta;

ctx.fillText(("angle == " + i.currentAngle + " delta " + delta),10,50);

You get a crazy large value.

but if you do

var newval = current + delta;
ctx.fillText(("angle == " + newval + " delta " + delta),10,50);

then newval has a value of around 0.025 which is what you would expect it to be.

Oddly if you then do the following

var newval = current + delta;
i.currentAngle = newval

ctx.fillText(("angle == " + newval + " delta " + delta),10,50);

then newval is now the completely crazy value....

Code Uniquely
  • 6,356
  • 4
  • 30
  • 40
  • 1
    That last part doesn't make sense why `newval` would change just because it is assigned to `i.currentAngle` ? Are you sure that happened? – Sir Nov 16 '13 at 17:48
  • Yes I'm absolutely sure that's happening. which is why this is interesting! Try it ... – Code Uniquely Nov 17 '13 at 08:10