canvas
canvas
Canvas英语中画布的意思,替代flash的。现在的网页中呈递动画、广告、游戏(抢车位、偷菜)基本都是flash。但是flash是浏览器插件,漏洞多、内存开销大、运行慢。HTML5花大气力研究了canvas标准,可以一举替代flash在网页动画中的地位,也能用来开发游戏。靠谱MDN点这里
一、基本认识
//得到画布
var canvas = document.getElementById('mecanvas') ;
//设置上下文 有2d 、3d
var ctx = canvas.getContext('2d');
//通过ctx来绘制元素
ctx.fillStyle = 'pink'; //设置填充颜色
ctx.fillRect(100,100,250,60)
//清屏
ctx.clearRect(0,0,'画布宽','画布高')
canvas有一个热点,上屏即像素化。在画布上绘制了一个图形,从某种意义上来说,这个图形再也拿不到了。如果想让这个元素动起来,必须重新绘制一个。
二、基本形状的绘制
- 矩形
ctx.fillRect(100,100,250,60)
fill表示填充 , Rect矩形 , 四个参数表示左上角坐标、宽度 、高度
绘制一个矩形的笔触 :
ctx.strokeStyle = 'red'; //设置 笔触颜色
ctx.strokeRect(100,100,200,400)
- 路径
简单列子说明一切
var canvas = document.getElementById('mecanvas') ;
var ctx = canvas.getContext('2d');
ctx.beginPath(); //开始一个路径
ctx.moveTo(100,100); // 移动画笔
ctx.lineTo(300,300); //划线
ctx.lineTo(400,400);
ctx.lineTo(500,100);
ctx.closePath(); //结束划线,自动补全最后一条线,让形状封闭
ctx.stroke(); //虚拟线已产生,需用stroke方法来绘制
- 圆弧
//开始绘制路径
ctx.beginPath()
ctx.arc(100,100,60,0,3,false) // Math.PI*2
ctx.stroke();
参数:
100,100 圆心坐标
60 半径
0 绘制开始的角度 ,弧度制
3 绘制结束的角度, 弧度制
false true逆时针绘制; false顺时针绘制
- 贝萨尔曲线
二次贝萨尔曲线
ctx.beginPath();
ctx.moveTo(100,100); //画笔起点
ctx.quadraticCurveTo(400,100,300,300); // 400 , 100 控制点坐标 300,300终点坐标
ctx.stroke();
三次贝萨尔曲线
ctx.beginPath();
ctx.moveTo(500,100);//画笔起点
ctx.bezierCurveTo(300, 300, 600, 20, 700, 100);//300, 300, 600, 20 两个控制点 700,100终点
ctx.stroke();
- 透明度
//给上下文设置不透明度
ctx.globalAlpha = 0.5;
ctx.fillRect(0, 0, 100, 100);
//后面的形状如果不设置透明度,那么就要设置回来
ctx.globalAlpha = 1;
ctx.fillStyle = "red";
ctx.fillRect(200,200,100,100);
- 线型
线的宽度: ctx.lineWidth = 30
末端形状: ctx.lineCap = “round” butt | square
线和线之间的连接: ctx.lineJoin = “round” 可以是bevel 、miter
绘制虚线 : ctx.setLineDash([4, 2]); - 渐变
//得到画布
var mycanvas = document.getElementById("mycanvas");
//得到上下文
var ctx = mycanvas.getContext("2d");
var jianbianduixiang = ctx.createLinearGradient(100,100,300,300);
jianbianduixiang.addColorStop(0, "red");
jianbianduixiang.addColorStop(1, "blue");
ctx.fillStyle = jianbianduixiang;
ctx.fillRect(100, 100, 300, 300)
- 绘制文本
ctx.font = “40px 微软雅黑”;
ctx.fillText(“你好”,100,100);
三、应用图片
canvas可以绘制任意的图片到画布上,需要一个固定的写法,需要图片onload之后再绘制:
//先设置图片地址
var image = new Image();
image.src = "images/tu.jpg";
//当这个图片load了,然后绘制
image.onload = function(){
ctx.drawImage(image,100,100);
}
绘制图片用的API :
实际上,drawImage()函数一共可以有9个参数
ctx.drawImage(image,308,197,59,82,100,100,59,82);
绿色参数表示切片,蓝色是画布上的信息
ctx.drawImage(image,100,100,140,140); //5个参数 表示位置和宽度、高度,没有切片
ctx.drawImage(images,100,100); //3个参数 表示位置
四、面向对象开发Canvas
//小球类
function Ball(x, y, r, color) {
this.x = x;
this.y = y;
this.r = r;
this.color = "white";
this.dx = Math.random() * 8 - 4;
this.dy = Math.random() * 8 - 4;
//把自己注册
g.balls.push(this);
}
// 更新,每帧执行
Ball.prototype.update = function () {
this.x += this.dx;
this.y += this.dy;
this.r -= 1;
}
// 渲染,每帧执行
Ball.prototype.render = function () {
if (this.r < 0) {
//从数组中删除自己
g.kill(this);
return;
}
g.ctx.beginPath();
g.ctx.arc(this.x, this.y, this.r, 0, 7, false);
g.ctx.closePath();
g.ctx.fillStyle = this.color;
g.ctx.fill();
}
//游戏类
function Game() {
//得到画布和设置上下文
this.canvas = document.getElementById("canvas");
this.ctx = this.canvas.getContext("2d");
//所有演员数组
this.balls = [];
//帧编号
this.frame = 0;
this.start();
//监听
this.canvas.onmousemove = function (event) {
var x = event.offsetX;
var y = event.offsetY;
new Ball(x, y, 30);
}
}
//从数组中删除某一个小球
Game.prototype.kill = function (ball) {
//遍历数组,看看谁是传进来的ball
for (var i = 0; i < this.balls.length; i++) {
if (this.balls[i] === ball) {
this.balls.splice(i, 1);
}
}
}
Game.prototype.start = function () {
var self = this;
//不管页面上有几个运动的元素,定时器只有一个
setInterval(function () {
//帧编号加1
self.frame++;
//清屏
self.ctx.clearRect(0, 0, 1200, 800);
//更新所有演员,渲染所有演员
for (var i = 0; i < self.balls.length; i++) {
self.balls[i].update();
self.balls[i].render();
}
//打印帧编号
self.ctx.fillText(self.frame, 10, 10);
console.log(self.balls);
}, 20);
}
五、ctx的平移和旋转
1、坐标系平移,坐标系的原点向右边移动100,向下边移动100
ctx.translate(100,100);
ctx.fillRect(0, 0, 100, 100);
注意: 可以让坐标系的原点平移,注意指的是相对平移,不是绝对平移。
2、上下文的保存和恢复
/坐标系平移,坐标系的原点向右边移动100,向下边移动100
ctx.save(); //上下文保存
ctx.translate(100,100);
ctx.fillRect(0, 0, 100, 100);
ctx.restore(); //上下文的恢复
ctx.translate(100,100);
ctx.fillRect(0, 0, 100, 100);
3、坐标系的轴旋转了30度
ctx.rotate(30 * 3.14 / 180);
ctx.fillRect(0,0,100,100);
canvas特别坑,旋转的时候不是绕着自己的中心转,而是坐标系绕着自己的原点转,怎么办。