canvas绘图
- 准备画布,画布是白色的 而且默认300*150
<canvas width="600" height="400" ></canvas>
建议直接行间设置宽高,不建议在样式表中设置,因为在样式表中设置呈现的是原始画布被拉伸的效果。 - 准备绘制工具,获取元素和上下文/绘制工具箱
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
没有3D,WebGL
可以为HTML5 Canvas
提供硬件3D加速渲染 - 利用工具绘图 如:绘制直线:先移动画笔(到起点)
ctx.moveTo(100,100);
再绘制直线(到终点) (轨迹,绘制路径)ctx.lineTo(200,100);
最后描边ctx.stroke();
线模糊问题
- 线默认的宽度是
1px
- 先默认的颜色是
黑色
- 线模糊产生的原因是线的中心点对应像素坐标,于是相当于两个
0.5px
的线拼起来一样,而浏览器的渲染以像素为单位,显示就会不饱和,并且错误地增加了宽度最终造成线条的模糊感(色差+增宽) - 解决方案:上下移动
0.5px
即可ctx.moveTo(100,100.5);ctx.lineTo(200,100.5);
设置线条的宽度和颜色
在描边前设置ctx.strokeStyle = 'red'; ctx.lineWidth = 20;
关闭路径之三角形
在绘制三角形的时候会出现路径不能闭合的情况如下:
解决方案:在描边前设置:ctx.closePath();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*1.绘制一个三角形*/
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.lineTo(200,200);
/*起始点和lineTo的结束点无法完全闭合缺角*/
/*使用canvas的自动闭合 */
//ctx.lineTo(100,100);
/*关闭路径*/
ctx.closePath();
ctx.lineWidth = 10;
/*2.描边*/
ctx.stroke();
/*3.填充*/
//ctx.fill();
</script>
</body>
</html>
填充之镂空正方形
在描边后:ctx.fill();
在填充时遵循非零环绕规则
如果需要判断某一个区域是否需要填充颜色,就从该区域中随机的选取一个点。从这个点拉一条直线出来, 一定要拉到图形的外面. 此时以该点为圆心。看穿过拉出的直线的线段, 如果是顺时针方向(就是绘制轨迹时的方向)就记为 +1, 如果是 逆时针方向,就记为 -1。最终看求和的结果. 如果是 0 就不填充, 如果是非零就填充。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*1.绘制两个正方形 一大200一小100 套在一起*/
ctx.moveTo(100,100);
ctx.lineTo(300,100);
ctx.lineTo(300,300);
ctx.lineTo(100,300);
ctx.closePath();
ctx.moveTo(150,150);
ctx.lineTo(150,250);
ctx.lineTo(250,250);
ctx.lineTo(250,150);
ctx.closePath();
/*2.去填充*/
//ctx.stroke();
ctx.fillStyle = '#ee6363';
ctx.fill();
/*在填充的时候回遵循非零环绕规则*/
</script>
</body>
</html>
设置端点和拐点
在描边前:ctx.lineCap = 'round';//拐点ctx.lineJoin = 'round';//端点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*画平行线*/
ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(200,20);
ctx.lineTo(300,100);
ctx.strokeStyle = 'blue';
ctx.lineWidth = 10;
ctx.lineCap = 'butt';
ctx.lineJoin = 'miter';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(200,120);
ctx.lineTo(300,200);
ctx.strokeStyle = 'red';
ctx.lineWidth = 20;
ctx.lineCap = 'square';
ctx.lineJoin = 'bevel';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(100,300);
ctx.lineTo(200,220);
ctx.lineTo(300,300);
ctx.strokeStyle = 'green';
ctx.lineWidth = 30;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.stroke();
</script>
</body>
</html>
绘制虚线
绘制完轨迹后,在描边前
- 设置虚线排列方式
ctx.setLineDash([20]);
[5(有线),10(无线)。。。。。] 数组是用来描述你的排列方式的 - 还可以设置偏移
ctx.lineDashOffset = -20;
如果是正的值 往后偏移,如果是负的值 往前偏移 - 根据需要获取虚线的排列方式
console.log(ctx.getLineDash());
获取的是不重复的那一段的排列方式
绘制渐变矩形(粗线为形,由点构线)
ctx.beginPath();
回到画布原点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
ctx.lineWidth = 30;
for (var i = 0; i < 255; i++) {
ctx.beginPath();//回到画布原点
ctx.moveTo(100+i-1,100);
ctx.lineTo(100+i,100);
ctx.strokeStyle = 'rgb('+i+',0,0)';
ctx.stroke();
}
</script>
</body>
</html>
关于矩形的方法和用矩形方法绘制矩形/渐变矩形
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*绘制矩形路径 不是独立路径*/
/*ctx.rect(100,100,200,100);
ctx.fillStyle = 'green';
ctx.stroke();
ctx.fill();*/
/*绘制矩形 有自己的独立路径*/
//ctx.strokeRect(100,100,200,100);
ctx.fillRect(100,100,200,100);
/*清除矩形的内容*/
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
//ctx.fillRect(100,100,200,100);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
/* .linearGradient{
width: 400px;
height: 100px;
background-image: linear-gradient(to right,pink,blue);
}*/
</style>
</head>
<body>
<div class="linearGradient"></div>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*fillStyle 'pink' '#000' 'rgb()' 'rgba()' */
/*也可以使用一个渐变的方案了填充矩形*/
/*创建一个渐变的方案*/
/*渐变是由长度的*/
/*x0y0 起始点 x1y1 结束点 确定长度和方向*/
var linearGradient = ctx.createLinearGradient(100,100,500,400);
linearGradient.addColorStop(0,'pink');
//linearGradient.addColorStop(0.5,'red');
linearGradient.addColorStop(1,'blue');
ctx.fillStyle = linearGradient;
ctx.fillRect(100,100,400,100);
/*pink---->blue*/
/*回想线性渐变---->要素 方向 起始颜色 结束颜色 */
/*通过两个点的坐标可以控制 渐变方向*/
</script>
</body>
</html>
绘制表格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
/*1.构造函数*/
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.x0 = this.space;
this.y0 = this.canvasHeight - this.space;
/*箭头的大小*/
this.arrowSize = 10;
/*绘制点*/
this.dottedSize = 6;
/*点的坐标 和数据有关系 数据可视化*/
}
/*2.行为方法*/
LineChart.prototype.init = function (data) {
this.drawGrid();
this.drawAxis();
this.drawDotted(data);
};
/*绘制网格*/
LineChart.prototype.drawGrid = function () {
/*x方向的线*/
var xLineTotal = Math.floor(this.canvasHeight / this.gridSize);
this.ctx.strokeStyle = '#eee';
for (var i = 0; i <= xLineTotal; i++) {
this.ctx.beginPath();
this.ctx.moveTo(0, i * this.gridSize - 0.5);
this.ctx.lineTo(this.canvasWidth, i * this.gridSize - 0.5);
this.ctx.stroke();
}
/*y方向的线*/
var yLineTotal = Math.floor(this.canvasWidth / this.gridSize);
for (var i = 0; i <= yLineTotal; i++) {
this.ctx.beginPath();
this.ctx.moveTo(i * this.gridSize - 0.5, 0);
this.ctx.lineTo(i * this.gridSize - 0.5, this.canvasHeight);
this.ctx.stroke();
}
};
/*绘制坐标系*/
LineChart.prototype.drawAxis = function () {
/*X轴*/
this.ctx.beginPath();
this.ctx.strokeStyle = '#000';
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();
/*Y轴*/
this.ctx.beginPath();
this.ctx.strokeStyle = '#000';
this.ctx.moveTo(this.x0, this.y0);
this.ctx.lineTo(this.space, this.space);
this.ctx.lineTo(this.space + this.arrowSize / 2, this.space + this.arrowSize);
this.ctx.lineTo(this.space - this.arrowSize / 2, this.space + this.arrowSize);
this.ctx.lineTo(this.space, this.space);
this.ctx.stroke();
this.ctx.fill();
};
/*绘制所有点*/
LineChart.prototype.drawDotted = function (data) {
/*1.数据的坐标 需要转换 canvas坐标*/
/*2.再进行点的绘制*/
/*3.把线连起来*/
var that = this;
/*记录当前坐标*/
var prevCanvasX = 0;
var prevCanvasY = 0;
data.forEach(function (item, i) {
/* x = 原点的坐标 + 数据的坐标 */
/* y = 原点的坐标 - 数据的坐标 */
var canvasX = that.x0 + item.x;
var canvasY = that.y0 - item.y;
/*绘制点*/
that.ctx.beginPath();
that.ctx.moveTo(canvasX - that.dottedSize / 2, canvasY - that.dottedSize / 2);
that.ctx.lineTo(canvasX + that.dottedSize / 2, canvasY - that.dottedSize / 2);
that.ctx.lineTo(canvasX + that.dottedSize / 2, canvasY + that.dottedSize / 2);
that.ctx.lineTo(canvasX - that.dottedSize / 2, canvasY + that.dottedSize / 2);
that.ctx.closePath();
that.ctx.fill();
/*点的连线*/
/*当时第一个点的时候 起点是 x0 y0*/
/*当时不是第一个点的时候 起点是 上一个点*/
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(prevCanvasX,prevCanvasY);
that.ctx.lineTo(canvasX,canvasY);
that.ctx.stroke();
}
/*记录当前的坐标,下一次要用*/
prevCanvasX = canvasX;
prevCanvasY = canvasY;
});
};
/*3.初始化*/
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>
</body>
</html>
</script>
</body>
</html>
绘制曲线
在描边前 ctx.arc(w/2,h/2,150,Math.PI/2,Math.PI,true);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*绘制圆弧*/
/*确定圆心 坐标 x y*/
/*确定圆半径 r */
/*确定起始绘制的位置和结束绘制的位置 确定弧的长度和位置 startAngle endAngle 弧度*/
/*取得绘制的方向 direction 默认是顺时针 false 逆时针 true */
/*在中心位置画一个半径150px的圆弧左下角*/
var w = ctx.canvas.width;
var h = ctx.canvas.height;
ctx.arc(w/2,h/2,150,Math.PI/2,Math.PI,true);
ctx.stroke();
</script>
</body>
</html>
绘制扇形
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*在中心位置画一个半径150px的圆弧右上角 扇形 边 填充 */
var w = ctx.canvas.width;
var h = ctx.canvas.height;
/*把起点放到圆心位置*/
ctx.moveTo(w/2,h/2);
ctx.arc(w/2,h/2,150,0,-Math.PI/2,true);
/*闭合路径*/
//ctx.closePath();
ctx.fill();
</script>
</body>
</html>
根据数据绘制饼图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
display: block;
margin: 100px auto;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
/*var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');*/
/*1.绘制饼状态图*/
/*1.1 根据数据绘制一个饼图*/
/*1.2 绘制标题 从扇形的弧中心伸出一条线在画一条横线在横线的上面写上文字标题*/
/*1.3 在画布的左上角 绘制说明 一个和扇形一样颜色的矩形 旁边就是文字说明*/
var PieChart = function (ctx) {
/*绘制工具*/
this.ctx = ctx || document.querySelector('canvas').getContext('2d');
/*绘制饼图的中心*/
this.w = this.ctx.canvas.width;
this.h = this.ctx.canvas.height;
/*圆心*/
this.x0 = this.w / 2 + 60;
this.y0 = this.h / 2;
/*半径*/
this.radius = 150;
/*伸出去的线的长度*/
this.outLine = 20;
/*说明的矩形大小*/
this.rectW = 30;
this.rectH = 16;
this.space = 20;
}
PieChart.prototype.init = function (data) {
/*1.准备数据*/
this.drawPie(data);
};
PieChart.prototype.drawPie = function (data) {
var that = this;
/*1.转化弧度*/
var angleList = this.transformAngle(data);
/*2.绘制饼图*/
var startAngle = 0;
angleList.forEach(function (item, i) {
/*当前的结束弧度要等于下一次的起始弧度*/
var endAngle = startAngle + 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.drawTitle(startAngle, item.angle, color , item.title);
/*绘制说明*/
that.drawDesc(i,item.title);
startAngle = endAngle;
});
};
PieChart.prototype.drawTitle = function (startAngle, angle ,color , title) {
/*1.确定伸出去的线 通过圆心点 通过伸出去的点 确定这个线*/
/*2.确定伸出去的点 需要确定伸出去的线的长度*/
/*3.固定伸出去的线的长度*/
/*4.计算这个点的坐标*/
/*5.需要根据角度和斜边的长度*/
/*5.1 使用弧度 当前扇形的起始弧度 + 对应的弧度的一半 */
/*5.2 半径+伸出去的长度 */
/*5.3 outX = x0 + cos(angle) * ( r + outLine)*/
/*5.3 outY = y0 + sin(angle) * ( r + outLine)*/
/*斜边*/
var edge = this.radius + this.outLine;
/*x轴方向的直角边*/
var edgeX = Math.cos(startAngle + angle / 2) * edge;
/*y轴方向的直角边*/
var edgeY = Math.sin(startAngle + angle / 2) * edge;
/*计算出去的点坐标*/
var outX = this.x0 + edgeX;
var outY = this.y0 + edgeY;
this.ctx.beginPath();
this.ctx.moveTo(this.x0, this.y0);
this.ctx.lineTo(outX, outY);
this.ctx.strokeStyle = color;
/*画文字和下划线*/
/*线的方向怎么判断 伸出去的点在X0的左边 线的方向就是左边*/
/*线的方向怎么判断 伸出去的点在X0的右边 线的方向就是右边*/
/*结束的点坐标 和文字大小*/
this.ctx.font = '14px Microsoft YaHei';
var textWidth = this.ctx.measureText(title).width ;
if(outX > this.x0){
/*右*/
this.ctx.lineTo(outX + textWidth,outY);
this.ctx.textAlign = 'left';
}else{
/*左*/
this.ctx.lineTo(outX - textWidth,outY);
this.ctx.textAlign = 'right';
}
this.ctx.stroke();
this.ctx.textBaseline = 'bottom';
this.ctx.fillText(title,outX,outY);
};
PieChart.prototype.drawDesc = function (index,title) {
/*绘制说明*/
/*矩形的大小*/
/*距离上和左边的间距*/
/*矩形之间的间距*/
this.ctx.fillRect(this.space,this.space + index * (this.rectH + 10),this.rectW,this.rectH);
/*绘制文字*/
this.ctx.beginPath();
this.ctx.textAlign = 'left';
this.ctx.textBaseline = 'top';
this.ctx.font = '12px Microsoft YaHei';
this.ctx.fillText(title,this.space + this.rectW + 10 , this.space + index * (this.rectH + 10));
};
PieChart.prototype.transformAngle = function (data) {
/*返回的数据内容包含弧度的*/
var total = 0;
data.forEach(function (item, i) {
total += item.num;
});
/*计算弧度 并且追加到当前的对象内容*/
data.forEach(function (item, i) {
var angle = item.num / total * Math.PI * 2;
item.angle = angle;
});
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();
pieChart.init(data);
</script>
</body>
</html>
绘制文本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
display: block;
margin: 100px auto;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*1.在画布的中心绘制一段文字*/
/*2.申明一段文字*/
var str = '您吃-,了吗';
/*3.确定画布的中心*/
var w = ctx.canvas.width;
var h = ctx.canvas.height;
/*4.画一个十字架在画布的中心*/
ctx.beginPath();
ctx.moveTo(0, h / 2 - 0.5);
ctx.lineTo(w, h / 2 - 0.5);
ctx.moveTo(w / 2 - 0.5, 0);
ctx.lineTo(w / 2 - 0.5, h);
ctx.strokeStyle = '#eee';
ctx.stroke();
/*5.绘制文本*/
ctx.beginPath();
ctx.strokeStyle = '#000';
var x0 = w/2;
var y0 = h/2;
/*注意:起点位置在文字的左下角*/
/*有文本的属性 尺寸 字体 左右对齐方式 垂直对齐的方式*/
ctx.font = '40px Microsoft YaHei';
/*左右对齐方式 (center left right start end) 基准起始坐标*/
ctx.textAlign = 'center';
/*垂直对齐的方式 基线 baseline(top,bottom,middle) 基准起始坐标*/
ctx.textBaseline = 'middle';
//ctx.direction = 'rtl';
//ctx.strokeText(str,x0,y0);
ctx.fillText(str,x0,y0);
/*6.画一个下划线和文字一样长*/
ctx.beginPath();
/*获取文本的宽度*/
console.log(ctx.measureText(str));
var width = ctx.measureText(str).width;
ctx.moveTo(x0-width/2,y0 + 20);
ctx.lineTo(x0+width/2,y0 + 20);
ctx.stroke();
</script>
</body>
</html>
绘制图片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<!--<img src="image/01.jpg" alt="">-->
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*1.加载图片到内存即可*/
/*var img = document.createElement('img');
img.src = 'image/01.jpg';*/
/*创建对象*/
var image = new Image();
/*绑定加载完成事件*/
image.onload = function () {
/*实现图片绘制*/
console.log(image);
/*绘制图片的三种方式*/
/*3参数*/
/*图片对象*/
/*绘制在画布上的坐标 x y*/
//ctx.drawImage(image,100,100);
/*5个参数*/
/*图片对象*/
/*绘制在画布上的坐标 x y*/
/*是图片的大小 不是裁剪 是缩放*/
//ctx.drawImage(image,100,100,100,100);
/*9个参数*/
/*图片对象*/
/*图片上定位的坐标 x y */
/*在图片上截取多大的区域 w h*/
/*绘制在画布上的坐标 x y*/
/*是图片的大小 不是裁剪 是缩放*/
ctx.drawImage(image,400,400,400,400,200,200,100,100);
};
/*设置图片路径*/
image.src = 'image/02.jpg';
</script>
</body>
</html>
帧动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<!--<img src="image/01.jpg" alt="">-->
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
var image = new Image();
image.onload = function () {
/*图片加载完成*/
/*动态的去获取当前图片的尺寸*/
var imageWidth = image.width;
var imageHeight = image.height;
/*计算出每一个小人物的尺寸*/
var personWidth = imageWidth/4;
var personHeight = imageHeight/4;
/*位截取图片*/
/*帧动画 在固定的时间间隔更换显示的图片 根据图片的索引*/
var index = 0;
/*绘制在画布的中心*/
/*图片绘制的起始点*/
var x0 = ctx.canvas.width /2 - personWidth / 2;
var y0 = ctx.canvas.height /2 - personHeight / 2;
ctx.drawImage(image,0,0,personWidth,personHeight,x0,y0,personWidth,personHeight);
setInterval(function () {
index ++;
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
ctx.drawImage(image,index * personWidth,0,personWidth,personHeight,x0,y0,personWidth,personHeight);
if(index >= 3){
index = 0;
}
},1000);
};
image.src = 'image/04.png';
</script>
</body>
</html>
控制型动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var Person = function (ctx) {
/*绘制工具*/
this.ctx = ctx || document.querySelector('canvas').getContext('2d');
/*图片路径*/
this.src = 'image/04.png';
/*画布的大小*/
this.canvasWidth = this.ctx.canvas.width;
this.canvasHeight = this.ctx.canvas.height;
/*行走相关参数*/
this.stepSzie = 10;
/* 0 前 1 左 2 右 3 后 和图片的行数包含的图片对应上*/
this.direction = 0;
/*x轴方向的偏移步数*/
this.stepX = 0;
/*y轴方向的偏移步数*/
this.stepY = 0;
/*初始化方法*/
this.init();
};
Person.prototype.init = function () {
var that = this;
/*1.加载图片*/
this.loadImage(function (image) {
/*图片的大小*/
that.imageWidth = image.width;
that.imageHeight = image.height;
/*人物的大小*/
that.personWidth = that.imageWidth / 4;
that.personHeight = that.imageHeight / 4;
/*绘制图片的起点*/
that.x0 = that.canvasWidth / 2 - that.personWidth / 2;
that.y0 = that.canvasHeight / 2 - that.personHeight / 2;
/*2.默认绘制在中心位置正面朝外*/
that.ctx.drawImage(image,
0,0,
that.personWidth,that.personHeight,
that.x0,that.y0,
that.personWidth,that.personHeight);
/*3.能通过方向键去控制人物行走*/
that.index = 0;
document.onkeydown = function (e) {
if(e.keyCode == 40){
that.direction = 0;
that.stepY ++;
that.drawImage(image);
/*前*/
}else if(e.keyCode == 37){
that.direction = 1;
that.stepX --;
that.drawImage(image);
/*左*/
}else if(e.keyCode == 39){
that.direction = 2;
that.stepX ++;
that.drawImage(image);
/*右*/
}else if(e.keyCode == 38){
that.direction = 3;
that.stepY --;
that.drawImage(image);
/*后*/
}
}
});
}
/*加载图片*/
Person.prototype.loadImage = function (callback) {
var image = new Image();
image.onload = function () {
callback && callback(image);
};
image.src = this.src;
};
/*绘制图片*/
Person.prototype.drawImage = function (image) {
this.index ++;
/*清除画布*/
this.ctx.clearRect(0,0,this.canvasWidth,this.canvasHeight);
/*绘图*/
/*在精灵图上的定位 x 索引*/
/*在精灵图上的定位 y 方向*/
this.ctx.drawImage(image,
this.index * this.personWidth,this.direction * this.personHeight,
this.personWidth,this.personHeight,
this.x0 + this.stepX * this.stepSzie ,this.y0 + this.stepY * this.stepSzie,
this.personWidth,this.personHeight);
/*如果索引超出了 变成0*/
if(this.index >= 3){
this.index = 0;
}
};
new Person();
</script>
</body>
</html>
坐标变换(针对原点)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
//ctx.translate(100,100);
//ctx.scale(0.5,1);
//ctx.rotate(Math.PI/6);
var startAngle = 0;
ctx.translate(150,150);
setInterval(function () {
startAngle += Math.PI/180;
ctx.rotate(startAngle);
ctx.strokeRect(-50,-50,100,100);
},500);
</script>
</body>
</html>