内容简介: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)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First HTML5 Programming
Eric Freeman、Elisabeth Robson / O'Reilly Media / 2011-10-18 / USD 49.99
What can HTML5 do for you? If you're a web developer looking to use this new version of HTML, you might be wondering how much has really changed. Head First HTML5 Programming introduces the key featur......一起来看看 《Head First HTML5 Programming》 这本书的介绍吧!