简体   繁体   English

甜甜圈图表香草JS和HTML画布

[英]Doughnut Chart Vanilla JS and HTML Canvas

I am writing a doughnut pie chart with vanilla JavaScript using the HTML canvas element and fillText() to put the labels on the chart. 我正在使用HTML canvas元素和fillText()编写带有vanilla JavaScript的圆环饼图,以将标签放在图表上。 I'm having a hard time positioning the labels on the outside of the chart, and they're getting cut off by the width of the canvas. 我很难将标签放在图表的外面,而且它们会被画布的宽度切断。 Here's a working Codepen of the issue. 这是一个有问题的Codepen问题。

甜甜圈图表

Here is the snippet of the code that actually prints out the labels to the chart: 以下是实际将标签打印到图表的代码片段:

start_angle = 0;            
for (categ in catergories) {
    let categoryLabel = categ;
    val = catergories[categ];
    let slice_angle = 2 * Math.PI * val / total_value;
    let pieRadius = Math.min(this.canvas.width / 2,this.canvas.height / 2);
    let labelX = this.canvas.width / 2 + (pieRadius / 2) * Math.cos(start_angle + slice_angle / 2);
    let labelY = this.canvas.height / 2 + (pieRadius / 2) * Math.sin(start_angle + slice_angle / 2);

    if (this.options.doughnutHoleSize){
        let offset = (pieRadius * this.options.doughnutHoleSize ) / 2;
        labelX = this.canvas.width / 2 + (offset + pieRadius / 2) * Math.cos(start_angle + slice_angle / 2);
        labelY = this.canvas.height / 2 + (offset + pieRadius / 2) * Math.sin(start_angle + slice_angle / 2);               
    }

    this.ctx.fillStyle = "black";
    this.ctx.font = "bold 11px Arial";
    this.ctx.fillText(`${categoryLabel} ${val}`, labelX, labelY);
    start_angle += slice_angle;
}

Desired positioning: 期望的定位:

期望

This is a simple case of knowing some trigonometry and the canvas text API. 这是了解一些三角函数和画布文本API的简单情况。

I used the cos and sin values from the angle of the center of the respective slice to set the horizontal and vertical alignment of the text, like so: 我使用相应切片中心角度的cos和sin值来设置文本的水平和垂直对齐方式,如下所示:

    this.ctx.textAlign = cos > 0 ? 'start' : 'end';
    this.ctx.textBaseline = sin > 0 ? 'top' : 'bottom';

Furthermore I added two more options to the piechart costructor: 此外,我在饼图结构中添加了两个选项:

    const monthlyPaymentChart = new Piechart({
        canvas: canvas,
        data: paymentInformation,
        colors: pieChartColors,
        doughnutHoleSize: 0.85,

        labelDistanceFromOuterEdge: 5,
        roomForLabels: 65,
    });
  • roomForLabels - tells how much room to reserve for the labels roomForLabels - 告诉我们为标签预留多少空间
    displayed outside of the pie chart in pixels. 以饼干形式显示在饼图外部。 If the width of any label won't fit in the canvas, this value is increased to accommodate it. 如果任何标签的宽度不适合画布,则增加此值以适应它。

  • labelDistanceFromOuterEdge - How far away the labels are from the labelDistanceFromOuterEdge - 标签距离标签的距离
    edge of the pie chart in pixels. 饼图的边缘(以像素为单位)。

To measure the text, I used the measureText function of the canvas 2d context API. 为了测量文本,我使用了canvas 2d context API的measureText函数。 That is why the font and text size is also set at the beginning of the constructor of the Piechart 这就是为什么字体和文本大小也设置在饼图的构造函数的开头

The full code can be found here: https://codepen.io/prtjohanson/pen/bZgQmY 完整的代码可以在这里找到: https//codepen.io/prtjohanson/pen/bZgQmY

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM