终于到了这里,也是我回来看这些的初衷因为实在太6了,这个东东。
不了解为什么他很6的可以感受一下:
http://codepen.io/dissimulate/pen/KrAwx(2d)
http://codepen.io/ara_node/pen/nuJCG(3d)
怎么开始呢?我也是头疼
1.首先来简单认识它一下:http://www.w3school.com.cn/html5/html_5_canvas.asp
2.接下来开始练练手熟悉api了:http://www.w3school.com.cn/tags/html_ref_canvas.asp
对着这个参考手册,我就这么开始了。
颜色、样式和阴影
<!DOCTYPE HTML>
<html>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript">
'use strict'
function draw(){
var canvas = document.getElementById('canvas');
if(!canvas || !canvas.getContext) return false; //浏览器兼容写法
var ctx = canvas.getContext("2d");
ctx.beginPath(); //我要开始绘制路径了
ctx.fillStyle = "#ff0000"; //填充样式:纯红色填充
ctx.shadowColor = 'black'; //阴影颜色:黑
ctx.shadowBlur = 100; //阴影扩散范围:向四周100px内
ctx.shadowOffsetX = -20; //阴影偏移:x轴-20(水平方向向左偏移20px)
ctx.shadowOffsetY= -20; //<span style="font-family: Arial, Helvetica, sans-serif;">阴影偏移:y轴-20(垂直方向向上偏移20px)</span>
ctx.arc(100,50,50,0,Math.PI,false); //绘制圆,圆心(100,50),半径50,起始弧角0,结束弧角π绘制半圆,false代表不采用逆时针
ctx.fill();
}
draw();
</script>
</body>
</html>
接着方法:
createLinearGradient() ,修改刚才的draw方法
function draw(){
var canvas = document.getElementById('canvas');
if(!canvas || !canvas.getContext) return false;
var ctx = canvas.getContext("2d");
ctx.beginPath();
// ctx.fillStyle = "#ff0000";
//创建线性渐变 由坐标(0,0)到(w,h) 画布左上到画布右下
var lgrd = ctx.createLinearGradient(0,0,canvas.width,canvas.height);
lgrd.addColorStop(0,'white'); //颜色停止位置
lgrd.addColorStop(0.3,'yellow');
lgrd.addColorStop(0.6,'red');
lgrd.addColorStop(1,'black');
ctx.fillStyle = lgrd; //设置样式为线性渐变
ctx.shadowColor = 'black';
ctx.shadowBlur = 100;
ctx.shadowOffsetX = -20;
ctx.shadowOffsetY= -20;
ctx.arc(100,50,50,0,Math.PI,false);
ctx.fill();
}
createPattern(),相当于复制,再次修改
先在body里加入一张图片
<img id="img" src="http://www.runoob.com/images/lamp.jpg">
然后执行js
function draw(direction)
{
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.clearRect(0,0,c.width,c.height);
var img=document.getElementById("img");
var pat=ctx.createPattern(img,direction);
ctx.rect(0,0,c.width,c.height);
ctx.fillStyle=pat;
ctx.fill();
}
setTimeout(function(){ //这里要延迟加载,否则可能画不出来,主要让img先加载出来
draw('repeat');
},1000);
线条样式
context.lineCap="butt|round|square"; 给线条添加两端的样式,默认butt无context.lineJoin="bevel|round|miter"; 两条线之间的样式,默认Miter尖角,bevel斜角,round圆角
context.lineWidth=number; 线条宽度
context.miterLimit=number;尖角的长度,超过了会被截掉成斜角bevel
矩形
方法 | 描述 |
---|---|
rect() | 创建矩形 |
fillRect() | 绘制“被填充”的矩形 |
strokeRect() | 绘制矩形(无填充) |
clearRect() | 在给定的矩形内清除指定的像素 |
路径 提一部分方法
clip()方法进去看图就能明白http://www.w3school.com.cn/tiy/t.asp?f=html5_canvas_clip
quadraticCurveTo() | 创建二次贝塞尔曲线 |
bezierCurveTo() | 创建三次方贝塞尔曲线 |
isPointInPath() | 如果指定的点位于当前路径中,则返回 true,否则返回 false |
转换
方法 | 描述 |
---|---|
scale() | 缩放当前绘图至更大或更小 |
rotate() | 旋转当前绘图 |
translate() | 重新映射画布上的 (0,0) 位置 |
transform() | 替换绘图的当前转换矩阵 |
setTransform() | 将当前转换重置为单位矩阵。然后运行 transform() |
说说这里的转换
画布上的每个对象都拥有一个当前的变换矩阵。
transform() 方法替换当前的变换矩阵。它以下面描述的矩阵来操作当前的变换矩阵:
a c e b d f 0 0 1
a | 水平缩放绘图 |
b | 水平倾斜绘图 |
c | 垂直倾斜绘图 |
d | 垂直缩放绘图 |
e | 水平移动绘图 |
f | 垂直移动绘图 |
我们知道对图形进行转换实际上是对每一像素点坐标进行转换
目前不论是SVG也好,CSS 3也好,还是Canvas,2D的矩阵变换都提供了6个参数a b c d e f,其使用基本公式是这样的:
也就是说,
x’=ax+cy+e
y’=bx+dy+f
这样就好办了,为了得到正确的坐标,传入正确的参数就行了。
a.最简单的是平移
x’=x+e
y’=y+f
所以a=1,b=0,c=0,d=1,e=水平偏移量,f=垂直偏移量
function draw(){
var canvas = document.getElementById('canvas');
if(!canvas || !canvas.getContext) return false;
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.fillStyle="red";
ctx.rect(0,0,100,30);
ctx.fill();
ctx.beginPath();
ctx.fillStyle="yellow";
ctx.transform(1,0,0,1,30,10);
ctx.rect(0,0,100,30);
ctx.fill();
}
看看效果,就知道,水平偏移了30,竖直偏移10
b.来一个缩放
x’=ax
y’=dy
很明显应该执行
ctx.transform(a,0,0,d,0,0);
c.比较难搞的是旋转
假设x,y是平面上的一点,在以0,0为圆心,r为半径的圆上,连线与x轴的夹角为a,则其坐标可以表示为
x=r*cosa
y=r*sina
让其绕0,0旋转θ角度,则新的坐标可以表示为
x’=r*cos(a+θ)=r*(cosa*cosθ-sina*sinθ)=(r*cosa)*cosθ-(r*sina)*sinθ=x*cosθ-y*sinθ
y’=r*sin(a+θ)=r*(sina*cosθ+cosa*sinθ)=(r*sina)*cosθ+(r*cosa)*sinθ=x*sinθ+y*cosθ
所以呢执行
ctx.transform(cosθ,sinθ,-sinθ,cosθ,0,0);
θ代表角度,用Math公式的时候计算的是弧度,所以cosθ要写成Math.cos(θ*2*Math.PI/360)
d.当然了,以上转换也可以结合起来使用
transform()与setTransform()的区别在于:
transform操作每次都是基于上一次transform操作的,比如先偏移了30,接着再做一次transform偏移20,
最后的结果是偏移50。而setTransform每次都先重置为初始状态,再进行转换
图像绘制
drawImage() | 向画布上绘制图像、画布或视频 |
像素操作
属性 | 描述 |
---|---|
width | 返回 ImageData 对象的宽度 |
height | 返回 ImageData 对象的高度 |
data | 返回一个对象,其包含指定的 ImageData 对象的图像数据 |
方法 | 描述 |
---|---|
createImageData() | 创建新的、空白的 ImageData 对象 |
getImageData() | 返回 ImageData 对象,该对象为画布上指定的矩形复制像素数据 |
putImageData() | 把图像数据(从指定的 ImageData 对象)放回画布上 |
先介绍下ImageData这个东东,它里面有个Data[]数组,保存了指定范围内的所有像素信息[RGBARGBARGBA...RGBA]
RGBA代表一个像素点的信息
- R - 红色 (0-255)
- G - 绿色 (0-255)
- B - 蓝色 (0-255)
- A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
其他用法看手册,挺简单的
合成
属性 | 描述 |
---|---|
globalAlpha | 设置或返回绘图的当前 alpha 或透明值 |
globalCompositeOperation | 设置或返回新图像如何绘制到已有的图像上 |
globalCompositeOperation进去看看,如果有在任何平台做过图像处理的,会相当的熟悉,就是图片混合方式,可以照着手册编码看效果