Canvas学习笔记

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坐标
      • 在进行点的绘制
      • 再把各个点连接起来
  • 初始化
    • 模拟数据
<!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 对象,xy 是其在目标 canvas 里的起始坐标。

  • drawImage(image, x, y, width, height)

    这个方法多了2个参数:widthheight,这两个参数用来控制 当向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)参数表示旋转角度
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值