How can I add a marker to a donut chart created with Raphael.js?
Asked Answered
C

1

7

I need help adding a marker to this donut chart script I've modified utilizing raphael.js. I've got most everything ready to go except for a way to dynamically generate a triangular marker.

JSFiddle: http://jsfiddle.net/aP7MK/73/

function donutChart(total, goal, avg){

    var paper = Raphael("canvas", 400, 400);
    paper.customAttributes.arc = function (xloc, yloc, value, total, R) {
        var alpha = 360 / total * value,
            a = (90 - alpha) * Math.PI / 180,
            x = xloc + R * Math.cos(a),
            y = yloc - R * Math.sin(a),
            path;
        if (total == value) {
            path = [
                ["M", xloc, yloc - R],
                ["A", R, R, 0, 1, 1, xloc - 0.01, yloc - R]
            ];
        } else {
            path = [
                ["M", xloc, yloc - R],
                ["A", R, R, 0, +(alpha > 180), 1, x, y]
            ];
        }
        return {
            path: path
        };
    };

    var backCircle = paper.circle(100, 100, 40).attr({
        "stroke": "#7BC2E5",
            "stroke-width": 14
    });

    var theArc = paper.path().attr({
        "stroke": "#f5f5f5",
            "stroke-width": 14,
        arc: [100, 100, 0, 100, 40]
    });


    //event fired on each animation frame
    eve.on("raphael.anim.frame.*", onAnimate);

    //text in the middle
    theText = paper.text(100, 100, "0%").attr({
        "font-size": 18,
            "fill": "#f5f5f5",
            "font-weight": "bold"
    });

    //the animated arc
    theArc.rotate(0, 100, 100).animate({
        arc: [100, 100, ((total/goal) * 100), 100, 40]
    }, 1900);


    //on each animation frame we change the text in the middle

    function onAnimate() {
        var howMuch = theArc.attr("arc");
        theText.attr("text", Math.floor(howMuch[2]) + "%");
    }
}

donutChart(80, 140, 40);

Here's what I'm eventually trying to create:

I'm not worried about the styling, just need help with the marker element, which will denote where the avg argument being passed to the donutChart function lies within the chart.

Cashmere answered 27/11, 2013 at 2:22 Comment(2)
Could you use var tri = paper.path("M100,100,130,100,100,130z"); and then rotate/translate it depending on howMuch or something ?Clandestine
Hey @Clandestine - Sorry, I should've clarified that I don't really have any experience with generating SVGs. I found the code above within another SO question and modified it slightly to be more along the lines of what I'm looking for, but as for drawing and generating paths I have no idea where to start. Any chance you could try updating the example on fiddle with your suggestion?Cashmere
G
5

As @Ian said you can use path to draw triangle:

// triangle
var tri = paper.path("M100 50 L90 40 L110 40 L100 50 Z");

See the docs about using path (its commands).

Then you need to rotate/translate (again as @Ian said) but SVG helps you here providing rotate method which takes not only angle of rotation but also coordinates of point to rotate around (it translates coordinates for you)

tri.rotate((howMuch[2] - prev_percent) * 3.6, 100, 100);

The only thing here to note is that you need difference of previous and current percentage.

The working fiddle

Guitarist answered 6/12, 2013 at 12:40 Comment(3)
Thanks for the updated fiddle! I've made a few changes to what you set up to further mimic what I need for my final product and was wondering if you know how to color in the triangle or possibly add a straight line within the circle similar to the image above. jsfiddle.net/RS882/3Cashmere
It's easy jsfiddle.net/RS882/4. Actually you have all the pieces in your code to figure it outGuitarist
Nice! I've learned a lot about SVGs from this, thanks again for the help @twil!Cashmere

© 2022 - 2024 — McMap. All rights reserved.