0

I am trying to create a gauge like this using Canvas or SVG. I think I am going to use Canvas, unless people think it will be a lot easier to make with SVG. My question is, using canvas and no images, how would you go about, or, is it possible, to create the dashed lines around the outside of the gauge.

enter image description here

Thanks

sherlock
  • 744
  • 7
  • 21

1 Answers1

10

Canvas would be a good choice if your guage will be constantly changing.

Canvas is good at redrawing very quickly.

SVG is not as quick at redrawing, but it’s good if user interactivity is required.

enter image description here

This canvas function will draw radiant lines between an inner and outer circle:

function radiantLine(centerX,centerY,innerRadius,outerRadius,degrees,linewidth,color){

    var radians=degrees*Math.PI/180;
    var innerX = centerX + innerRadius * Math.cos(radians);
    var innerY = centerY + innerRadius * Math.sin(radians);
    var outerX = centerX + outerRadius * Math.cos(radians);
    var outerY = centerY + outerRadius * Math.sin(radians);

    ctx.beginPath();
    ctx.moveTo(innerX,innerY);
    ctx.lineTo(outerX,outerY);
    ctx.strokeStyle=color;
    ctx.lineWidth=linewidth;
    ctx.stroke();

}

Your gauge has values from 0-1000.

Here is code that is useful in mapping that (0-1000) range of values into the degrees (0-270) of your gauge’s arc.

// scale the guage values (0-1000) is mapped
// into the range of a partial circle (0-270 degree arc)
// value==0 is mapped to 0 degrees on the arc
// value==1000 is mapped to 270 degrees on the arc
var scaledValue=scaleIntoRange(0,1000,0,270,value);


function scaleIntoRange(minActual,maxActual,minRange,maxRange,value){
  var scaled=(maxRange-minRange)*(value-minRange)/(maxActual-minActual)+minRange;
  return(scaled);
}

After the incoming values are mapped to degrees on a circle, you would rotate by 135 degrees to match the starting angle on your guage (0 degrees on your guage is approximately 135 degrees on a circle)

// rotate so guage value==0 starts at 135 degrees on the circle
var degrees=scaledValue+135;

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/GV8du/

<!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");

    var cx=150;
    var cy=150;
    var innerRadius=50;
    var outerRadius=65;
    var startRadians=135*Math.PI/180;
    var endRadians=405*Math.PI/180;


    for(var value=0;value<=1000;value+=25){

        // scale the guage values (0-1000) 
        // to fit into the range of a partial circle (0-270 degrees)
        var scaledValue=scaleIntoRange(0,1000,0,270,value);
        // rotate so guageValue==0 starts at 135 degrees on the circle
        var degrees=scaledValue+135;

        // draw the radiant line
        // draw thicker/longer line every 250
        if(value%250==0){
            radiantLine(cx,cy,innerRadius,outerRadius,degrees,2,"black");
        }else{
            var shorterLine=(outerRadius-innerRadius)/2;
            radiantLine(cx,cy,innerRadius,outerRadius-shorterLine,degrees,2,"lightgray");
        }
    }


    // draw inner arc of guage
    ctx.beginPath();
    ctx.arc(cx,cy,innerRadius,startRadians,endRadians,false);
    ctx.strokeStyle="black";
    ctx.lineWidth=3;
    ctx.stroke();

    // draw outer arc of guage (for illustration only)
    ctx.beginPath();
    ctx.arc(cx,cy,outerRadius,startRadians,endRadians,false);
    ctx.strokeStyle="lightgray";
    ctx.lineWidth=0.33;
    ctx.stroke();


    function radiantLine(centerX,centerY,innerRadius,outerRadius,degrees,linewidth,color){

        var radians=degrees*Math.PI/180;
        var innerX = centerX + innerRadius * Math.cos(radians);
        var innerY = centerY + innerRadius * Math.sin(radians);
        var outerX = centerX + outerRadius * Math.cos(radians);
        var outerY = centerY + outerRadius * Math.sin(radians);

        ctx.beginPath();
        ctx.moveTo(innerX,innerY);
        ctx.lineTo(outerX,outerY);
        ctx.strokeStyle=color;
        ctx.lineWidth=linewidth;
        ctx.stroke();

    }


    function scaleIntoRange(minActual,maxActual,minRange,maxRange,value){
      var scaled=(maxRange-minRange)*(value-minRange)/(maxActual-minActual)+minRange;
      return(scaled);
    }

}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
markE
  • 102,905
  • 11
  • 164
  • 176