Matt Rothenberg
Matt Rothenberg

Reputation: 86

Circular Progress Meter

all!

I'm using jQuery Knob to create a circular progress meter for a web project.

All goes well implementation-wise, but I've hit a snag on the coding / design front. I'm a visual learner, so I drew an illustration that probably explains my question better than I can.

illustration of desired outcome where circle fill originates from a point and propagates equally in both directions from the point

By default, the inner fill of the dials generated by this plug-in originate from one edge and flow continuously to the other (see: second half of illustration).

I'm wondering if it's possible to modify this behavior, and have the inner-fill originate from the center point of the dial, propagating outward in an equal fashion until it hits the edges of the dial.

Although I have some jQuery / Javascript chops, I'm a total novice when it comes to Canvas.

Any thoughts, ideas, or guidance would be most appreciated!

Upvotes: 2

Views: 3097

Answers (1)

David Titarenco
David Titarenco

Reputation: 33396

You need a couple of parts to make this work:

  1. You need to use the Knob "cursor" mode so jQuery Knob knows to start drawing from the center.
  2. You need to "lock" the cursor in position via a readonly directive to make sure people don't rotate the graphic once you've drawn it.
  3. You need to redraw the knob every increment via a change event (mousemove or similar might also work).

So basically the element will look something like this:

<input data-readonly="true" data-cursor="true" type="text" value="75" class="knob" data-width="140" data-fgcolor="#ffa800" style="width: 74px; height: 46px; position: absolute; vertical-align: middle; margin-top: 46px; margin-left: -107px; border: 0px none; background: none repeat scroll 0% 0% transparent; font: bold 28px Arial; text-align: center; color: rgb(255, 168, 0); padding: 0px;">

Note that we're making the knob readonly and we're using a data-cursor. Those are the only important parts here. Looking over to the JS we see:

var ratio = 20; // be warned: I shouldn't be using a global

function Cur(x) {
    return x/100; // we use x/100 here because that's what it looks like in jquery.knob.js
}

The ratio variable is going to be the variable we mess around with (once it changes, the "fill" increases or decreases. The Cur() function is a proxy function we will bind to the cursor option outlined in the Knob API reference. This is nontrivial for someone that doesn't really understand how JS works, but it does work. So when we init the Knob object, it will look like this:

$(".knob").knob({
    draw : function () {
        console.log("drawing...");
        this.cursorExt = Cur.bind(null, ratio)();
        }
});

Obviously the magic happens at Cur.bind(null, ratio)() -- this ensures that the value of ratio (via the ratio function Cur()) passes through to the internals of Knob. And then, we need to animate it (or somehow make sure that the graphic updates):

$( "#go" ).click(function() {
    $({value: 20}).animate({value: 300}, {
        duration: 1000,
    easing:'swing',
    step: function() {
        ratio = this.value;           // ratio updates..
        $('.knob').trigger('change'); // and we pass through the new cursor size via a 'change' ping
    }
    })
});

And that should do it. See an implementation of the above here.

Upvotes: 2

Related Questions