canvas 最早由Apple引入WebKit,用于Mac OS X 的 Dashboard,后来又在Safari和Google Chrome被实现。
基于 Gecko 1.8的浏览器,比如 Firefox 1.5, 同样支持这个元素。
<canvas> 元素是WhatWG Web applications 1.0规范的一部分,也包含于HTML 5中。
什么是Canvas?
HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。
画布是一个矩形区域,您可以控制其每一像素。
canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
创建Canvas元素
绘制步骤
var myCanvas=document.getElementById(“canvas”);
//获取上下文
var ctx=myCanvas.getContext(“2d”);
//移动画笔
ctx.moveTo(100.5,100);
//绘制直线
ctx.lineTo(100.5,200);
//描边
ctx.stroke();
1.画布尺寸要在canvas标签里设置,
2.beginPath()绘制新的路径(创建多条不同的平行线要在开头加);
3.stroke()描边 fill()填充
4.closePath() 关闭路径 (用于解决起始点和lineTo的结束点无法完全闭合情况)
5.非零环绕填充规则:从这个区域拉一条线,看和这条直线相交的轨迹,顺时针加1,逆时针-1,所有轨迹计算出来,非零填充,0不填充
6.设置样式
lineWidth 线宽
lineCap 线末端类型:butt(默认),round,square
lineJoin 相交的拐点 miter(默认),round,bevel
setLineDash([]) 以数组方式描述虚线的排列方式。
getLineDash() 获取虚线的排列方式,获取的是不重复的那一段的排列方式。
lineDashOffset 设置虚线偏移量,正值往右负值往左
7.绘制矩形
fillRect(x,y,width,height) 填充矩形
strokeRect ( x,y,width,height) 绘制矩形边框
clearRect (x,y,width,height) 将矩形区域颜色进行擦除
8.绘制圆弧
arc(x,y,radius,startAngle,endAngle,anticlockwise)
anticlockwise为true/false 默认是false顺时针,true是逆时针
9.绘制文字
ctx.font = ‘字体大小 字体类型’ 设置字体
strokeText(text,x,y,maxWidth)
fillText(text,x,y,maxWidth)
textAlign 相对绘制坐标说明,left,center,right,start,end;
text.Baseline 设置基线(垂直对齐方式),
top 文本的基线处于文本的正上方,并且和文本粘合
middle 文本的基线处于文本的正中间
bottom 文本的基线处于文本的证下方,并且有一段距离
hanging 文本的基线处于文本的正上方,并且有一段距离
alphabetic 默认值,基线处于文本的下方,并且穿过文字
ideographic 和bottom相似,但是不一样
10.绘制图片
translate(x,y) 移动坐标原点的位置
scale(x,y) 参数表示宽高的缩放比例,缩放的是坐标
rotate(angle) 参数表示旋转角度
getImgData(sx,sy,sw,sh) 获取像素
sx,sy表示获取区域起始坐标
sw,wh 表示获取区域的宽高
putImageDate(imagedata,dx,dy[,dirtyX,dirtyY,dirtyWidth,dirtyHeight])
imagedata 像素数组
dx,dy重绘图像的起始坐标,
后面四个参数为可选参数
方法很多,简单列举这么多
小案例
canvas绘制渐变矩形
js代码
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
// ctx.strokeRect(60,60,50,50);
// ctx.clearRect(0,0,150,150);
var linearGradient = ctx.createLinearGradient(100,100,500,100);
linearGradient.addColorStop(0,'blue');
linearGradient.addColorStop(1,'red');
ctx.fillStyle = linearGradient;
ctx.fillRect(100,100,400,100);
canvas的转换
js代码如下
var ctx = document.querySelector('canvas').getContext('2d');
ctx.translate(100,100)
var angle = 0;
setInterval(function () {
angle += Math.PI/180;
ctx.rotate(angle);
ctx.strokeRect(-50,-50,100,100);
},500)
曲线的绘制
js代码
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext('2d');
//y=(x+2)^2
//y=sinx
for(var i=0;i<600;i++)
{
x = i;
// y = Math.pow(x-100,2)+10;
y = 50*Math.sin(x/10)+100;
ctx.lineTo(x,y);
}
ctx.stroke();
经典案例(面向对象)
折线图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
canvas{
border: 1px solid #a5a5a5;
}
</style>
<body>
<canvas width="600x" height="400px"></canvas>
</body>
<script>
var lineChart = function (ctx) {
this.ctx = ctx || document.querySelector('canvas').getContext('2d');
this.canvasWidth = this.ctx.canvas.width;
this.canvasHeight = this.ctx.canvas.height;
this.gridSize = 10;
this.space = 20;
this.arrowSize = 10;
this.dotSize = 6;
this.x0 = this.space;
this.y0 = this.canvasHeight - this.space;
}
lineChart.prototype.init = function (data) {
this.drawGrid();
this.drawAxis();
this.drawDot(data);
}
lineChart.prototype.drawGrid = function () {
var xLineTotal = Math.floor(this.canvasHeight / this.gridSize);
var yLineTotal = Math.floor(this.canvasWidth / this.gridSize);
this.ctx.strokeStyle = '#eee';
for (var i=0;i <= xLineTotal;i++)
{
this.ctx.beginPath();
this.ctx.moveTo(0,i*this.gridSize);
this.ctx.lineTo(this.canvasWidth,i*this.gridSize);
this.ctx.stroke();
}
for (var i=0;i <= yLineTotal;i++)
{
this.ctx.beginPath();
this.ctx.moveTo(i * this.gridSize,0);
this.ctx.lineTo(i * this.gridSize,this.canvasHeight);
this.ctx.stroke();
}
}
lineChart.prototype.drawAxis = function () {
this.ctx.strokeStyle ='#000';
this.ctx.beginPath();
this.ctx.moveTo(this.x0,this.y0);
this.ctx.lineTo(this.canvasWidth - this.space,this.y0);
this.ctx.lineTo(this.canvasWidth - this.space - this.arrowSize,this.y0 + this.arrowSize / 2);
this.ctx.lineTo(this.canvasWidth - this.space - this.arrowSize,this.y0 - this.arrowSize / 2);
this.ctx.lineTo(this.canvasWidth -this.space,this.y0);
this.ctx.stroke();
this.ctx.fill();
//=========================================
this.ctx.beginPath();
this.ctx.moveTo(this.x0,this.y0);
this.ctx.lineTo(this.x0,this.space);
this.ctx.lineTo(this.x0 + this.arrowSize/2,this.space + this.arrowSize);
this.ctx.lineTo(this.x0 - this.arrowSize/2,this.space + this.arrowSize);
this.ctx.lineTo(this.x0,this.space);
this.ctx.stroke();
this.ctx.fill();
}
lineChart.prototype.drawDot = function (data) {
var that = this;
var preCanvasX = 0 ;
var preCanvasY = 0 ;
data.forEach(function (item, i) {
var canvasX = that.x0 + item.x;
var canvasY = that.y0 - item.y;
console.log("1111111111111");
that.ctx.strokeStyle = '#000';
that.ctx.beginPath();
that.ctx.moveTo(canvasX - that.dotSize / 2,canvasY - that.dotSize / 2);
that.ctx.lineTo(canvasX + that.dotSize / 2,canvasY - that.dotSize / 2);
that.ctx.lineTo(canvasX + that.dotSize / 2,canvasY + that.dotSize / 2);
that.ctx.lineTo(canvasX - that.dotSize / 2,canvasY + that.dotSize / 2);
that.ctx.closePath();
that.ctx.fill();
//========================================
if(i == 0)
{
that.ctx.beginPath();
that.ctx.moveTo(that.x0,that.y0);
that.ctx.lineTo(canvasX,canvasY);
that.ctx.stroke();
}
else
{
that.ctx.beginPath();
that.ctx.moveTo(preCanvasX,preCanvasY);
that.ctx.lineTo(canvasX,canvasY);
that.ctx.stroke();
}
preCanvasX = canvasX;
preCanvasY = canvasY;
});
}
var data = [
{
x: 100,
y: 120
},
{
x: 200,
y: 160
},
{
x: 300,
y: 240
},
{
x: 400,
y: 120
},
{
x: 500,
y: 80
}
]
var lineChart = new lineChart();
lineChart.init(data);
</script>
</html>
数据饼图
代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<style>
canvas{
border: 1px solid #a5a5a5;
}
</style>
<body>
<canvas height="400px" width="600px"></canvas>
<script>
var pieChart = function (data) {
this.ctx = document.querySelector('canvas').getContext('2d');
this.x0 = this.ctx.canvas.width / 2;
this.y0 = this.ctx.canvas.height / 2;
this.radius = 150;
this.lineout = 30;
this.rectHeight = 10;
this.rectwidth = 20;
this.space = 10 ;
}
pieChart.prototype.init = function (data) {
this.pie(data);
}
pieChart.prototype.pie = function (data) {
this.ctx
var that = this;
var angleList = this.transformAngle(data);
var startAngle = 0;
var endAngle = 0;
angleList.forEach(function (item,i) {
endAngle += item.angle;
that.ctx.beginPath();
that.ctx.moveTo(that.x0,that.y0);
that.ctx.arc(that.x0,that.y0,that.radius,startAngle,endAngle);
var color = that.ctx.fillStyle = that.getRandomColor();
that.ctx.fill();
that.title(startAngle,item.angle,color,item.title);
startAngle = endAngle;
that.desc(i,item.title);
})
}
pieChart.prototype.title = function (startAngle,angle,color,title) {
var line = this.radius + this.lineout;
var xout = this.x0 + line * Math.cos(angle / 2 + startAngle);
var yout = this.y0 + line * Math.sin(angle / 2 + startAngle);
console.log(xout,yout);
this.ctx.beginPath();
this.ctx.moveTo(this.x0,this.y0);
this.ctx.lineTo(xout,yout);
this.ctx.strokeStyle = color;
// this.ctx.font = '20px';
this.ctx.font = '15px Microsoft YaHei';
var titleWidth = this.ctx.measureText(title).width;
if(xout > this.x0)
{
var titleX = xout + titleWidth;
this.ctx.lineTo(titleX,yout);
this.ctx.textAlign = 'left';
}
else
{
var titleX = xout - titleWidth;
this.ctx.lineTo(titleX,yout);
this.ctx.textAlign = 'right';
}
this.ctx.stroke();
this.ctx.textBaseline = 'bottom';
this.ctx.fillText(title,xout,yout );
};
pieChart.prototype.desc = function (index,title) {
var rectX = this.space;
var rectY = this.space + index * (this.rectHeight +10);
this.ctx.fillRect(rectX,rectY,this.rectwidth,this.rectHeight);
this.ctx.beginPath();
this.ctx.textAlign = 'left';
this.ctx.textBaseline = 'top';
this.ctx.fillText(title,this.space + this.rectwidth + 10,this.space + index*(this.rectHeight + 10));
}
pieChart.prototype.transformAngle = function (data) {
var total = 0;
var that = this;
data.forEach(function (item,i) {
total +=item.num;
})
console.log(total);
data.forEach(function (item,i) {
var angle = Math.PI * 2 * item.num / total;
item.angle = angle;
})
console.log(data);
return data;
}
pieChart.prototype.getRandomColor = function () {
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
return 'rgb('+r+','+g+','+b+')';
}
var data = [
{
title: '15-20岁',
num: 6
},
{
title: '20-25岁',
num: 30
},
{
title: '25-30岁',
num: 10
},
{
title: '30以上',
num: 8
}
];
var pieChart = new pieChart(data);
pieChart.init(data);
</script>
</body>
</html>
3.行走的小人
代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
canvas{
border: 1px solid #a5a5a5;
}
</style>
<body>
<canvas width="600px" height="400px"></canvas>
<script>
var Person = function () {
this.ctx = document.querySelector("canvas").getContext('2d');
this.canvasWidth = this.ctx.canvas.width;
this.canvasHeight = this.ctx.canvas.height;
this.stepSize = 10;
this.stepX = 0;
this.stepY = 0;
}
Person.prototype.init = function () {
var that = this;
this.loadImage(function (image) {
that.personWidth = image.width / 4;
that.personHeight = image.height / 4;
that.x = that.canvasWidth / 2 - that.personWidth / 2;
that.y = that.canvasHeight / 2 - that.personHeight / 2;
that.ctx.drawImage(image,0,0,that.personWidth,that.personHeight,that.x,that.y,that.personWidth,that.personHeight);
that.index = 0;
document.onkeydown = function (e) {
console.log(e.keyCode);
if(e.keyCode == 40)
{
that.direction = 0;
that.stepY ++;
that.move(image);
}
else if(e.keyCode == 37)
{
that.direction = 1;
that.stepX --;
that.move(image);
}
else if(e.keyCode == 39)
{
that.direction = 2;
that.stepX ++;
that.move(image);
}
else if(e.keyCode == 38)
{
that.direction = 3;
that.stepY --;
that.move(image);
}
}
})
}
Person.prototype.loadImage = function (callback) {
var image = new Image();
image.onload = function () {
callback&&callback(image);
}
image.src = 'image/04.png';
}
Person.prototype.move = function (image) {
this.index ++;
this.ctx.clearRect(0,0,this.canvasWidth,this.canvasHeight);
this.ctx.drawImage(
image,
this.index * this.personWidth,this.direction * this.personHeight,
this.personWidth,this.personHeight,
this.stepX * this.stepSize + this.x,this.stepY * this.stepSize + this.y,
this.personWidth,this.personHeight
)
if(this.index >= 3)
{
this.index = 0;
}
}
var person = new Person();
person.init();
</script>
</body>
</html>