iWJ
iWJ

Reputation: 33

Rotate HTML canvas circle scale

I am experiencing trouble in rotating a circle with HTML5 canvas. the function is about control a circle, but the scale is out of control...

anyone know how to adjust(or set rotate) the scale to fit the canvas circle?

The starting angle(0.7 pi) and endAngle(0.3 pi). Do I need to reset the rotate? --> ctx.rotate(Math.PI * 3 / 16); -->(math.pi*15/10*1/8)

    var degrees = 0;
    var color = "lightblue";
    var bgcolor = "#222";
    var canvas, ctx, W, Htext;



    function init_rpm(name, val) {
        canvas = document.getElementById(name);
        ctx = canvas.getContext("2d");
        //dimensions
        W = canvas.width;
        H = canvas.height;
        //Clear the canvas everytime a chart is drawn
        ctx.clearRect(0, 0, W, H);

        //Background 360 degree arc
        ctx.beginPath();
        ctx.lineWidth = 25;
        ctx.strokeStyle = bgcolor;
        ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.3 * Math.PI, false); //you can see thr src now
        ctx.stroke();

        //center circle
        ctx.save();
        ctx.beginPath();
        ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
        ctx.lineWidth = 10;
        ctx.arc(W / 2, H / 2, Math.floor(W / 3) - 40, 0.7 * Math.PI, 0.3 * Math.PI, false);
        ctx.stroke();
        ctx.restore();

        // scale
        ctx.save();
        ctx.translate(300, 300);

        for (var i = 0; i < 9; i++) {
            ctx.beginPath();
            ctx.lineWidth = 2;
            ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
            ctx.moveTo(130, 0);
            ctx.lineTo(140, 0);
            ctx.stroke();
            ctx.rotate(Math.PI * 3 / 16);
        }
        ctx.restore();

        //angle in radians =angle in drgrees*pi/180 make color
        var percent = val / 8000 * 100;
        ctx.beginPath();
        ctx.lineWidth = 30;
        // ctx.strokeStyle= color;
        var my_gradient = ctx.createLinearGradient(0, 150, 250, 300);
        my_gradient.addColorStop(0, "#B31918");
        my_gradient.addColorStop(1, "#FFA000");
        ctx.strokeStyle = my_gradient;
        //the arc  start from the rightmost end. if we deduct 90 degrees from the angles 
        //the arc will start from the top most end
        ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.7 * Math.PI + 1.6 * Math.PI / 100 * percent, false); //you can see thr src now
        ctx.stroke();


        //add text
        ctx.fillStyle = color;
        ctx.font = "7vh play";
        // text=Math.floor(degrees/360*8)+' RPM';
        text = degrees / 360 * 8;
        text_width = ctx.measureText(text).width;
        ctx.fillText(text, W / 2 - text_width / 2, H / 2 + 15);

        ctx.font = "3vh play";
        text2 = 'RPM';
        ctx.fillText(text2, W / 2 - text_width / 2, H / 2 + 70);
    }

   
    function draw(val, name, type) {
        // console.log(val);
        if (name != "" || name != null) {

            if (type == "rpm") {
                if (val != "" || val != null) {
                    degrees = val / 1000 / 8 * 360;
                } else {
                    degrees = 180;
                }
                init_rpm(name, val);
            } else if (type == "kmh") {
                if (val != "" || val != null) {
                    degrees = val;
                } else {
                    degrees = 180;
                }
                init_kmh(name);
            }

        } else {
            console.log('can not find canvas id');
        }

    }


    $(document).ready(function () {
        //canvas init

        draw(0, "canvas3", "rpm");



        var rpmControl2 = document.querySelector('input[id=get_rpm]');
        rpmControl2.addEventListener('input', function () {
            draw(this.value, "canvas3", "rpm");
        });


    });
#canvas2{
    display:inline;
}
body{
    background:#333;
    font-family: 'Play', sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="container-fluid">
        <input id="get_rpm" type="number" value="0" min="0" max="8000" step="100" />
        <span style="color:white">RPM</span>
     
       
   
        <canvas id="canvas3" width="600" height="600"></canvas>

Upvotes: 3

Views: 699

Answers (1)

Kaiido
Kaiido

Reputation: 136628

Your scale is drawn by drawing its lines in a single direction and then controlling the context's rotation to make all these lines point at a different angle.
Just like if you held a ruler always in the same direction and simply rotated the leaf of paper underneath.
So to control the rotation of your scale, you have to set the context's rotation (or leaf of paper) before you draw the first line.

var ctx = c.getContext('2d');
angle.oninput = function(e) {
  ctx.clearRect(0, 0, c.width, c.height);
  var rad = angle.value * (Math.PI / 180);
  // move the context so its center be at 0,0
  ctx.setTransform(1, 0, 0, 1, c.width/2, c.height/2);
  // rotate it so we face the required angle
  ctx.rotate(rad);
  var stepAngle = Math.PI*2 / 14,
    innerRad = c.width / 2.8,
    outerRad = c.width / 2.5;
  ctx.beginPath();
  for(var i = 0; i < 12; i++) {
    ctx.moveTo(0, innerRad); // move vertically
    ctx.lineTo(0, outerRad); // draw line vertically
    ctx.rotate(stepAngle); // rotate by fixed increment
  }
  ctx.stroke();  // all drawn, we can stroke
  ctx.setTransform(1, 0, 0, 1, 0, 0); // reset context's position
};
angle.oninput();
<input type="range" min="0" max="360" id="angle"><br>
<canvas id="c" width="200" height="200"></canvas>

And with your code:

var degrees = 0;
    var color = "lightblue";
    var bgcolor = "#222";
    var canvas, ctx, W, Htext;



    function init_rpm(name, val) {
        canvas = document.getElementById(name);
        ctx = canvas.getContext("2d");
        //dimensions
        W = canvas.width;
        H = canvas.height;
        //Clear the canvas everytime a chart is drawn
        ctx.clearRect(0, 0, W, H);

        //Background 360 degree arc
        ctx.beginPath();
        ctx.lineWidth = 25;
        ctx.strokeStyle = bgcolor;
        ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.3 * Math.PI, false); //you can see thr src now
        ctx.stroke();

        //center circle
        ctx.beginPath();
        ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
        ctx.lineWidth = 10;
        ctx.arc(W / 2, H / 2, Math.floor(W / 3) - 40, 0.7 * Math.PI, 0.3 * Math.PI, false);
        ctx.stroke();

//EDITS BEGIN HERE
        // scale

        ctx.setTransform(1, 0, 0, 1, 300, 300);

        ctx.beginPath();
        ctx.lineWidth = 2;
        ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
        // there should be 10 lines
        var stepAngle = (Math.PI * 2) / 10;
        // begin angle
        ctx.rotate(0.7 * Math.PI);
        // draw only 9 of the 10 lines
        for (var i = 0; i < 9; i++) {
            ctx.moveTo(130, 0);
            ctx.lineTo(140, 0);
            ctx.rotate(stepAngle);
        }
        ctx.stroke();
        ctx.setTransform(1, 0, 0, 1, 0, 0);

//EDITS END HERE

        var percent = val / 8000 * 100;
        ctx.beginPath();
        ctx.lineWidth = 30;

        var my_gradient = ctx.createLinearGradient(0, 150, 250, 300);
        my_gradient.addColorStop(0, "#B31918");
        my_gradient.addColorStop(1, "#FFA000");
        ctx.strokeStyle = my_gradient;
        //the arc  start from the rightmost end. if we deduct 90 degrees from the angles 
        //the arc will start from the top most end
        ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.7 * Math.PI + 1.6 * Math.PI / 100 * percent, false); //you can see thr src now
        ctx.stroke();


        //add text
        ctx.fillStyle = color;
        ctx.font = "7vh play";
        // text=Math.floor(degrees/360*8)+' RPM';
        text = degrees / 360 * 8;
        text_width = ctx.measureText(text).width;
        ctx.fillText(text, W / 2 - text_width / 2, H / 2 + 15);

        ctx.font = "3vh play";
        text2 = 'RPM';
        ctx.fillText(text2, W / 2 - text_width / 2, H / 2 + 70);
    }

   
    function draw(val, name, type) {
        // console.log(val);
        if (name != "" || name != null) {

            if (type == "rpm") {
                if (val != "" || val != null) {
                    degrees = val / 1000 / 8 * 360;
                } else {
                    degrees = 180;
                }
                init_rpm(name, val);
            } else if (type == "kmh") {
                if (val != "" || val != null) {
                    degrees = val;
                } else {
                    degrees = 180;
                }
                init_kmh(name);
            }

        } else {
            console.log('can not find canvas id');
        }

    }


    $(document).ready(function () {
        //canvas init

        draw(0, "canvas3", "rpm");



        var rpmControl2 = document.querySelector('input[id=get_rpm]');
        rpmControl2.addEventListener('input', function () {
            draw(this.value, "canvas3", "rpm");
        });


    });
#canvas2{
    display:inline;
}
body{
    background:#333;
    font-family: 'Play', sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="container-fluid">
        <input id="get_rpm" type="number" value="0" min="0" max="8000" step="100" />
        <span style="color:white">RPM</span>
     
       
   
        <canvas id="canvas3" width="600" height="600"></canvas>

Upvotes: 3

Related Questions