画扇形的方法

方法一:起始角度是0,那么第一条线就是line(r,0),通过旋转扇形的角度,第二条线就是line(r,0)

//圆弧
ctx.save();
ctx.translate(100, 100);
ctx.arc(0,0,100,0, 30*Math.PI/180);
ctx.restore();
//第一条线
ctx.save();
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.restore();
//第二条线
ctx.save();
ctx.translate(100, 100);
ctx.moveTo(0,0);
ctx.rotate(30*Math.PI/180);
ctx.lineTo(100,0);
ctx.stroke();
ctx.restore();

第一步为什么是设置原点呢,为什么不用moveTo来设置起始点呢?

  因为画布的默认原点在0,0的位置上,如果用moveTo来设置起始点,原点依然还在0,0的位置,而变换是以原点为基准点的,即使你设置了起始点,但是起始点不是原点的话,图形旋转依然会围绕0,0点旋转然后自转,得到的图形就不知道是什么图形了。

方法二

//将原点设置100,100位置
ctx.translate(100,100);
//原点在100,100,则圆心设为0,0 ——> 100,100的位置
ctx.arc(0,0,100,30*Math.PI/180,60*Math.PI/180);
//save(),restore()是为了防止角度旋转的污染
ctx.save();
ctx.rotate(30*Math.PI/180);
ctx.moveTo(0,0);
ctx.lineTo(100,0);
ctx.restore();
ctx.rotate(60*Math.PI/180);
ctx.moveTo(0,0);
ctx.lineTo(100,0);
ctx.stroke();

关于save()和restore():

  其作用不只是可以防止外面的属性或方法对里面的绘制产生影响,它的本质意思是save()保存当前环境的状态,restore()返回之前保存路径的状态。在这里要注意还原的触点在什么地方,如下例子:

 //将原点设置100,100位置
ctx.translate(100,100);
//原点在100,100,则圆心设为0,0 ——> 100,100的位置
ctx.arc(0,0,100,30*Math.PI/180,60*Math.PI/180);
//save(),restore()是为了防止角度旋转的污染
ctx.save();
ctx.rotate(30*Math.PI/180);
ctx.moveTo(0,0);
ctx.lineTo(100,0);
ctx.restore();
ctx.rotate(60*Math.PI/180);
ctx.lineTo(100,0);
ctx.stroke();

跟上面的代码比就是少了12行的moveTo(0,0),结果如下图1:

原因是:线在旋转的时候,是从它的起点为圆心旋转的,而上面的代码是,第一条线从圆心开始,到圆弧的起点(旋转过后),自然现在的起点就是圆弧的起点了,然后再rotate(60*Math.PI/180);lineTo(100,0);就是从圆弧的起点画到(100,0)的线了

现在我们将第一条直线的起点设在(r,0)的位置,旋转后就到了圆弧的起始点,然后在画到圆心地方,那现在的起始点就是圆心了,再画一条线到圆弧,就可以了,如下:

//将原点设置100,100位置
ctx.translate(100,100);
//原点在100,100,则圆心设为0,0 ——> 100,100的位置
ctx.arc(0,0,100,30*Math.PI/180,60*Math.PI/180);
//save(),restore()是为了防止角度旋转的污染
ctx.save();
ctx.rotate(30*Math.PI/180);
ctx.moveTo(100,0);
ctx.lineTo(0,0);
ctx.restore();
ctx.rotate(60*Math.PI/180);
ctx.lineTo(100,0);
ctx.stroke();

 方法三:充分使用触点的作用,当我们再画圆弧的时候,画完之后其触点在圆弧的结束位置,为何不直接将这个触点作为起点,画一条到圆心的线,然后再画第二条线。如下代码:

//将原点设置100,100位置
ctx.translate(100,100);
//原点在100,100,则圆心设为0,0 ——> 100,100的位置
ctx.arc(0,0,100,30*Math.PI/180,60*Math.PI/180);
//以圆弧终点为起点画直线,rotate使得直角坐标系旋转了30°
ctx.lineTo(0,0);
ctx.rotate(30*Math.PI/180);
//以0,0为起点画直线
ctx.lineTo(100,0);
ctx.stroke();

方法四:配合beginPath()和closePath()

为什么要用translate,而不要moveTo,是因为如果需要旋转,所以就需要原点,现在不需要旋转,而是正常的画图,那么就不需要原点,就可以用moveTo。

配合beginPath()和closePath(),就会将一个圆弧封闭起来。

ctx.beginPath();
//定义起点
ctx.moveTo(100,100);
//以起点为圆心,画一个半径为100的圆弧
ctx.arc(100,100,100,30*Math.PI/180, 60*Math.PI/180);
ctx.closePath();
ctx.stroke();

 特别注意:

  • 使用arc()绘制图形时,如果没有设置moveTo(),那么会从圆弧的开始的点作为起始点。如果设置了moveTo(),那么该点会连线到圆弧起始点。
  • 如果使用stroke()方法,那么会从开始连线到圆弧的起始位置。 如果是 fill 方法, 会自动闭合路径填充

封装函数

CanvasRenderingContext2D.prototype.sector = function(x,y,r,angle1,angle2){
this.save();
this.beginPath();
this.moveTo(x,y);
this.arc(x,y,r,angle1*Math.PI/180,angle2*Math.PI/180,false);
this.closePath();
this.restore();
return this;
}
ctx.fillStyle = 'red';
ctx.sector(200,200,100,30,150).fill();
ctx.fillStyle = 'green';
ctx.sector(200,200,100,150,270).fill();
ctx.fillStyle = 'blue';
ctx.sector(200,200,100,270,390).fill();

画饼图

思路:

1)将每块饼的占比以整数形式储存在数组nums中,将每个饼的颜色以字符串形式储存在数组colors中,两个数组的值一一对应。将画布旋转坐标定义在即将绘制圆的中心,定义绘制圆弧(饼)的起始角度start和终止角度end均为0

2)绘制圆饼,6个不同板块,所以有6次for循环,从绘制第二个饼开始,起始角度是在上一个饼的终止角度位置,因此,每次循环开始后,要对当前的终止角度end进行累加一次,绘制圆弧直接以start开始,以end结束,当前绘制完成之后,要对起始角度start完成一次累加;同时每次绘制都给板块填充对应的颜色。封装为函数pieChart();

3)绘制圆饼对应的占比数值,也是6次for循环,为了便于代码易读,这里重新定义了一个函数。并对起始角度start和终止角度end重新利用,nums中储存的是当前数值占100的份数,将其转化为对应角度为nums[i]/50*Math.PI;让其显示在板块角度中线位置nums[i]/50*Math.PI/2;同样每次循环起始角度是在上一个饼的终止角度位置,绘制前后也要进行累加。封装为函数pieNum();

<canvas id="can1" width="800" height="600"></canvas>
<script type="text/javascript">
var can1 = document.getElementById("can1");
var ctx = can1.getContext("2d");
var nums = [26,15,12,5,25,17];
var colors = ["#983335","#77963f","#5d437c","#35859f","#d1702f","#365e96"];
var start = 0;
var end = 0;
ctx.translate(400,350);
//绘制圆饼
function pieChart(){
for (var i = 0;i < nums.length; i ++){
ctx.beginPath();
ctx.moveTo(0,0);
end += nums[i]/50*Math.PI;//终止角度
ctx.strokeStyle = "white";
ctx.fillStyle = colors[i];
ctx.arc(0,0,200,start,end);
ctx.fill();
ctx.closePath();
ctx.stroke();
start += nums[i]/50*Math.PI;//起始角度
}
}
//绘制圆饼上的数值
function pieNum(){
for (var i = 0;i < nums.length; i ++){
start = nums[i]/50*Math.PI/2;
ctx.rotate(end+start);//旋转数值
ctx.font = "25px scans-serif";
ctx.fillStyle = "#000";
ctx.fillText(nums[i]+"%",140,0);
end = nums[i]/50*Math.PI/2;
}
}
ctx.rotate(-Math.PI/6);//旋转一定角度更加自然
pieChart();
pieNum();
</script>

canvas画扇形、饼图的更多相关文章

  1. canvas画扇形图(本文来自于http://jo2.org/html5-canvas-sector/)

    1.定义画扇形的构造函数: //扇形CanvasRenderingContext2D.prototype.sector = function (x, y, radius, sDeg, eDeg) {/ ...

  2. canvas画饼图

    <style> body {    background: black;    text-align: center; } #cans {    background: white; } ...

  3. Android利用canvas画各种图形(点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形) .

    1.首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, ...

  4. Android利用canvas画各种图形 及Paint用法 .

    引自:http://blog.csdn.net/carlfan/article/details/8139984 1.首先说一下canvas类: Class Overview The Canvas cl ...

  5. canvas图表(3) - 饼图

    原文地址:canvas图表(3) - 饼图 这几天把canvas图表都优化了下,动画效果更加出色了,可以说很逼近echart了.刚刚写完的饼图,非常好的实现了既定的功能,交互的动画效果也是很棒的. 效 ...

  6. 关于设备与canvas画不出来的解决办法

    连续四天解决一个在三星手机上面画canvas的倒计时饼图不出来的问题,困惑了很久,用了很多办法,甚至重写了那个方法,还是没有解决,大神给的思路是给父级加 "overflow: visible ...

  7. Android利用canvas画各种图形

    Android利用canvas画各种图形(点.直线.弧.圆.椭圆.文字.矩形.多边形.曲线.圆角矩形) 本文链接:https://blog.csdn.net/rhljiayou/article/det ...

  8. 使用javascript和canvas画月半弯

    使用javascript和canvas画月半弯,月半弯好浪漫!浏览器须支持html5 查看效果:http://keleyi.com/a/bjad/8xqdm0r2.htm 以下是代码: <!do ...

  9. canvas 画圈 demo

    html代码: <canvas id="clickCanvas2"  width="180" height="180" data-to ...

随机推荐

  1. js中的文本编辑器控件KindEditor

    使用文本编辑器控件KindEditor渲染文本域页面显示 this.sync()同步KindEditor的值到textarea文本框 editor.isEmpty()判断文本域是否是空 editer. ...

  2. C语言随笔2: rom ram 及其运行的过程

    内存的分配方式 五个区 :堆区.栈区.全局区.文字常量区.程序代码区 这五个区是ram中的.或者说,堆栈段.数据段.代码段 而rom中,没有堆区和栈区,只有数据段和代码段. ram是在程序运行是的内存 ...

  3. National Contest for Private Universities (NCPU), 2019 C Boxes(双向链表)

    题目中的要求如果x在y的左边,不需要移动,x在y的右边,2操作不需要移动. 有一个问题是,如果x与y相邻,这时的swap操作变成了三个而不是四个,这点尤其需要注意,不然就会死循环.注意x是和y相邻,这 ...

  4. 【PAT甲级】1079 Total Sales of Supply Chain (25 分)

    题意: 输入一个正整数N(<=1e5),表示共有N个结点,接着输入两个浮点数分别表示商品的进货价和每经过一层会增加的价格百分比.接着输入N行每行包括一个非负整数X,如果X为0则表明该结点为叶子结 ...

  5. 【CSS属性#2】

    " 目录 一.盒子模型 二.外边距 margin 三.内填充 padding 四.浮动 float 五.清除浮动 clear 六.溢出 overflow 七.定位 position 1. 无 ...

  6. 基于SILVACO ATLAS的a-IGZO薄膜晶体管二维器件仿真(08)

    进展比较慢啊... 根据江南大学硕士论文IGZO/IZO双有源层薄膜晶体管特性的模拟研究: 其中, gCBa:类受主导带尾态 gVBd:类施主价带尾态 gGd:类施主氧空位态 NDeep:价带尾深施主 ...

  7. SQLite3介绍

    一.SQLite数据库简介 SQLite 是一个软件库,实现了自给自足的.无服务器的.零配置的.事务性的 SQL 数据库引擎.SQLite 是在世界上最广泛部署的 SQL 数据库引擎. DDL - 数 ...

  8. VMware15下载、安装、激活

    1.VMware15下载 链接:https://pan.baidu.com/s/1bI8LReRY-5k81O3rrNgg-A  提取码:6c03 2.VMware15安装 3.VMware15激活

  9. 惠普笔记本,如何选择U盘启动

    开机先连续点击键盘F9按键进入选择启动盘界面,找到自己的U盘(KingstonDataTraveler G3)

  10. Java后台技术(线程安全)

    前端时间一个同事因为后台线程安全问题出了一次生产事故,今天我就对线程安全问题进行一次总结. 首先,我们来大致看以下我同事写的代码,代码我进行了精简,大致如下: for (final String re ...