How can I build a double doughnut chart that spins when triggered


I've tried Chart.js, ChartJS.js, Highchart.js, and some straight forward CSS changes with jQuery, and nothing's working right. Here's what I'm hoping to accomplish:

enter image description here

I apologize for my lack of code, and I'm not looking for anyone to build me a solution. I'm not having any luck with Google and I'm out of creative ideas. Could anyone offer a suggestion or point me towards a possible solution?

Thanks

Update: here's an attempt to use rotate()

<div id="spectrumDoughnutWrapper">
    <canvas class="chart" id="spectrumDoughnut" width="150" height="150"></canvas>
</div>


buildChart(0);

$('spectrumDoughnut').click(function(){
    buildChart(20);
});

function buildChart(degree){
var ctx = document.getElementById("spectrumDoughnut").getContext("2d");

var data = [
    { value: 10, color:"#ad6262" },
{ value: 10, color:"#c26558" },
    { value: 10, color:"#c8896e" },
    { value: 10, color:"#d9bc78" },
    { value: 10, color:"#fdf57a" },
    { value: 10, color:"#b3c78f" },
    { value: 10, color:"#a3b476" },
    { value: 10, color:"#768b69" },
    { value: 10, color:"#6988b0" },
    { value: 10, color:"#698880" },
    { value: 10, color:"#8d95b9" },
    { value: 10, color:"#905e79" }
]

var options = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true,

//String - The colour of each segment stroke
segmentStrokeColor : "#fff",

//Number - The width of each segment stroke
segmentStrokeWidth : 1,

//The percentage of the chart that we cut out of the middle.
percentageInnerCutout : 75,

//Boolean - Whether we should animate the chart 
animation : true,

//Number - Amount of animation steps
animationSteps : 100,

//String - Animation easing effect
animationEasing : "easeOutBounce",

//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : false,

//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false
}

ctx.rotate(degree);

new Chart(ctx).Doughnut(data,options);
}

Answers:


Rotation around a centerpoint involves 2 context transforms

  • translate to the rotation point: context.translate(centerX,centerY);

  • rotate by a specified radian angle: context.rotate( 90 * Math.PI/180 );

Here's code and a Demo: http://jsfiddle.net/m1erickson/rL5aX/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    ctx.lineWidth=20;

    var PI=Math.PI;
    var rotation=0;

    var arcs=[];
    arcs.push({cx:150,cy:150,radius:100,startAngle:-45,endAngle:45,color:"blue"});
    arcs.push({cx:150,cy:150,radius:100,startAngle:45,endAngle:135,color:"red"});
    arcs.push({cx:150,cy:150,radius:100,startAngle:135,endAngle:225,color:"gold"});
    arcs.push({cx:150,cy:150,radius:100,startAngle:225,endAngle:315,color:"green"});

    arcs.push({cx:150,cy:150,radius:75,startAngle:-43,endAngle:-2,color:"blue"});
    arcs.push({cx:150,cy:150,radius:75,startAngle:0,endAngle:45,color:"blue"});


    arcs.push({cx:150,cy:150,radius:75,startAngle:47,endAngle:88,color:"red"});
    arcs.push({cx:150,cy:150,radius:75,startAngle:90,endAngle:135,color:"red"});

    arcs.push({cx:150,cy:150,radius:75,startAngle:137,endAngle:180,color:"gold"});
    arcs.push({cx:150,cy:150,radius:75,startAngle:182,endAngle:225,color:"gold"});

    arcs.push({cx:150,cy:150,radius:75,startAngle:227,endAngle:272,color:"green"});
    arcs.push({cx:150,cy:150,radius:75,startAngle:275,endAngle:313,color:"green"});

    drawAll();

    function drawAll(){
        for(var i=0;i<arcs.length;i++){
            draw(arcs[i]);
        }
    }
    function draw(a){
        ctx.save();
        ctx.translate(a.cx,a.cy);
        ctx.rotate(rotation*PI/180);
        ctx.beginPath();
        ctx.arc(0,0,a.radius,a.startAngle*PI/180,a.endAngle*PI/180);
        ctx.strokeStyle=a.color;
        ctx.stroke();
        ctx.restore();
    }

    $("#rotate").click(function(){
        rotation+=90;
        drawAll();
    });

}); // end $(function(){});
</script>
</head>
<body>
    <button id="rotate">Rotate</button>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

[ Extra Credit Followup ]

Here's some untested-probably-needs-tweaking code to determine if x,y is inside an arc

var arc1={
    cx:0,
    cy:0,
    innerRadius:50,
    outerRadius:70,
    startAngle:0,
    endAngle:Math.PI
}

function isPointInArc(x,y,arc){    
    var dx=x-arc.cx;
    var dy=y-arc.cy;
    var dxy=dx*dx+dy*dy;

    // test if x,y is between the inner and outer radii of the arc
    var rrOuter=arc.outerRadius*arc.outerRadius;
    var rrInner=arc.innerRadius*arc.innerRadius;
    if(dxy<rrInner || dxy>rrOuter){return(false);}

    // test if the angle of xy to centerpoint is inside the arc angle
    var angle=(Math.atan2(dy,dx)+PI2)%PI2;
    return(angle>=arc.startAngle && angle<=arc.endAngle);
}

Good luck with your project!