5

I'm currently trying to draw arcs using the KineticJS canvas framework. The issue I'm having is that these arcs are not nearly as "perfectly" circular as required.

They're being drawn out as follows:

var redArc = new Kinetic.Shape({
    drawFunc: function (canvas) {
        var ctx = canvas.getContext();
        ctx.beginPath();
        ctx.arc(x, y, r, 0, Math.PI / 2, true);    // Arc of 270°
        canvas.fillStroke(this);
    },
    x: x,
    y: y,
    stroke: 'rgb(255,0,0)',
    strokeWidth: 20,
    offset: [x, y]
});

I knew that this might have been an issue since there's no such thing as rendering a near-perfect circle on a pixel based medium without the use of anti-aliasing on the stroke

I was wandering if this issue might be resolved by rendering with vector graphics or if there was an alternative solution?

I've included a JSFiddle to outline this issue, the circles are being animated rotating around their axis. This effect is more apparent with the arc(s) appearing to "wobble" as they rotate.

JSFiddle: http://jsfiddle.net/EHDFV/

zesda
  • 418
  • 6
  • 18
  • Unfortunately I can't say anything on-topic, but when you ctx.beginPath() you should also ctx.endPath() after calling fillStroke. – Philipp Mar 19 '13 at 13:36
  • Those arcs look fine to me. I don't see any "wobble". What **exactly** do you mean when you say that they're imperfect? – Pointy Mar 19 '13 at 13:46
  • @Philipp I can see where you're coming from, but for the sake of this example `endPath()` doesn't really need to be called because there is no "end path", the arc itself is drawn within the limits of it's parameters. – zesda Mar 19 '13 at 13:47
  • @Pointy It's more noticeable on larger resolutions, currently I'm looking at it at `2550 x 1320` an it's fairly obvious observing from about a meter from the screen. – zesda Mar 19 '13 at 13:51
  • I think you don't understand what endPath actually means. `.arc` doesn't create a path, it creates a segment of a path. A path can consist of many line, arc, bezier and other segments. When you call the `fillStroke` method, this method will be applied to all path segments since the last beginPath command. – Philipp Mar 19 '13 at 13:53
  • @zesda - are you restricted to KinecticJs? – user1236048 Mar 19 '13 at 13:54
  • @Philipp I see what you mean, I'm not sure if it's handled automagically via KineticJS but including `ctx.endPath()` after the `fillStroke()` method breaks the original JSFiddle... – zesda Mar 19 '13 at 14:02
  • @alex.dominte Not necessarily, I've recreated the same with just canvas and JS before now. It was just the lure of KineticJS and it's capability of handling multiple-layered animations (where I'm hoping to go on with this project) that originally appealed to me. – zesda Mar 19 '13 at 14:05
  • @Philipp I don't think there's any such thing as `.endPath()` – Pointy Mar 19 '13 at 14:14
  • OK, my bad. I checked the w3c specification and there is indeed no endPath method. beginPath also ends the current path. No idea where I got that, maybe some other graphic API. Sorry about that. – Philipp Mar 19 '13 at 14:17
  • @zesda - I know this won't 'answer' your question - but maybe this will help: raphaelJS html library. similar example to what you need: http://raphaeljs.com/polar-clock.html – user1236048 Mar 19 '13 at 14:18
  • @alex.dominte That's very fancy! I will certainly have to look at that as being a possible work around to HTML5 canvas :) – zesda Mar 19 '13 at 16:48
  • 1
    I could be wrong, but your "wobble" is actually **caused** by anti-aliasing. On canvas, you can't turn off anti-aliasing so the browser will try to render your circles with partial-color pixels that "bleed" off the pure circle path. I ran across this problem when rendering text on canvas. Certain text (mainly with curves) appear blurry and I finally tracked it down to the browser's anti-aliasing. My research indicates that it is not possible to turn off A-A on canvas. You *are* able to turn off A-A when rendering SVG text. You might check if you can do same when rendering SVG paths. – markE Mar 20 '13 at 04:28

1 Answers1

0

Could the wobble be an optical illusion.

Have added a stationary black circle around your animation.

var blackCircle = new Kinetic.Shape({
    drawFunc: function (canvas) {
        var ctx = canvas.getContext();
        ctx.beginPath();
        ctx.arc(x, y, (r + 10), 0, 2 * Math.PI, true);
        canvas.fillStroke(this);
    },
    x: x,
    y: y,
    stroke: 'rgb(0,0,0)',
    strokeWidth: 1,
    offset: [x, y]
});

Does your wobble cross the black circle at any point or leave a gap?

New fiddle http://jsfiddle.net/EHDFV/1/

jing3142
  • 1,821
  • 1
  • 11
  • 16
  • You've added that black circle on a layer above the red arc, it appears that the "wobble" occurs within +/−1px (since the width of the stroke is 1px), but it's definitely there. If you add the black circle to a layer behind that of the red arc then this becomes noticeable. – zesda Mar 19 '13 at 16:45