介绍

首先canvas是html5的一种新标签,代表一个画布,可以在上面进行绘画、动画等操作。画布默认大小是300*150。
canvas标签本生就是一个只是画布,可以导出为透明背景的png图片。要实现上面有文字、线条等呈现,需要使用js实现。总之,画布上一切的呈现,都需要使用js来实现。
画布大小不能使用样式控制,用样式调整的是一个可视区域,其实真实的大小,还是一样的,只是在画布上画内容的话,会等比例放大。调整画布大小,需要在标签上直接添加width和height属性。
canvas标签也是可以放文字的,只是当canvas标签不被浏览器支持的时候,会显示,例如ie8。

基本使用

  1. 获取canvas元素

    var canvas = document.querySelector('canvas')
    
  2. 获取这个元素的工具箱 - 上下文

    工具箱中包含了很多工具:直线工具、弧形工具、文本工具、矩形工具… 我们需要依赖这些工具进行绘画

    语法:

    var ctx = canvas.getContext('2d')
    
  3. 画图形

    默认情况下,canvas选中的工具是直线工具,要画一条直线的话,需要先将画笔放到一个指定像素点

    ctx.moveTo(x轴坐标,y轴坐标)
    

    然后以线的形式,将画笔移动到终点:

    ctx.lineTo(200,100)
    

    此时应该已经有线了,但是页面中并没有出现,因为我们前面两个步骤描述的是画笔走的路径,这个路径需要进行填充:

    ctx.fill
    

    也可以进行描边:

    ctx.strock()
    

    默认是黑色,线的宽度是1px
    此时在画布中出现了一条线,但是发现线的粗细不是1px,颜色也不是黑色。这是因为,canvas绘制线条,会将线条的中心点跟坐标点的位置进行对齐,这样的话,不管是线的开始对准坐标点还是线的结束对准中心点都不合适,所以浏览器干脆将线强行拉伸到 坐标点-1~坐标点+1,也就是本来1px的线,被强制拉伸到了2px,这样的话,颜色也就浅了。

我们可以将线的宽度设置为2px做验证,因为2px就不用被拉伸了:

ctx.lineWith = 2 // 值是数字
ctx.lineTo(200,100)
//结果就是2px宽的线,纯黑色了。基于这个问题,我们以后在绘图的时候,尽量将像素设置为双数。

1 :简单封装的一个折线图

html和css

<html>
<head>
<meta charset="UTF-8">
<title>document</title>
</head>
<style>
canvas{border:1px solid #000;
}
</style>
<body>
<canvas class="linechart" width=600 height=300></canvas>
</body>

javascript封装的源码

// 定义一个类
class LineChart{constructor(classname,data){// 画布标签获取到this.canvas = document.querySelector('.'+classname)// 工具箱this.ctx = this.canvas.getContext('2d')// 定义画布大小this.canvasWidth = this.ctx.canvas.widththis.canvasHeight = this.ctx.canvas.height// 定义坐标轴到画布边缘的间隙this.space = 20// 定义原点this.originX = 0this.originY = 0// 定义箭头三角形的高 和 点 的长度this.length = 10// 将数据绑定成类的属性this.data = data// 定义画布中的数据this.canvasData = null;}// 定义一个初始化方法init(){// 获取原点this.getOrigin()// 创建坐标轴 - x、ythis.createAxisX()this.createAxisY()// 转换数据this.convert(this.data)// 描每个点// this.setPoint(data)// 描所有点this.setPoints(this.canvasData)// 连线this.connectLine(this.canvasData)}connectLine(data){for(let i=0;i<data.length-1;i++){this.ctx.beginPath()// 放画笔this.ctx.moveTo(data[i].x,data[i].y)// 画线this.ctx.lineTo(data[i+1].x,data[i+1].y)this.ctx.closePath()this.ctx.stroke()}}// 描所有点的方法setPoints(data){data.forEach(point=>{this.setPoint(point)})}// 描一个点的方法setPoint(data){this.ctx.beginPath()// 放画笔位置this.ctx.moveTo(data.x-this.length/2,data.y-this.length/2)// 画线this.ctx.lineTo(data.x+this.length/2,data.y-this.length/2)this.ctx.lineTo(data.x+this.length/2,data.y+this.length/2)this.ctx.lineTo(data.x-this.length/2,data.y+this.length/2)this.ctx.lineTo(data.x-this.length/2,data.y-this.length/2)this.ctx.closePath()this.ctx.stroke()this.ctx.fill()}// 转换数据的方法convert(){// 将坐标轴的数据转成画布的数据// 遍历数据this.canvasData = this.data.map(point=>{return {x:point.x+this.space,y:this.canvasHeight - this.space - point.y}})}// 创建y轴createAxisY(){this.ctx.beginPath()// 将画笔放到原点this.ctx.moveTo(this.originX,this.originY)// 画线this.ctx.lineTo(this.originX,this.space)// 画箭头this.ctx.lineTo(this.originX-this.length/2,this.space + this.length)this.ctx.lineTo(this.originX+this.length/2,this.space + this.length)this.ctx.lineTo(this.originX,this.space)this.ctx.closePath()this.ctx.stroke()this.ctx.fill()}// 获取原点的方法getOrigin(){this.originX = this.space;this.originY = this.canvasHeight - this.space}// 定义创建x坐标轴的方法createAxisX(){this.ctx.beginPath()// 将画笔放到原点this.ctx.moveTo(this.originX,this.originY)// 画线this.ctx.lineTo(this.canvasWidth - this.space,this.originY)// 画箭头this.ctx.lineTo(this.canvasWidth-this.space-this.length,this.originY-this.length/2)this.ctx.lineTo(this.canvasWidth-this.space-this.length,this.originY+this.length/2)this.ctx.lineTo(this.canvasWidth - this.space,this.originY)this.ctx.closePath()this.ctx.stroke()this.ctx.fill()}
}

调用方法

var lc = new LineChart('linechart',[{x:0,           //写入每个坐标点的位置y:0},{x:100,y:100},{x:200,y:120},{x:300,y:220},{x:400,y:150},])
lc.init()

效果

是不是简陋了点,现在封装一个好看点的饼图

Demo2:封装一个圆饼图

html和css

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>document</title>
</head>
<body>
<style>canvas{border:1px solid #000}
</style>
<canvas width=900 height=500 class="pie"></canvas>
</body>

javascript封装的源码

class Pie{constructor(classname,data){// 将数据绑定在属性上this.data = data// 获取canvas节点this.canvas = document.querySelector('.'+classname)// 获取工具箱this.ctx = this.canvas.getContext('2d');// 定义圆心this.x = this.ctx.canvas.width / 2 + 200;this.y = this.ctx.canvas.height / 2;// 定义半径this.r = 150// 定义延伸线的长度this.R = this.r + 40// 定义数据总量this.total = this.data.reduce((a,b)=>{if(typeof a === 'number'){return a + b.num}else{return this.data[0].num + b.num}})}// 初始化方法init(){// 数据处理方法this.convertData()// 画饼的方法this.drawPie()}// 数据处理方法convertData(){this.data.forEach(v=>{v.arc = v.num/this.total*2 * Math.PI})}// 画饼的方法drawPie(){// 初始弧度var startArc = 0this.data.forEach((v,index)=>{this.ctx.beginPath()this.ctx.moveTo(this.x,this.y)var endArc = startArc + v.arcthis.ctx.arc(this.x,this.y,this.r,startArc,endArc)startArc = endArcvar color = this.getColor()this.ctx.fillStyle = colorthis.ctx.fill()// 画延伸线this.outLine(v.arc,endArc,color,v.title)// 画说明方块this.descSquare(index)})}// 画说明方块的方法descSquare(index){var squareWidth = 50;var squareHeight = 30;var squareLeft = 20;var squareTop = 20// 画小方块this.ctx.fillRect(squareLeft,squareTop*(index+1)+squareHeight*index,squareWidth,squareHeight)// 计算文字的开始坐标var textX = squareLeft + squareWidth + squareLeftvar textY = squareTop*(index+1)+squareHeight*index+squareHeight/2this.ctx.textBaseline = 'middle';this.ctx.textAlign = 'left';var percent = (this.data[index].num / this.total).toFixed(2) * 100 + '%'this.ctx.fillText(this.data[index].title+'   ' + percent,textX,textY)}// 画延伸线的方法outLine(currentArc,endArc,color,title){// 获取到需要画线的这个弧度var arc = endArc - currentArc/2// 计算这条线的终点x和yvar endX = Math.cos(arc) * this.R + this.xvar endY = Math.sin(arc) * this.R + this.ythis.ctx.moveTo(this.x,this.y)this.ctx.lineTo(endX,endY)this.ctx.strokeStyle = color// 获取文字长度this.ctx.font = '16px 楷体'var textWidth = this.ctx.measureText(title).widthif(endX<this.x){var textX = endX - textWidththis.ctx.textAlign = 'left';}else{var textX = endX + textWidththis.ctx.textAlign = 'right';}this.ctx.textBaseline = 'bottom';this.ctx.lineTo(textX,endY)// 写字this.ctx.strokeText(title,textX,endY-3)this.ctx.stroke()}// 获取随机颜色的方法getColor(){return `rgb(${Math.floor(Math.random()*256)},${Math.floor(Math.random()*256)},${Math.floor(Math.random()*256)})`}}

调用方法

var data = [{title:"15 ~ 20 岁",num:20},{title:"20 ~ 25 岁",num:15},{title:"25 ~ 30 岁",num:10},{title:"30 ~ 35 岁",num:35},{title:"35 ~ 40 岁",num:12},{title:"40 ~ 45 岁",num:25},{title:"45 ~ 50 岁",num:30},{title:"50 ~ 55 岁",num:35},{title:"55 ~ 60 岁",num:50}
];var pie = new Pie('pie',data)
pie.init()

效果图

额外想说的

首先我知道。真实工作中用E-charts做统计图表的多,但是原生canvas的练习对开发能力的增长和基础的锻炼是很有用的,尤其是刚接触前端刚学习js不久的小白们
现在附上E-charts的使用

首先通过cdn或者npm

cnpm i --save echarts

接下来引入js文件

<script src="./node_modules/echarts/dist/echarts.min.js"></script>

初始化实例化Echarts对象

var myChart = echarts.init(document.getElementById('main'));

指定图表的配置项和数据

 var option = {tooltip: {trigger: "axis",showDelay: 0,axisPointer: {type: "cross",lineStyle: {type: "dashed",width: 1}}},legend: {data: ["scatter1", "scatter2"]},toolbox: {show: true,feature: {mark: {show: true},dataZoom: {show: true},dataView: {show: true,readOnly: true},restore: {show: true},saveAsImage: {show: true}}},xAxis: [{type: "value",power: 1,splitNumber: 4,scale: true}],yAxis: [{type: "value",power: 1,splitNumber: 4,scale: true}],series: [{name: "scatter1",type: "scatter",symbol: "circle",data: [[-69, 58, 70], [10, 74, 29], [-11, 68, 99], [10, 76, 53], [-79, -9, 93], [-81, -67, 56], [-95, -71, 50], [-7, 22, 5], [-57, -67, 73], [16, 58, 73], [-65, 30, 56], [4, -75, 3], [-65, 92, 98], [30, -65, 29], [-11, -37, 59], [48, -31, 89], [-39, -51, 23], [-21, -37, 23], [24, -11, 38], [90, -19, 79], [-61, -11, 98], [-23, -83, 75], [-39, 58, 25], [-93, -65, 24], [60, -17, 22], [54, 88, 27], [-29, 76, 76], [-45, 32, 89], [-69, 58, 63], [90, 34, 33], [-41, -5, 91], [58, -33, 77], [-79, -83, 69], [-99, -43, 80], [44, 8, 0], [-81, -19, 74], [-13, 40, 84], [60, -67, 82], [16, 14, 59], [-37, 36, 93], [0, 54, 23], [-61, 44, 26], [32, 60, 10], [90, 20, 21], [20, -91, 53], [32, -87, 73], [-85, 90, 74], [72, -1, 95], [-67, -59, 87], [-21, -29, 60]],symbolSize: function anonymous(value/*``*/) {var radius = (value[2] - 0) * 16 / 100 + 4;return Math.max(Math.round(radius), 1) || 1;}},{name: "scatter2",type: "scatter",symbol: "circle",data: [[76, 72, 50], [-67, 70, 52], [26, 20, 71], [-57, -63, 93], [-19, -49, 78], [46, 28, 71], [-87, -97, 7], [-81, -59, 71], [32, 28, 49], [68, 88, 73], [20, -47, 46], [-61, 18, 89], [-89, -3, 92], [-19, -27, 43], [-55, -67, 18], [-79, 52, 92], [14, 16, 61], [-19, -1, 97], [-93, -67, 81], [-63, 14, 4], [-87, -37, 92], [24, 96, 82]],symbolSize: function anonymous(value/*``*/) {var radius = (value[2] - 0) * 16 / 100 + 4;return Math.max(Math.round(radius), 1) || 1;}}]}

使用刚指定的配置项和数据显示图表。

 myChart.setOption(option);

效果图

原生CANVAS语法实现的封装折线图和饼图相关推荐

  1. java使用poi在word中生成柱状图、折线图、饼图、柱状图+折线图组合图、动态表格、文本替换、图片替换、更新内置Excel数据、更新插入的文本框内容、合并表格单元格;

    本文参考地址:https://blog.csdn.net/wangxiaoyingWXY/article/details/95377533 在参考文章的基础上,增加了扩展.感谢被参考的妹子.另外该博客 ...

  2. java使用poi在word中生成柱状图、折线图、饼图、柱状图+折线图组合图、动态表格、文本替换、图片替换 springboot项目

    本文参考地址:https://blog.csdn.net/u014427811/article/details/100771314 在参考文章的基础上,增加了模板样例 模板样例地址 百度网盘 链接:h ...

  3. vue中使用ECharts实现折线图和饼图

    在开发后台管理项目时,需要统计后台用户数据,以折线图和饼图的形式显示,这边采用apache-echarts来实现需求. 1.安装echarts和引入 npm install echarts --sav ...

  4. Tableau画条形图、直方图、折线图、饼图、环形图、箱线图

    Tableau画条形图.直方图.折线图.饼图.环形图.箱线图.雷达图 一.条形图 第一步,打开"豆瓣电影数据.xlsx": 第二步,画各国家电影评分直方图.选择"产地&q ...

  5. 安卓图表引擎AChartEngine(三) - 示例源码折线图、饼图和柱状图

    折线图: package org.achartengine.chartdemo.demo.chart;import java.util.ArrayList; import java.util.List ...

  6. itextpdf 添加折线图、饼图、柱状图

    itextpdf 添加折线图.饼图.柱状图 时隔三年,又要对PDF一顿改版了,此次改版加入了饼图.折线图.柱状图等图形可视化. 文章目录 itextpdf 添加折线图.饼图.柱状图 依赖包 效果图 步 ...

  7. 【Echart多场景示例应用】Echarts柱状图、折线图、饼图、雷达图等完整示例。 echarts主标题和副标题的位置、样式等设置(已解决附源码)

    **[写在前面]**前端时间做一个echarts的页面调整,临时客户要求加一个参数(总容量)显示,当时我就想用个默认的副标题吧,哪知客户和我说得紧跟在主标题后面,于是乎我就根据设置做了一个调整,我也是 ...

  8. 【GraphMaker】Unity3D图表——柱状图、折线图、饼图

    http://blog.csdn.net/yongh701/article/details/71637090?utm_source=itdadao&utm_medium=referral 版权 ...

  9. java使用poi在word模板中替换柱状图、折线图、饼图、表格、文本、图片

    介绍 java使用poi在word模板中替换柱状图.折线图.饼图.表格.文本.图片 软件架构 安装教程 环境搭建:jdk1.8.0_291.maven1.8.0_291 IDEA工具:IntelliJ ...

最新文章

  1. oracle.com.cn宕机于09-11-13 20:21
  2. 友情链接交换看的不是“真友情”!
  3. 利用gulp处理简单的前端问题
  4. Redis事务(transaction)
  5. divmod数字处理函数
  6. php不判断比较大小,php怎么不分大小比较字符串
  7. fiddler2抓包数据工具使用教程
  8. Linux性能测试分析命令_sar
  9. 5G 已来,是否意味着 4G 淘汰?
  10. android 点滴积累
  11. 难道是我洞悉了CSDN网站订阅专栏收益的秘密?带你看看网站专栏一天营收几何?
  12. 计算机二级excel试题练习网盘,计算机二级练习试题excel
  13. 小榕密码管家xp 绿色
  14. python 通信调制方式_python实现BPSK调制信号解调
  15. android 圆形自定义进度条,Android自定义漂亮的圆形进度条
  16. matlab ttest空值,用MATLAB做T检验(ttest)
  17. android程序图标透明,怎么把android手机软件图标变透明
  18. Matlab顶级期刊配色工具Rggsci
  19. 关于在线评论有用性的论文研读笔记---51-60篇
  20. 【板栗糖GIS】如何免费下载landsat8的遥感影像数据

热门文章

  1. UDP 打洞 java demo
  2. 企业级硬盘产品这么多,到底该选哪一个?
  3. 淘宝客商品 获取详情图片
  4. 项目式51单片机c语言题库,《单片机C语言项目式教程》选择题含答案.doc
  5. android 竖屏拍照旋转90度,三星等机型上拍照后图片被旋转90度的解决方案
  6. andy the android ppt,剑桥国际少儿英语KB1Unit课件.ppt
  7. 西北大学计算机学院考博真题,2016年西北大学考博英语真题
  8. Django+bootstrap+注册登录系统
  9. 可以嵌入ppt的课堂点名器_智慧校园--嵌入式高清全自动录播子系统
  10. 老头怎么打边惩程咬金?