Canvas
注释:基础知识来自: https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API
视频资源来自: https://www.bilibili.com/video/av53813293/?p=2
1.canvas简单绘制—线条绘制
1.1绘制直线
注意:设置canvas的width和height的时候,不能直接在样式列表中设置,只能通过
<canvas id="myCanvas" width="600" height="400"></canvas>
来设置;
原因是:通过样式列表设置的时候,只对画布大小进行缩放,并不能达到预期的效果。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="app">
<p>需求:在画板上绘制一条线段</p>
<p>要求:</p>
<ol>
<li>起点在画布的(100,100)位置处</li>
<li>线段长度:100</li>
</ol>
</div>
<!-- 1.创造画布 -->
<!-- 2.canvas默认大小 300*150 -->
<!-- 3.设置canvas的大小 width="600" height="400" -->
<canvas id="myCanvas" width="600" height="400"></canvas>
<!-- 4.准备绘制工具 -->
<!-- 5.利用工具绘图 -->
<script type="text/javascript">
// 1.获取画布
var myCanvas = document.querySelector("canvas");
// 2.获取上下文(绘制工具箱)
var ctx = myCanvas.getContext("2d")
// 3.移动画笔
ctx.moveTo(100,100);
// 4.绘制直线(轨迹、绘制路径,不可见)
ctx.lineTo(200,100);
// 5.描边
ctx.stroke();
</script>
</body>
</html>
回首发现,我们所画的线条,颜色并没有那么黑,而且高度也比1px大,
产生原因:对齐点是线的中心位置,会把先分成两个0.5px,显示的时候,不饱和而增加宽度
解决方案:前后移动0.5px
1.2.绘制平行线
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
// 移动前
ctx.moveTo(100,100.5);
ctx.lineTo(200,100.5);
// 移动后
ctx.moveTo(100,200);
ctx.lineTo(200,200)
ctx.stroke()
/*
回首发现,我们所画的线条,颜色并没有那么黑,而且高度也比1px大,
造成这个的原因是因为:对齐点是线的中心位置,会把先分成两个0.5px,显示的时候,不饱和而增加宽度
解决方案:前后移动0.5px
*/
</script>
</body>
</html>
1.3.绘制三条不同颜色、不同宽度的平行线
不同的线段,需要设置不同的样式,而且必须要以用 ctx.beginPath(); 开启新路径
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
// 开启新路径
ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.strokeStyle = "lightgreen";
ctx.lineWidth = 10;
ctx.stroke()
// 开启新路径
ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(200,200);
ctx.strokeStyle = "pink";
ctx.lineWidth = 20;
ctx.stroke();
// 开启新路径
ctx.beginPath();
ctx.moveTo(100,300);
ctx.lineTo(200,300);
ctx.strokeStyle = "lightblue";
ctx.lineWidth = 30;
ctx.stroke();
</script>
</body>
</html>
1.4.绘制一个填充颜色的三角形
当三角形的三边宽度较大时,如果直接用lineTo绘制三条边直接构成三角形,那么,末尾不能闭合缺角;此时使用
使用canvas自动闭合----关闭路径:ctx.closePath();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.lineTo(100,200);
// ctx.lineTo(100,100); //此时,末尾不能闭合缺角
// 使用canvas自动闭合----关闭路径
ctx.closePath();
ctx.lineWidth = 10
ctx.stroke();
// 填充颜色(默认黑色)
// ctx.fill();
</script>
</body>
</html>
1.5.绘制镂空正方形及非零环绕填充规则
重点:非零环绕填充规则
看一块区域是否填充
- 从这个区域拉一条直线出去
- 看这条直线相交的轨迹
- 如果顺时针轨迹则+1,逆时针则-1
- 所有轨迹计算值的总合
- 如果非0,则填充;为0则不填充
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="900" height="900"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
/* // 最大正方形
ctx.moveTo(0,0);
ctx.lineTo(0,400);
ctx.lineTo(400,400);
ctx.lineTo(400,0);
ctx.closePath(); */
// 中等正方形
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();
ctx.lineWidth = 3;
//改变填充颜色
ctx.fillStyle = "red"
ctx.fill();
</script>
</body>
</html>
1.6.线两端样式&拐点样式
线末端类型:lineCap,类型: butt(默认)、square、round
相交线的拐点:lineJoin,类型:miter(默认)、bevel、round
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script type="text/javascript">
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.lineCap = "butt"
// 相交线的拐点
ctx.lineJoin = "miter"
ctx.strokeStyle = "lightgreen";
ctx.lineWidth = 10;
ctx.stroke()
// 开启新路径
ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(200,100);
ctx.lineTo(300,200);
// 线末端类型
ctx.lineCap = "square"
// 相交线的拐点
ctx.lineJoin = "bevel"
ctx.strokeStyle = "pink";
ctx.lineWidth = 20;
ctx.stroke();
// 开启新路径
ctx.beginPath();
ctx.moveTo(100,300);
ctx.lineTo(200,180);
ctx.lineTo(300,300);
// 线末端类型
ctx.lineCap = "round"
// 相交线的拐点
ctx.lineJoin = "round"
ctx.strokeStyle = "lightblue";
ctx.lineWidth = 30;
ctx.stroke();
</script>
</body>
</html>
1.7.绘制虚线
绘制虚线:setLineDash([a1,a2,a3,…an]),[a1,a2,a3,…an]数组是用来描述数组的排列方式。
虚线的偏移:lineDashOffset,正值则往后偏移,负值则往前偏移。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
ctx.moveTo(100,100);
ctx.lineTo(300,100);
// [20]数组是用来描述数组的排列方式
// 获取虚线的排列方式 获取的是不重复的排列方式
ctx.setLineDash([20])
// 正值则往后偏移,负值则往前偏移
ctx.lineDashOffset = -20;
ctx.stroke();
</script>
</body>
</html>
1.8.canvas升级绘制
1.8.1渐变色绘制
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
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+',152,135)'
ctx.stroke();
}
</script>
</body>
</html>
1.8.2.绘制折线图
(1).绘制网格
绘制步骤:
- 绘制网格
- 网格大小
- 画多少条X轴方向的线
- 画多少条Y轴方向的线
- 通过什么方式去画:遍历的形式去画
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d")
// 设置网格大小
var grid = 10;
var canvasWidth = ctx.canvas.width;
var canvasHeight = ctx.canvas.height;
// 画多少条X方向上的线
var xLineTotal = Math.floor(canvasHeight/grid);
// 画多少条Y方向上的线
var yLineTotal = Math.floor(canvasWidth/grid);
console.log(xLineTotal+","+yLineTotal);
// 遍历的形式去画
// x方向
for (var i = 0; i < xLineTotal; i++) {
ctx.moveTo(0,i*grid-0.5);
ctx.lineTo(canvasWidth,i*grid-0.5)
ctx.strokeStyle = "#eee"
ctx.stroke();
}
// y方向
for (var i = 0; i < yLineTotal; i++) {
ctx.moveTo(i*grid-0.5,0);
ctx.lineTo(i*grid-0.5,canvasHeight)
ctx.strokeStyle = "#eee"
ctx.stroke();
}
</script>
(2).绘制坐标系
- 绘制坐标轴
- 确定原点距离画布旁边的距离
- 确定箭头的大小(等腰三角形)
- 确定原点
- 确定坐标轴的长度
- 绘制箭头填充
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
// - 绘制坐标轴
// - 确定原点距离画布旁边的距离
var space = 20;
// - 确定箭头的大小(等腰三角形)
var arrowsSize = 10;
// - 确定原点
// 计算原点
var canvasWidth = ctx.canvas.width;
var canvasHeight = ctx.canvas.height;
// 原点横坐标
var x0 = space;
var y0 = canvasHeight-space;
// - 确定坐标轴的长度
// - 绘制箭头填充
// x轴
ctx.beginPath();
ctx.moveTo(x0,y0);
ctx.lineTo(canvasWidth-space,y0);
// 绘制三角形
ctx.lineTo(canvasWidth-space-arrowsSize,y0-space/4);
ctx.lineTo(canvasWidth-space-arrowsSize,y0+space/4);
ctx.lineTo(canvasWidth-space,y0);
ctx.fill();
ctx.stroke();
// y轴
ctx.beginPath();
ctx.moveTo(x0,y0);
ctx.lineTo(space,space);
// 绘制三角形
ctx.lineTo(space+arrowsSize/2,space+arrowsSize)
ctx.lineTo(space-arrowsSize/2,space+arrowsSize)
ctx.lineTo(space,space);
ctx.fill();
ctx.stroke();
</script>
(3).绘制点
- 绘制点
- 点的尺寸
- 以坐标中心绘制点
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
// 绘制点
// 点的尺寸
// 以坐标中心绘制点
var doorinateOne = {
x:100,
y:150
};
var doorinateTwo = {
x:150,
y:100
};
var pointSize = 6;
ctx.beginPath()
ctx.moveTo(doorinateOne.x-pointSize/2,doorinateOne.y-pointSize/2)
ctx.lineTo(doorinateOne.x+pointSize/2,doorinateOne.y-pointSize/2)
ctx.lineTo(doorinateOne.x+pointSize/2,doorinateOne.y+pointSize/2)
ctx.lineTo(doorinateOne.x-pointSize/2,doorinateOne.y+pointSize/2)
ctx.closePath()
ctx.fill()
ctx.beginPath()
ctx.moveTo(doorinateTwo.x-pointSize/2,doorinateTwo.y-pointSize/2)
ctx.lineTo(doorinateTwo.x+pointSize/2,doorinateTwo.y-pointSize/2)
ctx.lineTo(doorinateTwo.x+pointSize/2,doorinateTwo.y+pointSize/2)
ctx.lineTo(doorinateTwo.x-pointSize/2,doorinateTwo.y+pointSize/2)
ctx.closePath()
ctx.fill()
ctx.beginPath()
ctx.moveTo(doorinateOne.x,doorinateOne.y)
ctx.lineTo(doorinateTwo.x,doorinateTwo.y)
ctx.closePath()
ctx.stroke()
</script>
(4).绘制折线图
- 构造函数
- 获取绘图上下文
- 获取画布大小
- 设定网格大小
- 设定坐标系间距
- 设定箭头大小
- 绘制点,设定点的大小
- 点的坐标,和数据有关系,数据可视化
- 行为方法
- 绘制网格
- 绘制坐标系
- 绘制所有点
- 数据坐标转化为canvas坐标
- x=原点x坐标+数据的x坐标
- y=原点y坐标-数据的y坐标
- 在进行点的绘制
- 再把各个点连接起来
- 数据坐标转化为canvas坐标
- 初始化
- 模拟数据
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style type="text/css">
canvas {
display: block;
border: 1px solid #ccc;
margin: 100px auto;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
// - 构造函数
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.arrowsSize = 10;
// - 绘制点,设定点的大小
this.pointSize = 6;
// - 点的坐标,和数据有关系,数据可视化
}
// - 行为方法
lineChart.prototype.init = function(data) {
this.drowGrid();
this.drowAixs();
this.drowPoint(data);
};
// - 绘制网格
lineChart.prototype.drowGrid = function() {
var xLineTotal = Math.floor(this.canvasHeight / this.gridSize);
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.strokeStyle = "#eee"
this.ctx.stroke();
}
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.strokeStyle = "#eee"
this.ctx.stroke();
}
};
// - 绘制坐标系
lineChart.prototype.drowAixs = function() {
var x0 = this.space;
var y0 = this.canvasHeight - this.space;
this.ctx.beginPath();
this.ctx.moveTo(x0, y0);
this.ctx.lineTo(this.canvasWidth - this.space, y0);
// 绘制三角形
this.ctx.lineTo(this.canvasWidth - this.space - this.arrowsSize, y0 - this.space / 4);
this.ctx.lineTo(this.canvasWidth - this.space - this.arrowsSize, y0 + this.space / 4);
this.ctx.lineTo(this.canvasWidth - this.space, y0);
this.ctx.strokeStyle = "#000"
this.ctx.fill();
this.ctx.stroke();
// y轴
this.ctx.beginPath();
this.ctx.moveTo(x0, y0);
this.ctx.lineTo(this.space, this.space);
// 绘制三角形
this.ctx.lineTo(this.space + this.arrowsSize / 2, this.space + this.arrowsSize)
this.ctx.lineTo(this.space - this.arrowsSize / 2, this.space + this.arrowsSize)
this.ctx.lineTo(this.space, this.space);
this.ctx.strokeStyle = "#000"
this.ctx.fill();
this.ctx.stroke();
};
// - 绘制所有点
lineChart.prototype.drowPoint = function(data) {
// - 数据坐标转化为canvas坐标
// - x=原点x坐标+数据的x坐标
// - y=原点y坐标-数据的y坐标
// - 在进行点的绘制
// - 再把各个点连接起来
var that = this;
var provCanvasX = 0;
var provCanvasY = 0;
data.forEach(function(item, i) {
var canvasX = 10 + item.x;
var canvasY = 10 - item.y;
// 绘制点
that.ctx.beginPath();
that.ctx.moveTo(canvasX-that.pointSize/2,canvasY-that.pointSize/2);
that.ctx.lineTo(canvasX+that.pointSize/2,canvasY-that.pointSize/2);
that.ctx.lineTo(canvasX+that.pointSize/2,canvasY+that.pointSize/2);
that.ctx.lineTo(canvasX-that.pointSize/2,canvasY+that.pointSize/2);
that.ctx.closePath();
that.ctx.strokeStyle = "#000"
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(provCanvasX,that.y0);
that.ctx.lineTo(canvasX,canvasY);
that.ctx.stroke();
}
provCanvasX = canvasX;
provCanvasY = canvasY;
})
};
// - 初始化
// - 模拟数据
var data = [
{
x: 100,
y: 120
},
{
x: 200,
y: 160
},
{
x: 300,
y: 240
},
{
x: 400,
y: 320
},
{
x: 500,
y: 80
}
];
var lineChart = new lineChart();
lineChart.init(data);
</script>
</body>
</html>
这个具体问题没找出来,绘制不出来
2.图形绘制
2.1.矩形
2.1.1.绘制矩形
矩形的绘制中。canvas提供了三种方法绘制矩形:
-
rect(x, y, width, height) 绘制矩形路径,不是独立路径
-
fillRect(x, y, width, height) 绘制一个填充的矩形
-
strokeRect(x, y, width, height) 绘制一个矩形的边框
-
clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="500"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
// - rect(x, y, width, height) 绘制矩形路径,不是独立路径
ctx.beginPath()
ctx.rect(100,100,100,50);
ctx.strokeStyle = "pink"
ctx.stroke();
// - fillRect(x, y, width, height) 绘制一个填充的矩形
ctx.fillRect(300,100,100,50);
// - strokeRect(x, y, width, height) 绘制一个矩形的边框
ctx.strokeRect(100,300,100,50)
// - clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明。
ctx.fillRect(300,300,100,150)
ctx.clearRect(325,325,50,100)
</script>
</body>
</html>
2.1.2.绘制渐变矩形
-
创建一个渐变方案
-
渐变是有长度的
-
x0,y0是起点、x1,y1是结束点
createLinearGradient(x0,y0,x1,y1);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
var lin = ctx.createLinearGradient(50,100,500,100);
lin.addColorStop(0,"pink");
lin.addColorStop(0.25,"lightblue");
lin.addColorStop(0.75,"blue");
lin.addColorStop(1,"darkblue");
ctx.fillStyle = lin;
ctx.fillRect(50,100,500,100)
</script>
</body>
</html>
2.2.曲线
2.2.1.绘制曲线
- 线是由点构成的
- 曲线可以由数学公式得来
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
for (var i = 0; i < ctx.canvas.width; i++) {
var x = i;
var y = 100*Math.sin(x/20+50)+200;
ctx.lineTo(x,y)
}
ctx.stroke();
</script>
</body>
</html>
2.2.2.圆弧的绘制
绘制圆弧,也就是绘制圆的一半:arc(x,y,r,startAngle,endAngle,[direction]);
- 确定圆心,(x,y)
- 确定半径,r
- 确定绘制的起始位置和绘制的结束位置,确定弧的长度和位置,startAngle、endAngle(弧度制)
- 取得绘制的方向 direction,顺时针false(默认),逆时针为true
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<!-- 需求,在画布中心绘制一个四分之三的圆,半径为150px -->
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
var w = ctx.canvas.width;
var h = ctx.canvas.height;
ctx.arc(w/2,h/2,150,0,Math.PI/2,true);
ctx.stroke();
</script>
</body>
</html>
2.2.3.绘制扇形
把起点放到圆心位置
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<!-- 需求,在画布中心绘制一个四分之三的圆,半径为150px -->
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
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.stroke();
</script>
</body>
</html>
2.2.4.绘制等份的扇形
绘制随机等份(1—10)的扇形,并且各个扇形颜色随机
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<!-- 需求,在画布中心绘制一个四分之三的圆,半径为150px -->
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
function getNum(){
var num = Math.floor(Math.random()*10);
return num
}
var num = getNum();
var angle = Math.PI*2/num;
var w = ctx.canvas.width;
var h = ctx.canvas.height;
var x0 = w/2;
var y0 = h/2;
// 随机获取颜色
function getRandomColor(){
var r = Math.floor(Math.random()*256);
var g = Math.floor(Math.random()*256);
var b = Math.floor(Math.random()*256);
var a = Math.random();
return "rgba("+r+","+g+","+b+","+a+")"
}
for (var i = 0; i < num; i++) {
var startAngle = i*angle;
var endAngle = (i+1)*angle;
ctx.beginPath();
ctx.moveTo(x0,y0);
ctx.arc(x0,y0,150,startAngle,endAngle);
ctx.fillStyle = getRandomColor();
ctx.fill();
}
</script>
</body>
</html>
2.2.5.根据数据画饼状图
- 准备统计的数据
- 把数据转化成弧度
- 在饼图表示出来
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas {
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<!-- 需求,在画布中心绘制一个四分之三的圆,半径为150px -->
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
var data = [10, 30, 2, 15];
var angleList = [];
var total = 0;
var w = ctx.canvas.width;
var h = ctx.canvas.height;
var x0 = w / 2;
var y0 = h / 2;
function getRandomColor() {
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
return "rgba(" + r + "," + g + "," + b + ")"
}
data.forEach(function(item, i) {
total += item;
})
data.forEach(function(item, i) {
var angle = Math.PI * 2 * (item / total);
angleList.push(angle);
})
console.log(angleList);
var startAngle = 0;
angleList.forEach(function(item, i) {
var endAngle = startAngle + item;
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.arc(x0, y0,150,startAngle, endAngle);
ctx.fillStyle = getRandomColor();
ctx.fill();
startAngle = endAngle;
})
</script>
</body>
</html>
2.2.6.绘制文本
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas {
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<!-- 需求,在画布中心绘制一个四分之三的圆,半径为150px -->
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
var w = ctx.canvas.width;
var h = ctx.canvas.height;
var x0 = w / 2;
var y0 = h / 2;
var string = "你好,我是程序员"
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()
ctx.beginPath();
ctx.font = "40px Microsoft YaHei"
ctx.textAlign = "center";
ctx.textBaseline = "middle"
ctx.fillText(string,x0,y0)
ctx.beginPath();
var textWidth = ctx.measureText(string).width;
ctx.moveTo(x0-textWidth/2,y0+20);
ctx.lineTo(x0+textWidth/2,y0+20);
ctx.strokeStyle = "#000";
ctx.stroke();
</script>
</body>
</html>
2.2.7.绘制带数据的饼状图
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas {
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
// 根据数据绘制一个饼状图
// 绘制标题,从扇形弧中心伸出一条直线再画一条横线,横线上写该区域的文字说明
// 在画布左上角,绘制说明
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 = 40;
// 说明矩形的大小
this.rectW = 30;
this.rectH = 16;
this.space = 20;
}
pieChart.prototype.init = function(data) {
this.drowPie(data)
};
pieChart.prototype.drowPie = function(data) {
var that = this;
// 转化弧度
var angleList = this.transformAngle(data);
// 绘制饼图
var startAngle = 0;
angleList.forEach(function(item, i) {
/* 当前结束弧度等于下次其实弧度 */
var endAngle = startAngle + item.angle;
ctx.beginPath();
ctx.moveTo(that.x0, that.y0);
ctx.arc(that.x0, that.y0, that.radius, startAngle, endAngle)
var color = ctx.fillStyle = that.getRandomColor();
ctx.fill();
that.drowTitle(startAngle, item.angle, color, item.title);
// 下一次要使用当前这一次的弧度
that.drowDesc(i,item.title);
startAngle = endAngle;
})
};
pieChart.prototype.drowTitle = function(startAngle, angle, color, title) {
// 确定伸出去的线,通过圆心,通过伸出去的点 确定这个线
// 确定伸出去的点,需要确定伸出去的长度
// 固定伸出去线的长度,
// 计算这个点的坐标
// 需要根据角度和斜边的长度
// 使用弧度 当前扇形的起始弧度+对应弧度的一半
// 半径+伸出去的长度
// outX = x0+cos(angle)*(r+outLine);
// 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 = "12px 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.font = "12px Microsoft YaHei";
this.ctx.fillText(title, outX, outY);
};
pieChart.prototype.drowDesc = function(index,title) {
// 绘制说明
// 矩形的大小
// 距离上和左边之间的距离
// 每个矩形之间的距离
this.ctx.fillRect(this.space, this.space + index * (this.rectH + this.space), this.rectW, this.rectH);
// 绘制文字
this.ctx.beginPath();
this.ctx.textAlign = "left";
this.ctx.textBaseline = "top"
this.ctx.fillText(title,this.rectW + this.space+10,this.space + index * (this.rectH + this.space));
};
pieChart.prototype.transformAngle = function() {
// 返回数据内容包含弧度
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);
var a = Math.random();
var rgb = r + "," + g + "," + b;
if (rgb != "255,255,255") {
return "rgba(" + rgb + ")"
}
}
var data = [{
title: "15~20岁",
num: 6,
angle: 0
},
{
title: "21~30岁",
num: 31,
angle: 0
},
{
title: "31~40岁",
num: 15,
angle: 0
},
{
title: "41~50岁",
num: 9,
angle: 0
},
{
title: "51岁以上",
num: 3,
angle: 0
}
];
var pieChart = new pieChart();
pieChart.init(data);
</script>
</body>
</html>
3.图片绘制
3.1.图片的加载
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d")
var image = new Image();
image.onload = function(){
console.log(image);
}
image.src = "img/02.gif"
</script>
</body>
</html>
3.2.三种绘制方式
-
drawImage(image, x, y)
其中
image
是 image 或者 canvas 对象,x
和y 是其在目标 canvas 里的起始坐标。
-
drawImage(image, x, y, width, height)
这个方法多了2个参数:
width
和height,
这两个参数用来控制 当向canvas画入时应该缩放的大小 -
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。其它8个参数最好是参照右边的图解,前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style type="text/css">
canvas{
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d")
var image = new Image();
image.onload = function(){
console.log(image);
// 三个参数
// ctx.drawImage(image,50,50);
// 五个参数
// ctx.drawImage(image,100,50,200,200);
// 九个参数
ctx.drawImage(image,400,400,400,400,200,200,200,200);
}
image.src = "img/bcg.jpeg"
</script>
</body>
</html>
3.3.坐标转换
- 平移移动画布的原点
- translate(x,y)参数表示移动目标点的位置
- 缩放
- scale(x,y)参数表示宽高的缩放比例
- 旋转
- rotate(x,y)参数表示旋转角度