前言:
这节课主要学习HTML5中新增的画布(canvas)。
1.canvas基本认识
作用:canvas是HTML5给出的一个可以展示绘图(可以用JavaScript控制图的内容)内容的标签。
坐标位置:canvas中的坐标是从左上角开始算起的。
场景:
游戏
可视化数据(重点) 根据数据,绘制出相应的图表
banner广告
多媒体
未来
模拟仿真 threejs.org(canvas派生出来的)
远程操作
图形编辑
2.canvas基本使用
1.canvas的宽、高属性:
canvas标签默认占据300 * 150的区域。
设置宽、高:
第一种:行内式设置,相当于增加了canvas画布的像素点。(推荐方式)
第二种:内嵌式设置,只是将像素扩大了,并没有增加像素点,这样图形会变虚。
注意事项:canvas的宽、高不带单位。
2.操作步骤
获取canvas标签
var cas = document.getElementById("cas");
获取2d绘图画笔:
var ctx = cas.getContext("2d");
开始描点:
ctx.moveTo(100, 100); //把笔放到这个位置(绘制的起始点)
ctx.lineTo(200, 100); //绘制直线到什么位置(绘制的终点)
开始绘图:
ctx.stroke(); //描边绘图,可以看到效果
demo示例:
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); ctx.moveTo( 100, 100 ); // 把笔放在那里 ctx.lineTo( 200, 100 ); // 从刚才的位置, 绘制到哪里 ctx.stroke(); // 描边绘图, 可以看到效果 </script>
3.常用方法和属性:
moveTo(); 设置绘图的起始点
lineTo(); 从起始点绘制直线到x, y。
stroke(); 将描好的边连接,形成封闭的图形。
fill(); 调用fill方法会将所有的点连接起来,并构成一个封闭的图形结构
如果所有的描点没有构成封闭结构,也会将开始的起点与最终的点连接起来,构成一个闭合的图像,并且填充
lineWidth = 值; 改变画笔的粗细
如果是奇数,线宽会+1变成偶数,绘制结果:线宽的上下各会有1px的虚影。
如果是偶数,上下就不会有虚影。
strokeStyle = "颜色",设置画笔的颜色
lineDashOffset = 数字 表示线起始位置距画布边框距离
当数字为"正"时,表示虚线向左移动。
当数字为"负"时,表示虚线向右移动。
setLineDash(数组);
数组中的数字交替表示实线和间隙的长度。
closePath();用于闭合图形, 会对终点处理。
beginPath()开辟新的路径
getLineDash();获取线形的参数设置
fillStyle(); 设置某块区域的填充颜色。
3.canvas案例演示
1.绘制虚线(step=10)
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> // 绘制虚线 // 从 (100,100) 绘制到 右下角 (500, 100) // 获取canvas元素 var cas = document.getElementById( 'cas' ); // 获取2d画笔 var ctx = cas.getContext( '2d' ); // 设置间隙为10,起始x坐标为100 var step = 10,start = 100; // 一直绘制下去, 当 moveTo 的 x 超过 500 的时候停下来 while ( true ) { if ( start >= 500 ) break; // 绘制虚线的 实线部分 ctx.moveTo( start, 100 ); ctx.lineTo( start+=step, 100 ) // 绘制间隔部分 start+=step; } ctx.stroke(); </script>
2.绘制倾斜虚线
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> // 从 (0,0) 绘制到 右下角 (600, 400) var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); //使stepY和stepX不是等比例变化 var stepX = 5, stepY = stepX * 2 / 3,startX = 0, startY = 0; while ( true ) { if ( startX >= 600 || startY >= 400 ) break; // 绘制虚线的 实线部分 ctx.moveTo( startX, startY ); ctx.lineTo( startX+=stepX, startY+=stepY ); // 绘制空白部分 startX+=stepX; startY+=stepY; } ctx.stroke(); </script>
3.绘制矩形、梯形、三角形
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); // 绘制矩形 ctx.moveTo( 50, 100 ); ctx.lineTo( 50 + 100, 100 ); ctx.lineTo( 50 + 100, 100 + 100 ); ctx.lineTo( 50, 100 + 100 ); ctx.lineTo( 50, 100 ); // 绘制三角形 ctx.moveTo( 200, 100 ); ctx.lineTo( 200, 200 ); ctx.lineTo( 300, 200 ); ctx.lineTo( 200, 100 ); // 绘制梯形 ctx.moveTo( 350, 100 ); ctx.lineTo( 350, 200 ); ctx.lineTo( 450, 200 ); ctx.lineTo( 400, 100 ); ctx.lineTo( 350, 100 ); ctx.stroke(); </script>
4.fill方法演示
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); // fill 替代 stroke方法 ctx.moveTo( 100, 100 ); ctx.lineTo( 200, 100 ); ctx.lineTo( 200, 200 ); ctx.fill(); </script>
5.closePath方法演示
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); //设置线宽为3 ctx.lineWidth = 3; //设置线颜色为red ctx.strokeStyle = "red"; ctx.moveTo( 100, 50 ); ctx.lineTo( 200, 50 ); ctx.lineTo( 200, 150 ); ctx.lineTo( 100, 150 ); // 当绘图没有封闭时, closePath()会自动将起点和终点连接闭合。 ctx.closePath(); ctx.stroke(); </script>
6.beginPath方法演示
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); // 首先绘制一个描边的矩形 ctx.moveTo( 100, 80 ); ctx.lineTo( 400, 80 ); ctx.lineTo( 400, 180 ); ctx.lineTo( 100, 180 ); ctx.closePath(); ctx.stroke(); // 如果不使用beginPath(),上面的矩形会被再绘制一次结果就会比之前加粗 ctx.beginPath(); ctx.moveTo( 100, 200 ); ctx.lineTo( 400, 200 ); ctx.lineTo( 400, 300 ); ctx.lineTo( 100, 300 ); ctx.closePath(); ctx.stroke(); </script>
7.setLineDash(arr)方法演示
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); ctx.moveTo( 100, 100 ); ctx.lineTo( 400, 100 ); // 表示先画10像素的的实线,再间隔5像素的空白 ctx.setLineDash( [ 10, 5] ); ctx.stroke(); </script>
8.综合练习坐标系
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); var paddingTop = 50, paddingLeft = 50, paddingBottom = 50, paddingRight = 50; var arrowHeight = 20,arrowWidth = 10; var x0 = paddingLeft, y0 = cas.height - paddingBottom; // 首先绘制坐标轴线 ctx.moveTo( x0, paddingTop ); ctx.lineTo( x0, y0 ); ctx.lineTo( cas.width - paddingRight, y0 ); ctx.stroke(); // 绘制箭头 ctx.beginPath(); ctx.moveTo( cas.width - paddingRight, y0 ); ctx.lineTo( cas.width - paddingRight - arrowHeight, y0 - arrowWidth * .5 ); ctx.lineTo( cas.width - paddingRight - arrowHeight * .5, y0 ); ctx.lineTo( cas.width - paddingRight - arrowHeight, y0 + arrowWidth * .5 ); ctx.closePath(); ctx.moveTo( paddingLeft, paddingTop ); ctx.lineTo( paddingLeft - arrowWidth * .5, paddingTop + arrowHeight ); ctx.lineTo( paddingLeft, paddingTop + arrowHeight * .5 ); ctx.lineTo( paddingLeft + arrowWidth * .5, paddingTop + arrowHeight ); ctx.closePath(); ctx.fill(); // 下面绘制点 ctx.beginPath(); // // 绘制一个点在坐标轴的中间 var width = cas.width - paddingRight - paddingLeft - arrowHeight, height = cas.height - paddingTop - paddingBottom - arrowHeight; var x = width * .5, y = height * .5; // 坐标变换 x = x0 + x; y = y0 - y; // 绘制一个红色的矩形 var pointWidth = 8; ctx.fillStyle = 'red'; ctx.moveTo( x - pointWidth * .5, y - pointWidth / 2 ); ctx.lineTo( x + pointWidth * .5, y - pointWidth / 2 ); ctx.lineTo( x + pointWidth * .5, y + pointWidth / 2 ); ctx.lineTo( x - pointWidth * .5, y + pointWidth / 2 ); ctx.closePath(); ctx.fill(); </script>
9.绘制直线的方法封装
<head> <meta charset="UTF-8"> <title></title> <style> canvas { border:1px solid black; } </style> </head> <body> <canvas width="600" height="400" id="cas"></canvas> </body> <script> var cas = document.getElementById( 'cas' ); var ctx = cas.getContext( '2d' ); function Line( config ) { // 必须提供的属性 this.ctx = config.ctx; this.x0 = config.x0; this.y0 = config.y0; this.x1 = config.x1; this.y1 = config.y1; // 选择提供 this.strokeStyle = config.strokeStyle; this.lineWidth = config.lineWidth; } Line.prototype = { constructor: Line, stroke: function () { // 封装绘制过程即可 this.ctx.moveTo( this.x0, this.y0 ); this.ctx.lineTo( this.x1, this.y1 ); if ( this.strokeStyle ) { this.ctx.strokeStyle = this.strokeStyle; } if ( this.lineWidth ) { this.ctx.lineWidth = this.lineWidth; } this.ctx.stroke(); } }; var line = new Line( { ctx: ctx, x0: 100, y0: 100, x1: 400, y1: 100, strokeStyle:'red', lineWidth: 5 }); line.stroke(); </script>