Reputation: 1976
I have drawn arc using canvas with percentage data. Now, I want to label each data with percentage text(ex: 20%). I have problem in positioning data percentage label on canvas arc. I could not position the text within each arc correctly.
blue-20% , yellow-20%, red-10%
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var jQCanvas = $('#canvas');
var canvas = jQCanvas[0];
canvas.width = jQCanvas.width();
canvas.height = jQCanvas.height();
center_x = canvas.width / 2; //x
center_y = canvas.height / 2; //y
lineWidth = 20;
var radius = canvas.height / 2 - 20; //r
circle(center_x, center_y, radius);
function circle(x, y, r) {
var starting_point = 1.5 * Math.PI;
cumulative_degree = 0;
data = [
['#17a2b8', 20],
['#ffc107', 20],
['#dc3545', 10]
]; //value in percent
ctx.lineWidth = 20; //arc thickness
for (j = 0; j < data.length; j++) {
ctx.strokeStyle = data[j][0]; //arc color
ctx.beginPath();
start = cumulative_degree * (Math.PI / 180) + starting_point;
degree = data[j][1] / 100 * 360;
cumulative_degree += data[j][1] / 100 * 360;
end = degree * (Math.PI / 180) + start;
ctx.arc(x, y, r, start, end);
//ctx.fillText(data[j][1]+'%', start, end);
ctx.stroke();
// draw the label
var midAngle = ((cumulative_degree - 90) - degree) + ((cumulative_degree - 90) - ((cumulative_degree - 90) - degree)) / 2;
var labelRadius = r * .75;
var cx = 50;
var cy = 50;
var lbl_x = cx + (labelRadius) * Math.cos(midAngle);
var lbl_y = cy + (labelRadius) * Math.sin(midAngle);
ctx.fillStyle = 'black';
ctx.fontSize = 30;
ctx.fillText(data[j][1], lbl_x, lbl_y);
}
remaining_degree = 360 - cumulative_degree;
ctx.strokeStyle = 'silver'; //arc color
ctx.beginPath();
start = cumulative_degree * (Math.PI / 180) + starting_point;
degree = remaining_degree;
end = degree * (Math.PI / 180) + start;
ctx.arc(x, y, r, start, end);
if (remaining_degree > 0) {
ctx.stroke();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" height="150" width="150"></canvas>
Upvotes: 0
Views: 170
Reputation: 1976
I have used radian of start and end angle instead of using angle when calculating midAngle. This is because when calculating radian, I have add in starting_point (1.5*Math.PI)
since I draw arc from top. Then, using midAngle to calculate x and y of label position.
var lbl_x = cx + (labelRadius) * Math.cos(midAngle);
var lbl_y = cy + (labelRadius) * Math.sin(midAngle);
For cx and cy, I have gave the value of canvas.width/2;
and canvas.height/2;
var canvas = document.getElementById("canvas");
var ctx = setupCanvas(document.querySelector('#canvas'));//to sharpen blur text on canvas
var ctx = canvas.getContext("2d");
var jQCanvas = $('#canvas');
var canvas = jQCanvas[0];
canvas.width = jQCanvas.width();
canvas.height = jQCanvas.height();
center_x=canvas.width/2;//x
center_y=canvas.height/2;//y
lineWidth=20;
var radius = canvas.height/2 - 20;//r
circle(center_x, center_y, radius);
function setupCanvas(canvas) {//increase device pixel ratio by adding 0.05
// Get the device pixel ratio, falling back to 1.
var dpr = window.devicePixelRatio || 1;
// Get the size of the canvas in CSS pixels.
var rect = canvas.getBoundingClientRect();
//console.log(dpr+'=>'+rect);
dpr=dpr+0.05;
// Give the canvas pixel dimensions of their CSS
// size * the device pixel ratio.
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
var ctx = canvas.getContext('2d');
// Scale all drawing operations by the dpr, so you
// don't have to worry about the difference.
ctx.scale(dpr, dpr);
return ctx;
} //high dpi canvas(https://www.html5rocks.com/en/tutorials/canvas/hidpi/)
function circle(x,y,r)
{
var starting_point=1.5*Math.PI;
cumulative_degree=0;
data=[['#17a2b8',25],['#ffc107',20],['#dc3545',5]];//value in percent
ctx.lineWidth=20;//arc thickness
for(j=0;j<data.length;j++)
{
ctx.strokeStyle=data[j][0];//arc color
ctx.beginPath();
start=cumulative_degree* (Math.PI / 180)+starting_point;
degree=data[j][1]/100*360;
cumulative_degree+=data[j][1]/100*360;
end=degree * (Math.PI / 180)+start;
ctx.arc(x, y, r, start, end);
ctx.stroke();
//label
var midAngle=start+(end-start)/2;
var labelRadius = r * .75;
var cx = center_x;
var cy = center_y;
var lbl_x = cx + (labelRadius) * Math.cos(midAngle);
var lbl_y = cy + (labelRadius) * Math.sin(midAngle);
ctx.fillStyle = 'black';
ctx.fontSize= 30;
console.log(lbl_x+'=>'+lbl_y);
ctx.fillText(data[j][1], lbl_x, lbl_y);
}
remaining_degree=360-cumulative_degree;
ctx.strokeStyle='silver';//arc color
ctx.beginPath();
start=cumulative_degree* (Math.PI / 180)+starting_point;
degree=remaining_degree;
end=degree * (Math.PI / 180)+start;
ctx.arc(x, y, r, start, end);
if(remaining_degree>0)
{
ctx.stroke();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" height="150" width="150"></canvas>
Upvotes: 1