Canvas初探--实现一个饼图

上一节中,我们详细介绍了柱状图的canvas实现方式,那么在本篇文章中,我将详细介绍一下如何用canvas实现一个饼图。

如何实现一个饼图?

Step1

首先创建一个叫做piechart.html的新文件,并且在其中写入如下代码:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <canvas width="500" height="500" id="canvas"></canvas>
  </body>
  <script>
    //initialize data set
    var data = [100, 68, 20, 30, 100];

    var canvas = document.getElementById("canvas");
    var c = canvas.getContext("2d");
    //draw background
    c.fillStyle = "white";
    c.fillRect(0, 0, 500, 500);
  </script>
</html>

在这里我们创建了一个文件来存放我们的canvas和数据。

再说回饼图,如果我们想要绘制饼图的话,就会遇到一个核心问题:"角度的计算与绘制。"

Step2

js 复制代码
//a list of colors
var colors = ["orange", "green", "blue", "yellow", "teal"];

//calculate total of all data
var total = 0;
for (var i = 0; i < data.length; i++) {
    total += data[i];
}

如代码所示,我们使用totaldata的比例来计算角度。

Step3

到了这里,我们就要详细的计算角度了

  1. 绘制圆弧路径,我们需要用到一个新的 api =>

CanvasRenderingContext2D.arc(x, y, radius, startAngle, endAngle, anticlockwise)

这里一共有五个参数,第一个参数是圆弧中心(圆心)的 x 轴坐标;第二个参数是圆弧中心(圆心)的 y 轴坐标;第三个参数是圆弧的半径;第四个参数是圆弧的起始点,x 轴方向开始计算,单位以弧度表示;第五个参数是圆弧的终点,单位以弧度表示;第六个参数是可选的Boolean值,如果为 true,逆时针绘制圆弧,反之,顺时针绘制。

  1. 第二个点,是想要说一下弧度的计算公式:2*π*占比

代码如下:

JS 复制代码
    var prevAngle = 0;
    for (var i = 0; i < data.length; i++) {
      // 占比
      var fabrication = data[i] / total;
      // 计算当下角度
      var angle = prevAngle + fabrication * Math.PI * 2;
      c.fillStyle = colors[i];

      // 写一个路径
      c.beginPath();
      c.moveTo(250, 250);
      c.arc(250, 250, 100, prevAngle, angle, false);
      c.lineTo(250, 250);

      c.fill();

      c.strokeStyle = "black";
      c.stroke();

      prevAngle = angle;
    }

效果如下:

Step4

在实现了我们的基本功能之后,我们得把相应的描述饼图的文本加上去。

为了实现文本的居中,我们这里又涉及了一个新的api =>

CanvasRenderingContext2D.measureText()方法返回一个关于被测量文本TextMetrics 对象包含的信息(例如它的宽度)。

我们这边基本只使用返回对象的宽度:

ts 复制代码
    //draw centered text
    c.fillStyle = "black";
    c.font = "24pt sans-serif";
    var text = "Sales Data from 2025";
    var metrics = c.measureText(text);
    c.fillText(text, 250 - metrics.width / 2, 400);

我们可以看到fillText这里我们的第二个参数,也就x的位置设置为了250 - metrics.width,这是类似于left: 50%; transform: trnaslateX(-50%)一样的效果,主要是为了实现居中。

实现效果:

相关推荐
若川44 分钟前
Taro 源码揭秘:10. Taro 到底是怎样转换成小程序文件的?
前端·javascript·react.js
IT女孩儿1 小时前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js
真的很上进10 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
噢,我明白了14 小时前
同源策略:为什么XMLHttpRequest不能跨域请求资源?
javascript·跨域
sanguine__14 小时前
APIs-day2
javascript·css·css3
关你西红柿子14 小时前
小程序app封装公用顶部筛选区uv-drop-down
前端·javascript·vue.js·小程序·uv
济南小草根14 小时前
把一个Vue项目的页面打包后再另一个项目中使用
前端·javascript·vue.js
小木_.15 小时前
【python 逆向分析某有道翻译】分析有道翻译公开的密文内容,webpack类型,全程扣代码,最后实现接口调用翻译,仅供学习参考
javascript·python·学习·webpack·分享·逆向分析
Aphasia31115 小时前
一次搞懂 JS 对象转换,从此告别类型错误!
javascript·面试