内容简介:canvas是html5很受欢迎的新特性,它给我们提供了一个我们在使用canvas的时候,可以想象自己动手作一幅画。
canvas介绍
canvas是html5很受欢迎的新特性,它给我们提供了一个 图像容器 ,让我门可以使用脚本javascript来在这个容器上完成对图像的绘制。
canvas基础
我们在使用canvas的时候,可以想象自己动手作一幅画。
- 当你作画的时候,你需要一张可以在上面作画的纸,并决定使用多大的纸张(画布尺寸)。 注意:不要在style里面直接选择
canvas
设置宽高,会导致画布失真。
<canvas width="600",height="400"></canvas>
- 其次你得选中这张纸,选中作图工具,才能开始作画
/*获取元素*/ var myCanvas = document.querySelector('#myCanvas'); /*获取绘图工具*/ var ctx = myCanvas.getContext('2d'); 复制代码
- 最后开始作画,作画之前,我们要基于坐标点来控制每一个像素,所以,首先我们需要知道Canvas的坐标系是如何分布的。
有了以上的知识点以后,我们正式开始使用canvas来绘制图片。
1.先简单的绘制一条直线 分为以下三步
/*设置绘图的起始位置*/ ctx.moveTo(100,100); /*绘制路径*/ ctx.lineTo(200,200); /*描边*/ ctx.stroke();复制代码
2.接下来,我们绘制平行线
/*画平行线*/ ctx.moveTo(100,100.5); ctx.lineTo(300,100.5); ctx.moveTo(100,200); ctx.lineTo(300,200); /*描边*/ ctx.stroke();复制代码
总结一下,绘制线条时候遇到的问题
- 默认的宽度: 1px
- 默认的颜色: 黑色
- 线条会出现模糊的情况
- 产生原因 :对齐的点是线的中心位置 会把线分成两个0.5px 显示的是会不饱和增加宽度
- 解决方案 :前后移动0.5px
3.绘制不同颜色的平行线
ctx.moveTo(100,100); ctx.lineTo(300,100); ctx.strokeStyle = 'blue'; ctx.lineWidth = 10; /*描边*/ ctx.stroke(); /*红色 20px*/ ctx.moveTo(100,200); ctx.lineTo(300,200); ctx.strokeStyle = 'red'; ctx.lineWidth = 20; /*描边*/ ctx.stroke(); /*粉色 30px*/ ctx.moveTo(100,300); ctx.lineTo(300,300); ctx.strokeStyle = 'pink'; ctx.lineWidth = 30; /*描边*/ ctx.stroke(); 复制代码
如果直接用以上的代码去画图,最终三条线都会显示最后一条线的颜色,原因是因为最后的 ctx.strokeStyle
会覆盖之前定义的颜色。
解决方案:在每个线条绘制前重新开辟一条路径: ctx.beginPath()
ctx.beginPath(); ctx.moveTo(100,100); ctx.lineTo(300,100); ctx.strokeStyle = 'blue'; ctx.lineWidth = 10; /*描边*/ ctx.stroke(); /*红色 20px*/ ctx.beginPath(); ctx.moveTo(100,200); ctx.lineTo(300,200); ctx.strokeStyle = 'red'; ctx.lineWidth = 20; /*描边*/ ctx.stroke(); /*粉色 30px*/ ctx.beginPath(); ctx.moveTo(100,300); ctx.lineTo(300,300); ctx.strokeStyle = 'pink'; ctx.lineWidth = 30; /*描边*/ ctx.stroke(); 复制代码
4.绘制一个三角形
/*1.绘制一个三角形*/ ctx.moveTo(100,100); ctx.lineTo(200,100); ctx.lineTo(200,200); ctx.linnTo(100,100); ctx.stroke()复制代码
绘制的三角形,会发现无法闭合,这是因为绘图都是以线条的中心点为交点,所以导致无法闭合,此时,我们需要让线条自动闭合.
/*1.绘制一个三角形*/ ctx.moveTo(100,100); ctx.lineTo(200,100); ctx.lineTo(200,200); /*使用canvas的自动闭合 */ //ctx.lineTo(100,100); /*关闭路径*/ ctx.closePath(); ctx.lineWidth = 10; /*2.描边*/ ctx.stroke(); /*3.填充*/ //ctx.fill();复制代码
注意:ctx.closePath()和ctx.beginPath()并没有半毛钱关系,它也不是关闭路径,而是使路径下的图像闭合无缺角
5.填充规则说明
上面代码我们用到了ctx.fill(),对于填充,会有一个非零环绕规则
简单来说,从闭合的区域内,拉出一条向外的射线,尽量使期相交的线的数量少,方便判断。每与一根线相交,如果方向是顺时针则+1,如果是逆时针则-1.最后如果得出是0,则改位置便不填充
6.绘制一个渐变色的矩形
/*线是由点构成的*/ ctx.lineWidth = 30; for (var i = 0; i < 255; i++) { ctx.beginPath(); ctx.moveTo(100+i-1,100); ctx.lineTo(100+i,100); ctx.strokeStyle = 'rgb('+i+',0,0)'; ctx.stroke(); }复制代码
原理:使每一个像素点的颜色发生渐变,最后得出一个渐变的矩形
案例:绘制一个折线图
要求:根据数据,绘制折线图,即达到数据可视化的效果。
思路:
- 制作一张网格
- 制作坐标轴
- 根据数据,制作坐标点
- 连接坐标点
第一步:制作一个网格
- 定义网格的大小
- 根据网格的大小决定x轴方向有多少条线,y轴一样。
var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.绘制网格*/ /*2.网格的大小*/ var gridSize = 10; var canvasHeight = ctx.canvas.height; var canvasWidth = ctx.canvas.width; /*3.画多少条X轴方向的线 横线的条数 画布高度*/ var xLineTotal = Math.floor(canvasHeight / gridSize); for (var i = 0; i <= xLineTotal; i++) { ctx.beginPath(); ctx.moveTo(0, i * gridSize - 0.5 ); ctx.lineTo(canvasWidth, i * gridSize - 0.5); ctx.strokeStyle = '#eee'; ctx.stroke(); } /*4.画多少条Y轴方向的线*/ var yLineTotal = Math.floor(canvasWidth / gridSize); for (var i = 0; i <= yLineTotal; i++) { ctx.beginPath(); ctx.moveTo(i*gridSize - 0.5 ,0); ctx.lineTo(i*gridSize - 0.5 ,canvasHeight); ctx.strokeStyle = '#eee'; ctx.stroke(); }复制代码
第二步:制作一个坐标系
- 确定原点的位置
- 确定坐标轴的长度
- 确定箭头的位置,大小
var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.绘制坐标系*/ /*2.确定原点*/ /*3.确定距离画布旁边的距离*/ /*4.确定坐标轴的长度*/ /*5.确定箭头的大小 是个等腰三角形 10 */ /*6.绘制箭头填充*/ var space = 20; var arrowSize = 10; /*计算原点*/ var canvasWidth = ctx.canvas.width; var canvasHeight = ctx.canvas.height; var x0 = space; var y0 = canvasHeight - space; /*绘制x轴*/ ctx.beginPath(); ctx.moveTo(x0, y0); ctx.lineTo(canvasWidth - space, y0); /*x轴箭头*/ ctx.lineTo(canvasWidth - space - arrowSize, y0 + arrowSize / 2); ctx.lineTo(canvasWidth - space - arrowSize, y0 - arrowSize / 2); ctx.lineTo(canvasWidth - space, y0); ctx.fill(); ctx.stroke(); /*绘制y轴*/ ctx.beginPath(); ctx.moveTo(x0, y0); ctx.lineTo(space, space); /*y轴箭头*/ ctx.lineTo(space + arrowSize / 2, space + arrowSize); ctx.lineTo(space - arrowSize / 2, space + arrowSize); ctx.lineTo(space, space); ctx.fill(); ctx.stroke();复制代码
第三步:绘制坐标点
- 绘制点,点的尺寸,以及要以坐标原点为中心绘制
var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*点坐标*/ var coordinate = { x:100, y:100 } /*点尺寸*/ var dottedSize = 10; ctx.moveTo(coordinate.x - dottedSize / 2,coordinate.y - dottedSize / 2); ctx.lineTo(coordinate.x + dottedSize / 2,coordinate.y - dottedSize / 2); ctx.lineTo(coordinate.x + dottedSize / 2,coordinate.y + dottedSize / 2); ctx.lineTo(coordinate.x - dottedSize / 2,coordinate.y + dottedSize / 2); ctx.closePath(); ctx.fill(); 复制代码
以上是分布实现,现在我们以面向对象的思想整体实现这个折方图:
/*1.构造函数*/ var LineChart = function (ctx) { /*获取绘图工具*/ this.ctx = ctx || document.querySelector('canvas').getContext('2d'); /*画布的大小*/ this.canvasWidth = this.ctx.canvas.width; this.canvasHeight = this.ctx.canvas.height; /*网格的大小*/ this.gridSize = 10; /*坐标系的间距*/ this.space = 20; /*坐标原点*/ this.x0 = this.space; this.y0 = this.canvasHeight - this.space; /*箭头的大小*/ this.arrowSize = 10; /*绘制点*/ this.dottedSize = 6; /*点的坐标 和数据有关系 数据可视化*/ } /*2.行为方法*/ LineChart.prototype.init = function (data) { this.drawGrid(); this.drawAxis(); this.drawDotted(data); }; /*绘制网格*/ LineChart.prototype.drawGrid = function () { /*x方向的线*/ var xLineTotal = Math.floor(this.canvasHeight / this.gridSize); this.ctx.strokeStyle = '#eee'; for (var i = 0; i <= xLineTotal; i++) { this.ctx.beginPath(); this.ctx.moveTo(0, i * this.gridSize - 0.5); this.ctx.lineTo(this.canvasWidth, i * this.gridSize - 0.5); this.ctx.stroke(); } /*y方向的线*/ var yLineTotal = Math.floor(this.canvasWidth / this.gridSize); for (var i = 0; i <= yLineTotal; i++) { this.ctx.beginPath(); this.ctx.moveTo(i * this.gridSize - 0.5, 0); this.ctx.lineTo(i * this.gridSize - 0.5, this.canvasHeight); this.ctx.stroke(); } }; /*绘制坐标系*/ LineChart.prototype.drawAxis = function () { /*X轴*/ this.ctx.beginPath(); this.ctx.strokeStyle = '#000'; this.ctx.moveTo(this.x0, this.y0); this.ctx.lineTo(this.canvasWidth - this.space, this.y0); this.ctx.lineTo(this.canvasWidth - this.space - this.arrowSize, this.y0 + this.arrowSize / 2); this.ctx.lineTo(this.canvasWidth - this.space - this.arrowSize, this.y0 - this.arrowSize / 2); this.ctx.lineTo(this.canvasWidth - this.space, this.y0); this.ctx.stroke(); this.ctx.fill(); /*Y轴*/ this.ctx.beginPath(); this.ctx.strokeStyle = '#000'; this.ctx.moveTo(this.x0, this.y0); this.ctx.lineTo(this.space, this.space); this.ctx.lineTo(this.space + this.arrowSize / 2, this.space + this.arrowSize); this.ctx.lineTo(this.space - this.arrowSize / 2, this.space + this.arrowSize); this.ctx.lineTo(this.space, this.space); this.ctx.stroke(); this.ctx.fill(); }; /*绘制所有点*/ LineChart.prototype.drawDotted = function (data) { /*1.数据的坐标 需要转换 canvas坐标*/ /*2.再进行点的绘制*/ /*3.把线连起来*/ var that = this; /*记录当前坐标*/ var prevCanvasX = 0; var prevCanvasY = 0; data.forEach(function (item, i) { /* x = 原点的坐标 + 数据的坐标 */ /* y = 原点的坐标 - 数据的坐标 */ var canvasX = that.x0 + item.x; var canvasY = that.y0 - item.y; /*绘制点*/ that.ctx.beginPath(); that.ctx.moveTo(canvasX - that.dottedSize / 2, canvasY - that.dottedSize / 2); that.ctx.lineTo(canvasX + that.dottedSize / 2, canvasY - that.dottedSize / 2); that.ctx.lineTo(canvasX + that.dottedSize / 2, canvasY + that.dottedSize / 2); that.ctx.lineTo(canvasX - that.dottedSize / 2, canvasY + that.dottedSize / 2); that.ctx.closePath(); that.ctx.fill(); /*点的连线*/ /*当时第一个点的时候 起点是 x0 y0*/ /*当时不是第一个点的时候 起点是 上一个点*/ if(i == 0){ that.ctx.beginPath(); that.ctx.moveTo(that.x0,that.y0); that.ctx.lineTo(canvasX,canvasY); that.ctx.stroke(); }else{ /*上一个点*/ that.ctx.beginPath(); that.ctx.moveTo(prevCanvasX,prevCanvasY); that.ctx.lineTo(canvasX,canvasY); that.ctx.stroke(); } /*记录当前的坐标,下一次要用*/ prevCanvasX = canvasX; prevCanvasY = canvasY; }); }; /*3.初始化*/ var data = [ { x: 100, y: 120 }, { x: 200, y: 160 }, { x: 300, y: 240 }, { x: 400, y: 120 }, { x: 500, y: 80 } ]; var lineChart = new LineChart(); lineChart.init(data);复制代码
效果图如下:
折线图制作完毕.
以上所述就是小编给大家介绍的《canvas 基础及应用(1)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
海量运维、运营规划之道
唐文 / 电子工业出版社 / 2014-1-1 / 59.00
《海量运维、运营规划之道》作者具有腾讯、百度等中国一线互联网公司多年从业经历,书中依托工作实践,以互联网海量产品质量、效率、成本为核心,从规划、速度、监控、告警、安全、管理、流程、预案、考核、设备、带宽等方面,结合大量案例与读者分享了作者对互联网海量运维、运营规划的体会。 《海量运维、运营规划之道》全面介绍大型互联网公司运维工作所涉及的各个方面,是每个互联网运维工程师、架构师、管理人员不可或......一起来看看 《海量运维、运营规划之道》 这本书的介绍吧!