嗯,那个,我是来试水的,跟你们这些大神不能比,所以就为小小白们总结一下Canvas的基础,还望各位多多指教……
第一话 与canvas的初次邂逅
姓名:Canvas
自我介绍:一个默认为宽300,高150的空白画布,可以使用脚本来绘制图形的HTML元素,可以绘制图表、制作图片构图或者制作简单的动画
哦,对了,Canvas说他只是一个容器,本身没有绘制能力,所以他在等一个意中人拿到一个画布,使之具有绘制各种图形的能力,他的意中人应该可以做到以下几点:
1、 有一个舒适的地方(页面),一般我们最常用html文件
2、 里面要有标签,作为h5新标签,不太支持较老版本的浏览器,因此稍稍判断以下还是可以的,或者说如果你用的浏览器版本比较新 ,那可以不用写‘你的浏览器不支持canvas’这句话了,同时我们在标签上规定id、宽高,这里的宽高如果拿到外面去设置就会导致canvas变形,所以乖乖仔这里设,至于其他样式设置就拿到外面去吧
<canvas id="canvas" width="400" height="500">
你的浏览器不支持canvas!
</canvas>
复制代码
3、 获取到这个画布,每个canvas节点都有一个对应的context对象(上下文对象),Canvas API定义在这个context对象上面,所以需要获取这个对象,方法是使用getContext方法。即Canvas.getContext(contextID),参数 contextID 指定了您想要在画布上绘制的类型。当前唯一的合法值是 “2d”,它指定了二维绘图,并且导致这个方法返回一个环境对象,该对象导出一个二维绘图 API。在未来,如果 <canvas> 标签扩展到支持 3D 绘图,getContext() 方法可能允许传递一个 “3d” 字符串参数。
var canvas=document.getElementById('canvas')
//获得画布
var context=canvas.getContext('2d')
复制代码
第二话 他的意中人
- 跟矩形有关的那点事
在此之前,我们先做一下准备工作:fillReact(坐标x,坐标y,宽,高):一般用于绘制实心的矩形,与fillStyle() 填充颜色搭配使用;strokeReact(坐标x,坐标y,宽,高) : 一般绘制空心的矩形,与strokeStyle() 设置边框颜色搭配使用;
context.benginPath(): 开始路径;context.closePath() : 结束路径,值得注意的是
1、系统默认在绘制第一个路径的开始点为beginPath 2、如果画完前面的路径没有重新指定beginPath,那么画第其他路径的时候会将前面最近指定的beginPath后的全部路径重新绘制 3、每次调用context.fill()的时候会自动把当次绘制的路径的开始点和结束点相连,接着填充封闭的部分,这时也就不用调用closePath()了,但是调用strock()不会自动闭合
var canvas=document.getElementById('canvas')
//获得画布
var context=canvas.getContext('2d')
context.beginPath(); // 开始路径
context.fillStyle='yellow' // 设置要填充的颜色
context.fillRect(100,150,100,100)
context.fill() // 全部填充
复制代码
这样做,我们就可以得到下面这个图
再来个空心的像这样的
context.beginPath()
context.strokeStyle="red"
context.strokeRect(150,150,100,100)
context.fill()
复制代码
什么?想要个橡皮擦?没问题,满足你
context.clearRect(x,y,width,height) 仅支持矩形
context.clearRect(30,30,50,50)
复制代码
矩形的故事先说到这里,下面我们来说说圆形那个家伙
- 一个球的故事
跟矩形的套路差不多 ,我们常用来画圆的是arc , context.arc(x, y, radius, starAngle,endAngle, anticlockwise) 坐标位置不用介绍了,后面就是半径,开始弧度,结束弧度,顺逆时针
//绘制圆形
context.beginPath()
context.arc(250,250,20,0,Math.PI*2,true)
context.closePath()
context.fillStyle='rgba(0,255,0,0.25)'
context.fill()
复制代码
然后差不多就是这个样子了
第三话 贝塞尔的约会
在说约会的故事前,先来认识一下牵线人 线段
context.moveTo(x,y) context.lineTo(x,y)
moveTo(x,y) 移动到某一点,但是它只是代表的作画的起点 lineTo(x,y) 与上面的对应,代表作画的终点,每次画线都从moveTo的点到lineTo的点, 如果没有moveTo那么第一次lineTo的效果和moveTo一样, 每次lineTo后如果没有moveTo,那么下次lineTo的开始点为前一次lineTo的结束点
Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。 曲线定义:起始点、终止点、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。 1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。来见识一下贝塞尔如何?下面是五阶贝塞尔曲线的绘制过程
如果觉得太复杂,那我们先来看二阶的,是不是好很多
绘制贝塞尔曲线(贝济埃、bezier) context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) 先来说说个个参数都代表什么 cp1x:第一个控制点x坐标 cp1y:第一个控制点y坐标 cp2x:第二个控制点x坐标 cp2y:第二个控制点y坐标 x:终点x坐标 y:终点y坐标
如果你想要了解他的算法,可以参考一下这个http://www.cnblogs.com/wxydigua/p/4204254.html http://www.cnblogs.com/regina1123/p/6256375.html
ctx.beginPath();
ctx.moveTo(75,25); // 开个头
ctx.quadraticCurveTo(25,25,25,62.5);
ctx.quadraticCurveTo(25,100,50,100);
ctx.quadraticCurveTo(50,120,30,125);
ctx.quadraticCurveTo(60,120,65,100);
ctx.quadraticCurveTo(125,100,125,62.5);
ctx.quadraticCurveTo(125,25,75,25);
ctx.stroke();
复制代码
结果如下,还可以吧,没那么丑,至于那个控制点,个人理解为以moveTo为中心,向前向后画曲线,然后就这样了,当然如果想要画更复杂的图,可以在好好研究一下
- 还有一点值得注意,精确画图时,我们要考虑一下线条的像素会不会对你的图有影响?
比如说,我们想要一个1像素的,但是结果却不太像1像素的
这是因为计算机不允许出现小于1px的图形,所以他做了一个折中的事:把这两个像素都绘制了。所以,如此一来,本来1px的线条,就成了看起来2px宽的线。也就是说这个1像素为了能生存下去,就向左向右跨了0.5像素,也就成了2像素
为了解决这个问题,聪明的人们还是想到了办法的,那就是给需要的地方加上0.5像素,虽然有点麻烦,但是亲测有效
第四话 初识文(文字)阴(阴影)渐(渐变)
- 我是文字啊
fillText(text, x, y [, maxWidth]) 在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的. 当然如果绘制一个空心的也可以,那就这样strokeText(text, x, y);
ctx.font = "20px Arial";
ctx.textBaseline = "hanging";
ctx.strokeText("Hello ", 50, 50);
复制代码
- 嗯,我是阴影
context.shadowOffsetX :阴影的横向位移量(默认值为0) context.shadowOffsetY :阴影的纵向位移量(默认值为0) context.shadowColor :阴影的颜色 context.shadowBlur :阴影的模糊范围(值越大越模糊)
ctx.shadowOffsetX = 2; //X轴阴影距离,负上,正下
ctx.shadowOffsetY = 2; //Y轴阴影距离,负左,正右
ctx.shadowBlur = 2; //阴影的模糊程度
ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; //阴影颜色
ctx.font = "30px Times New Roman"; //设置字体和字体大小
ctx.fillStyle = "Black";
ctx.fillText("Sample String", 15, 30); //实体文字
ctx.strokeStyle = 'red';
ctx.strokeText('Hello world', 15, 100); //边框文字
复制代码
- 我,我是渐变……
线性渐变 createLinearGradient(xStart,yStart,xEnd,yEnd) 线性渐变颜色addColorStop(offset,color) xstart:渐变开始点x坐标 ystart:渐变开始点y坐标 xEnd:渐变结束点x坐标 yEnd:渐变结束点y坐标 offset:设定的颜色离渐变结束点的偏移量(0~1) color:绘制时要使用的颜色
let can=document.getElementById('Canvas')
let ctx=Canvas.getContext('2d')
let bg = ctx.createLinearGradient(0, 0, 0, 200);
bg.addColorStop(0, 'black'); // 开始颜色
bg.addColorStop(0.6, '#fff’); //结束颜色 ctx.fillStyle = bg; ctx.fillRect(10, 10, 100, 100); 复制代码
径向渐变(发散)context.createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd) 径向渐变(发散)颜色rg.addColorStop(offset,color) xStart:发散开始圆心x坐标
yStart:发散开始圆心y坐标 radiusStart:发散开始圆的半径 xEnd:发散结束圆心的x坐标 yEnd:发散结束圆心的y坐标 radiusEnd:发散结束圆的半径 offset:设定的颜色离渐变结束点的偏移量(0~1) color:绘制时要使用的颜色
var bg1 = ctx.createRadialGradient(100, 100, 0, 100, 100, 50);
bg1.addColorStop(0, '#FF5F98');
bg1.addColorStop(0.75, '#FF0188');
bg1.addColorStop(1, 'rgba(255,1,136,0)');
ctx.fillStyle = bg1;
ctx.fillRect(0,0,150,150);
复制代码
第五话 千变万化
这里先了解一下状态:对于canvas 的状态就是当前画面应用的所有样式和变形的一个快照,操作状态有两个方法:save() 和 restore (),前者是用来保存当前状态,后者用来恢复刚才保存的状态,他们都可以多次调用,举个例子
ctx.fillStyle = 'black';
ctx.fillRect(20, 20, 150, 150);
ctx.save(); //保存当前状态
ctx.fillStyle= '#fff’; ctx.fillRect(45, 45, 100, 100); ctx.restore(); //恢复到刚才保存的状态 ctx.fillRect(70, 70, 50, 50);复制代码
然后就这样了
位移了解一下? ctx.translate(x, y); //更改canvas的原点
for(var i = 1; i< 4; i++) {
ctx.save();
//使用save方法保存状态,让每次位移时都针对(0,0)移动。
ctx.translate(100*i, 0);
ctx.fillRect(0, 50, 50, 50);
ctx.restore();
}
复制代码
缩放也了解一下吧 ctx.scale(x, y); //基于原点缩放,x、y是两个轴的缩放倍数
var ctx = document.getElementById('canvas').getContext('2d’); ctx.fillStyle = 'red’;
ctx.scale(0.8, 1.2);
ctx.beginPath();
ctx.arc(75, 75, 60, 0, Math.PI * 2); ctx.fill();
复制代码
第六话 有情人终成眷属
我们来简单结合一下图形做一个好看的效果,像这样的
怎么样是不是还可以,那就上代码
let can=document.getElementById('can')
let context=can.getContext('2d')
//绘制颜色板
for(let i=0;i<6;i++){
for(let j=0;j<6;j++){
context.fillStyle='rgb('+Math.floor(255-42.5*i)+','+Math.floor(255-42.5*j)+',0)'
context.fillRect(i*25,j*25,25,25)
}
}
//绘制圆形
for(var i=0;i<10;i++){
for(var j=0;j<10;j++){
context.strokeStyle='rgb(0,'+Math.floor(255-42.5*i)+','+Math.floor(255-42.5*j)+')'
context.beginPath()
context.arc(12.5+j*25,180+i*25,10,0,Math.PI*2,true)
context.stroke()
}
}
复制代码
最后经过不懈的努力,他们就变成了这个样纸,代码找不到了,反正就是拼在一起就好了^_^