Canvas基础入门
2015-06-05 22:30
344 查看
Canvas学习笔记
标签(空格分隔):HTML5 Canvascanvas基础知识
canvas元素
<canvas width="500" height="500"> // 默认宽度和高度为350和150像素 </canvas>
坐标系统
2D渲染上下文是一种基于屏幕的标准绘图平台,采用笛卡尔坐标体系,左上角为原点(0, 0),坐标系统的一个单位相当于屏幕的1个像素。可以通过Javascript来访问2D渲染上下文。
绘制基本的图形和线条
矩形,有三个方法:rect,
fillRect,
strokeRect分别绘制矩形,填充矩形和矩形(无填充有边框)
/* rect(x, y, width, height) 4个参数,前两个表示矩形左上角的坐标值,width和height分别表示矩形的宽度和高度*/ context.fillRect(40, 40, 100, 100) // 填充矩形 context.fillRect(40, 40, 100, 100) // 线框矩形
线条,可以通过线条的组合画出很多的图形
/* 画线条*/ context.lineWidth = 2; // 设置线条的宽度,默认为1 context.beginPath(); // 开始路径 context.moveTo(0, 0); // 设置路径原点 context.lineTo(300, 100); // 设置路径终点 context.closePath(); // 结束路径 context.stroke(); // 绘出路径轮廓
圆弧,圆弧最常见的应用就是画圆形,圆弧首位相连就是一个圆形,用方法
arc,
context.arc(x, y, radius, startAngle, endAngle, anticlockwise), 前三个参数代表圆心的坐标和半径的大小,第四个和第五参数表示开始角度和结束角度,第六个参数是一个布尔值,逆时针则为true,顺时针为false
/* 画圆形*/ context.beginPath(); context.arc(50, 50, 50, 0, Math.PI*3/2, false); context.closePath(); context.fill(); // 填充整个圆形 context.stroke(); // 绘出圆形轮廓(线框图)
绘制文本,canvas文本以图像形式绘制,无法通过鼠标选取,不能编辑。通过方法
fillText绘制,还可以修改文本的样式
/* 绘制文本*/ var text = "hello world!"; context.font = " italic 50px serif"; // 修改字号和字体 context.fillText(text, 40, 40); context.strokeText(text, 40, 40);
修改样式,通过方法
fillStyle方法可以修改形状和路径的填充颜色,方法
lineWidth可以修改线宽,默认为1。
context.fillStyle = "rgb(255, 0, 0)"; context.lineWidth = 5; // 加粗线条
擦除canvas,
clearRect(x, y, width, height)可以部分清除一个矩形大小的区域
context.clearRect(0, 0, canvas.width(), canvas.height()); // 清除全部canvas区域
canvas 高级功能
绘图状态
在画布中,绘图状态指的是描述某一个时刻2D渲染上下文外观的整套属性,从简单的颜色值到变换矩阵。可以通过方法save和
restore保存和恢复绘图状态
context.fillStyle = "rgb(255, 0, 0)"; context.save(); // 保存画布状态 context.fillRect(50, 50, 100, 100); // 红色正方形 context.fillStyle = "rgb(0, 0, 225)"; context.fillRect(200, 50, 100, 100); // 蓝色正方形 // context.restore(); // 恢复画布状态 context.fillRect(350, 50, 100, 100); // 红色正方形
可以同时保存和恢复多个绘图状态,各个绘图状态以栈的形式储存,先进后出,每恢复一个绘图状态就从栈顶取出,直到栈空
context.fillStyle = "rgb(255, 0, 0)"; context.save(); // 保存画布状态 context.fillRect(50, 50, 100, 100); // 红色正方形 context.fillStyle = "rgb(0, 0, 225)"; context.save(); // 保存画布状态 context.fillRect(200, 50, 100, 100); // 蓝色正方形 // context.restore(); // 恢复画布状态 context.fillRect(350, 50, 100, 100); // 蓝色正方形 context.restore(); // 恢复画布状态 context.fillRect(50, 200, 100, 100); // 红色正方形
变形
平移,移动2D渲染上下文的坐标原点context.translate(150, 150); // 平移原点的坐标到(150, 150)
缩放,调整2D渲染上下文的尺寸,分别在x方向和y方向上
context.scale(2, 2); // x和y方向都乘以2
旋转,将2D渲染上下文绕其原点进行旋转
context.rotate(0.7854); // 旋转45度(Math.PI/4)
变换矩阵,3X3的矩阵,默认为单位矩阵,可以通过方法
setTransform和
transform修改其值的大小
/* 变换矩阵*/ context.setTransform(1,0,0,1,0,0); var xScale = Math.cos(0.7845); var ySkew = -Math.sin(0.7845); var xSKew = Math.sin(0.7845); var yScale = Math.cos(0.7845); var xTrans = 100; var yTrans = 100; context.transform(xScale, ySkew, xSKew, yScale, xTrans, yTrans); context.fillRect(-50, -50, 100, 100);
合成
阿尔法值,可以通过设置globalAlpha设置全局阿尔法值也可通过
rgba设置样式的阿尔法值。
globalAlpha的值必须在0.0(透明)到1.0(不透明)之间,影响透明度。
合成,设置两个图形层叠时候的处理方式,
globalCompositeOperation有11种可选方法,但是游览器并不支持所有属性。介绍两种常用的
source-top默认值,后面的图形盖住前面的,
destination-over前面的盖住后面的。
高级样式
阴影,通过4个属性进行控制,shadowBlur,
shadowOffsetX,
shadowOffsetY,
shadowColor。
context.shadowBlur = 80; // 模糊值 context.shadowOffsetX = 10; // 阴影长度 context.shadowOffsetY = 10; context.shadowColor = "rgba(100, 100, 100, 0.5)"; // 阴影颜色 context.fillRect(50, 50, 100, 100);
渐变,分为线性渐变和放射性渐变
/* 线性渐变色*/ var gradient = context.createLinearGradient(0, 0, 0, canvas.height()); gradient.addColorStop(0, "rgb(0, 0, 0)"); // 0,渐变起点 gradient.addColorStop(1, "rgb(255, 255, 255)"); // 1,渐变终点 context.fillStyle = gradient; context.fillRect(0, 0, canvas.width(), canvas.height());
复杂路径,可以通过线条的组合画出很多比较复杂的图形
/* 画三角形*/ context.beginPath(); context.moveTo(100, 50); context.lineTo(150, 150); context.lineTo(50, 150); context.closePath(); context.stroke(); context.fill();
贝塞尔曲线,二次贝塞尔曲线有一个控制点,三次贝塞尔曲线有两个控制点,可以用来画三角函数图形。
/* 二次贝塞尔曲线*/ context.lineWidth = 5; // 线宽 context.beginPath(); context.moveTo(50, 250); 起点坐标 context.quadraticCurveTo(250, 100, 450, 250); 终点坐标(450, 250),控制点坐标(250, 100) context.stroke(); /* 三次贝塞尔曲线*/ context.lineWidth = 5; context.beginPath(); context.moveTo(50, 250); context.bezierCurveTo(150, 50, 350, 450, 450, 250); // 两个控制点 context.stroke();
处理图像和视频
加载图像
调用函数drawImage至少需要3个参数,所绘制的图像,图像绘制位置的(x, y)坐标
var image = new Image(); image.src = "example.jpg"; $(image).load(function(){ context.drawImage(image, 0, 0); });
函数
drawImage还可以调整图像的大小和canvas画布的大小相匹配
context.drawImage(image, 0, 0, width, height);
函数
drawImage将图像裁剪至你想要的大小,并可以做相应的放大和缩小,此时共需要9个参数,源图像,源图像的裁剪区原点坐标(x,y),源图像的裁剪区宽度和高度,在画布上绘制图像的原点坐标(x,y)及在画布上绘制图像的宽度和高度。
context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
图像变形
对图像的变形如阴影,平移,旋转以及缩放和对整个画布进行的变形使用的方法是一致的。访问像素值
在画布中访问像素的方法是getImageData, 有4个参数,要访问的像素区域的原点坐标(x,y),像素区域的宽度和高度。返回一个ImageData对象,这个对象包含3个属性:width,height,data,最重要的是属性值data,是一个包含了所访问区域全部像素信息的一维数组。
var imageData = context.getImageData(x, y, width, height); var pixel = imageData.data; // 一维数组 `4*widht*height`, *rgba*
通过对像素值的访问我们可以对图像进行一些处理,如反转图像,灰度化图像,以及像素化。实例代码:
/* 通过访问图像像素值实现基本的图像效果*/ var image = new Image(); image.src = "example.jpg"; $(image).load(function(){ context.drawImage(image, 0, 0, 500, 500); var imageData = context.getImageData(0, 0, canvas.width(), canvas.height()); var pixels = imageData.data; var numPixels = pixels.length; context.clearRect(0, 0, canvas.width(), canvas.height); // 反转颜色,255 减去当前颜色值所得就是反转后的颜色 for(var i = 0; i < numPixels; i++){ pixels[i*4] = 255 - pixels[i]; pixels[i*4 + 1] = 255 - pixels[i*4 + 1]; pixels[i*4 + 2] = 255 - pixels[i*4 + 2]; } // 灰度化图像,计算现有颜色的平均值 for(var i =0; i < numPixels; i++){ var average = (pixels[i*4]+pixels[i*4+1]+pixels[i*4+2])/3; pixels[i*4] = average; pixels[i*4+1] = average; pixels[i*4+1] = average; } context.putImageData(imageData, 0, 0); })
像素化图像类似于打马赛克的效果,可以将图像变得不可识别。
// 小方块在每行每列上的数目 var numTileRows = 50; var numTileCols = 50; // 每个小方块的宽度和长度 var tileWidth = imageData.width/numTileRows; var tileHeight = imageData.height/numTileCols; for(var r = 0; r < numTileRows; r++){ for(var c = 0; c < numTileCols; c++){ // 小方块中心的坐标 var x = (c*tileWidth)+(tileWidth/2); var y = (r*tileHeight)+(tileHeight/2); // 小方块中心的像素值 var pos = (Math.floor(y)*(imageData.width*4)) + (Math.floor(x)*4); var red = pixels[pos]; var green = pixels[pos + 1]; var blue = pixels[pos + 2]; context.fillStyle = "rgb("+red+", "+green+", "+blue+")"; // 马赛克效果 context.fillRect(x-(tileWidth/2), y-(tileHeight/2), tileWidth, tileHeight); } }
视频处理
视频处理的原理和处理图像几乎一样,只是处理的是视频当前帧的图像值,不再赘述。制作动画
更新,清除,绘制
动画的原理就是使得一个动画对象不断的更新,清除和绘制。只要这个循环的速度到一定程度就可产生动画效果function animate(){ // 消除 context.clearRect(0, 0, canvasWidth, canvasHeigth); var shapesLength = shapes.length; for(var i = 0; i < shapesLength; i++){ var tmpShape = shapes[i]; /* 更新*/ // tmpShape.x += 2; // tmpShape.y++; // tmpShape.x += Math.random()*4 - 2; // tmpShape.y += Math.random()*4 - 2; //圆周运行 tmpShape.x += (tmpShape.radius*Math.cos(tmpShape.angle*(Math.PI/180))); tmpShape.y += (tmpShape.radius*Math.sin(tmpShape.angle*(Math.PI/180))); // 增大角度 tmpShape.angle += 5; if(tmpShape.angle >= 360){ tmpShape.angle = 0; } // 绘制 context.fillRect(tmpShape.x, tmpShape.y, tmpShape.width, tmpShape.height); } if(playAnimate){ setTimeout(animate, 33); } };
反弹效果
$(document).ready(function(){ var canvas = $("#myCanvas"); var context = canvas.get(0).getContext("2d"); var canvasWidth = canvas.width(); var canvasHeight = canvas.height(); var playAnimation = true; var startButton = $("#startAnimation"); var stopButton = $("#stopAnimation"); // 添加按钮时间处理 startButton.hide(); startButton.click(function() { $(this).hide(); stopButton.show(); playAnimation = true; animate(); }); stopButton.click(function() { $(this).hide(); startButton.show(); playAnimation = false; }); // 图形类 var Shape = function(x, y, width, height) { this.x = x; this.y = y; this.width = width; this.height = height; /* 可以通过修改运动的默认值,来设置运动方式*/ this.reverseX = false; this.reverseY = true; }; var shapes = new Array(); // 创造图形 for (var i = 0; i < 10; i++) { var x = Math.random()*250; var y = Math.random()*250; var width = height = Math.random()*30; shapes.push(new Shape(x, y, width, height)); }; context.clearRect(0, 0, canvasWidth, canvasHeight); var shapesLength = shapes.length; for (var i = 0; i < shapesLength; i++) { var tmpShape = shapes[i]; // 更新 // 检查是否碰壁 if (!tmpShape.reverseX) { tmpShape.x += 2; } else { tmpShape.x -= 2; }; if (!tmpShape.reverseY) { tmpShape.y += 2; } else { tmpShape.y -= 2; }; // 绘制 context.fillRect(tmpShape.x, tmpShape.y, tmpShape.width, tmpShape.height); // 检查碰壁 if (tmpShape.x < 0) { tmpShape.reverseX = false; } else if (tmpShape.x + tmpShape.width > canvasWidth) { tmpShape.reverseX = true; }; if (tmpShape.y < 0) { tmpShape.reverseY = false; } else if (tmpShape.y + tmpShape.height > canvasHeight) { tmpShape.reverseY = true; }; }; if (playAnimation) { setTimeout(animate, 33); }; }; animate(); });
相关文章推荐
- Linux常用命令-文件处理命令-链接命令
- [Servlet]深入研究HttpServlet
- 第二次冲刺——第7天
- java程序员应该熟练掌握的技术
- Lemon OA第1篇:简单介绍
- Cool Edit Pro 中把歌曲的原唱声消除掉制作伴奏带
- [D3] 13. Cleaner D3 code with selection.call()
- 谷歌浏览器打不开
- JavaWeb系列之七(response域与request)
- android file explorer
- java线程学习(二)—并发编程实践学习笔记
- 中科院开源协会镜像站 Android SDK镜像
- 《EventBus使用详解(二)——EventBus使用进阶》
- UITableViewCell重用和性能优化
- Python模拟登陆
- DOS常用命令
- 多线程同步辅助类
- JavaScript Style Attributes
- Palindrome Number
- 《最后期限》——读书笔记1