目录
一、初识canvas
1.1 基本使用
1.2 示例
1.1 注意点
二、canvas线条相关属性
2.1 常用属性
2.2 示例
2.3 绘制多根线条
c.示例:
三、canvas绘制简单图形
3.1 绘制三角形
3.2 路径绘制
3.3 矩形绘制
3.4 绘制虚线
3.5 绘制表格
3.6 绘制坐标系
3.7 绘制数据点
3.8 绘制折线图
3.9 绘制柱状图
四、渐变背景颜色
4.1 设置图形渐变背景颜色步骤
4.2 绘制圆弧
4.3 绘制饼状图
4.4 绘制文字
4.5 图片绘制
五、绘制动画
六、canvs形变
七、事件绑定
Canvas是H5新增的一个标签, 我们可以通过JS在这个标签上绘制各种图案
Canvas 拥有多种绘制路径、矩形、圆形、字符以及图片的方法
Canvas可以替换像flash等其他做动画或游戏的插件的一个标签,能够大大减小页面的结构大小。让页面加载速度变快。
只不过div是存放元素的,而canvas则是提供了一个区域用来绘制图形。
内部的所有内容或图形都需要通过js脚本来完成。
首先,创建canvas画布,在body标签中创建一个canvas标签
其次,进行相关样式设置
最后,如果想要在画布上进行操作,则需要通过脚本来创建一个‘画家’,来帮助我们进行内容绘制。
*{
margin: 0;
padding: 0;
}
canvas{
background: red;
}
// 2.通过js代码拿到canvas标签
let oCanvas = document.querySelector("canvas");
// 3.从canvas标签中获取到绘图工具
let oCtx = oCanvas.getContext("2d");
// 4.通过绘图工具在canvas标签上绘制图形
// 4.1设置路径的起点
oCtx.moveTo(50, 50);
// 4.2设置路径的终点
oCtx.lineTo(200, 50);
// 4.3告诉canvas将这些点连接起来
oCtx.stroke();
不能通过CSS设置画布的宽高:通过CSS设置画布宽高会在默认宽高的基础上拉伸,如果需要设置canvas宽高请通过元素行内属性width和height设置
butt 无端点 round圆角端点 square方块端点
round圆弧连接 bevel截面连接 miter直角连接
*{
margin: 0;
padding: 0;
}
canvas{
background: red;
}
示例1:
//拿到画布
let oCanvas = document.querySelector("canvas");
//拿到绘制工具
let ctx = oCanvas.getContext("2d");
//修改线条高度
ctx.lineWidth = 10;
//修改线条颜色
ctx.strokeStyle = "#fff";
//修改线条两端样式
// ctx.lineCap="";
// ctx.lineCap="square";
ctx.lineCap="round";
//设置虚线
ctx.setLineDash([10,5,20]);
//利用后置工具绘制直线
// 设置起始位置
ctx.moveTo(50,50.5);
// 设置路径上的点
ctx.lineTo(200,50.5);
ctx.lineTo(200,150.5);
ctx.lineTo(50,150.5);
ctx.lineTo(50,50.5);
// 绘制已定义的路径
ctx.stroke();
示例2:
var huaban = document.querySelector('canvas');
var ctx = huaban.getContext('2d');
ctx.beginPath(); //开始
ctx.moveTo(40, 80); //起始位置
ctx.lineTo(230, 80);
ctx.lineTo(230, 180);
ctx.lineWidth = 5; //线型宽度
ctx.lineCap = 'butt'; //端点类型 无端点
ctx.lineJoin = 'miter'; //设置连接 直角连接
ctx.setLineDash([10, 5, 20]); //设置虚线 第一段长度,第二段长度,第三段长度...
ctx.stroke();
ctx.closePath(); //结束
a.多根线条注意点:
b.如何给每根线条单独设置路径样式?
每根线条都开启一个新的路径即可
//拿到画布
let oCanvas = document.querySelector("canvas");
//拿到绘制工具
let ctx = oCanvas.getContext("2d");
// //修改线条两端样式
// // ctx.lineCap="";
// // ctx.lineCap="square";
// ctx.lineCap="round";
//设置虚线
// ctx.setLineDash([10,5,20]);
//利用后置工具绘制直线
// 设置起始位置
ctx.moveTo(50, 50);
// 设置路径上的点
ctx.lineTo(200, 50);
// 修改线条高度
ctx.lineWidth = 20;
//修改线条颜色
ctx.strokeStyle = "blue";
// 绘制已定义的路径
ctx.stroke();
ctx.beginPath(); // 重新开启一个路径
ctx.moveTo(50, 100);
ctx.lineTo(200, 100);
ctx.lineWidth = 10; // 重新设置当前路径样式
ctx.strokeStyle = "white";
ctx.stroke();
ctx.beginPath(); // 重新开启一个路径
ctx.moveTo(50, 150);
ctx.lineTo(200, 150);
ctx.lineWidth = 15; // 重新设置当前路径样式
ctx.strokeStyle = "green";
ctx.stroke();
closePath():自动创建从当前点回到起始点的路径
lineJoin():设置相交线的拐点样式 miter(默认)、round、bevel
如果通过lineTo()来闭合图形, 那么是不能很好的闭合
默认情况下不会自动从最后一个点连接到起点
* {
margin: 0;
padding: 0;
}
canvas {
background: red;
display: block;
margin: 0 auto;
}
//拿到画布
let oCanvas = document.querySelector("canvas");
//拿到绘制工具
let ctx = oCanvas.getContext("2d");
ctx.moveTo(50,50);
ctx.lineTo(200,50);
ctx.lineTo(200,200);
// ctx.lineTo(50,50);
ctx.closePath(); // 自动创建从当前点回到起始点的路径
ctx.lineWidth = 10;
// 设置相交线的拐点样式 miter(默认)、round、bevel
ctx.lineJoin = "round";
ctx.stroke();
canvas {
border: 1px solid;
}
* {
margin: 0;
padding: 0;
}
canvas {
background: red;
display: block;
margin: 0 auto;
}
let oCanvas = document.querySelector("canvas");
let oCtx = oCanvas.getContext("2d");
oCtx.moveTo(100, 100);
oCtx.lineTo(300, 100);
oCtx.lineTo(300, 300);
oCtx.lineTo(100, 300);
oCtx.closePath();
oCtx.moveTo(250, 150);
oCtx.lineTo(150, 150);
oCtx.lineTo(150, 250);
oCtx.lineTo(250, 250);
oCtx.closePath();
/*
注意点: 只要没有手动开启新的路径, 那么使用的都是默认路径
如果都是默认路径, 那么设置的样式在同一个路径中都是有效的
* */
oCtx.fill();
/*
对于同一路径,在填充的时候会遵循非零环绕规则
从当前的区域拉出一条直线, 遇到顺时针相交的线就+1, 遇到逆时针相交的线就-1
最终计算的结果如果是0就不填充, 如果不是0就填充
* */
绘制填充矩形:ctx.fillRect(横,纵,宽,高);
绘制描边矩形:ctx.strokeRect(横,纵,宽,高);
擦除矩形区域:ctx.clearRect(横,纵,宽,高);
ctx.fillStyle='blue';
ctx.fillRect(50,70,50,50);
ctx.strokeRect(150,70,50,50);
ctx.clearRect(75,70,100,50);
setLineDash():设置
lineDashOffset():设置偏移位
//拿到画布
let oCanvas = document.querySelector("canvas");
//拿到绘制工具
let ctx = oCanvas.getContext("2d");
ctx.moveTo(20,120);
ctx.lineTo(280,120);
ctx.lineWidth = 2;
ctx.strokeStyle = "white";
// ctx.setLineDash([2,8]);
ctx.setLineDash([2,8,10]);
// console.log(ctx.getLineDash());
//设置虚线的偏移位
ctx.lineDashOffset = -200;
ctx.stroke();
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
//拿到画布
let oCanvas = document.querySelector("canvas");
//拿到绘制工具
let ctx = oCanvas.getContext("2d");
//定义变量,保存小方格的尺寸
let gridSize = 10;
//拿到 canvas 的宽高
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
// 计算在垂直和水平方向可以画多少条横线
let row = Math.floor(canvasHeight / gridSize);
let col = Math.floor(canvasWidth / gridSize);
//绘制垂直方向的横线
for (let i = 0; i < row; i++) {
ctx.beginPath();
ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点
ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点
ctx.stroke();
}
//绘制水平方向的横线
for (let i = 0; i < col; i++) {
ctx.beginPath();
ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点
ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点
ctx.stroke();
}
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
//拿到画布
let oCanvas = document.querySelector("canvas");
//拿到绘制工具
let ctx = oCanvas.getContext("2d");
//定义变量,保存小方格的尺寸
let gridSize = 50;
//拿到 canvas 的宽高
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
// 计算在垂直和水平方向可以画多少条横线
let row = Math.floor(canvasHeight / gridSize);
let col = Math.floor(canvasWidth / gridSize);
//绘制垂直方向的横线
for (let i = 0; i < row; i++) {
ctx.beginPath();
ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点
ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点
ctx.strokeStyle = "#ccc";
ctx.stroke();
}
//绘制水平方向的横线
for (let i = 0; i < col; i++) {
ctx.beginPath();
ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点
ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点
ctx.strokeStyle = "#ccc";
ctx.stroke();
}
//计算坐标系原点的位置
let originX = gridSize;
let originY = canvasHeight - gridSize;
//计算X轴终点位置
let endX = canvasWidth - gridSize;
//绘制X轴
ctx.beginPath();
ctx.moveTo(originX,originY);
ctx.lineTo(endX,originY);
ctx.strokeStyle = "#f40";
ctx.stroke();
//绘制X轴的箭头
ctx.lineTo(endX -10,originY + 5);
ctx.lineTo(endX -10,originY - 5);
ctx.lineTo(endX,originY);
ctx.fill();
//计算Y轴终点位置
let endY = gridSize;
//绘制Y轴
ctx.beginPath();
ctx.moveTo(originX,originY);
ctx.lineTo(originX,endY);
ctx.strokeStyle = "#f40";
ctx.stroke();
//绘制Y轴的箭头
ctx.lineTo(originX -5,endY + 10);
ctx.lineTo(originX +5,endY + 10);
ctx.lineTo(originX,endY);
ctx.fill();
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
//拿到画布
let oCanvas = document.querySelector("canvas");
//拿到绘制工具
let ctx = oCanvas.getContext("2d");
//定义变量,保存小方格的尺寸
let gridSize = 50;
//拿到 canvas 的宽高
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
// 计算在垂直和水平方向可以画多少条横线
let row = Math.floor(canvasHeight / gridSize);
let col = Math.floor(canvasWidth / gridSize);
//绘制垂直方向的横线
for (let i = 0; i < row; i++) {
ctx.beginPath();
ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点
ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点
ctx.strokeStyle = "#ccc";
ctx.stroke();
}
//绘制水平方向的横线
for (let i = 0; i < col; i++) {
ctx.beginPath();
ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点
ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点
ctx.strokeStyle = "#ccc";
ctx.stroke();
}
//计算坐标系原点的位置
let originX = gridSize;
let originY = canvasHeight - gridSize;
//计算X轴终点位置
let endX = canvasWidth - gridSize;
//绘制X轴
ctx.beginPath();
ctx.moveTo(originX, originY);
ctx.lineTo(endX, originY);
ctx.strokeStyle = "#f40";
ctx.stroke();
//绘制X轴的箭头
ctx.lineTo(endX - 10, originY + 5);
ctx.lineTo(endX - 10, originY - 5);
ctx.lineTo(endX, originY);
ctx.fill();
//计算Y轴终点位置
let endY = gridSize;
//绘制Y轴
ctx.beginPath();
ctx.moveTo(originX, originY);
ctx.lineTo(originX, endY);
ctx.strokeStyle = "#f40";
ctx.stroke();
//绘制Y轴的箭头
ctx.lineTo(originX - 5, endY + 10);
ctx.lineTo(originX + 5, endY + 10);
ctx.lineTo(originX, endY);
ctx.fill();
// 拿到服务器返回数据
let list = [
{
x: 100,
y: 300,
},
{
x: 200,
y: 200,
},
{
x: 300,
y: 250,
},
{
x: 400,
y: 100,
},
];
let dotLocation = {
x: 100,
y: 300,
};
let dotSize = 20;
for (let i = 0; i < list.length; i++) {
ctx.beginPath();
ctx.moveTo(list[i].x - dotSize / 2, list[i].y - dotSize / 2);
ctx.lineTo(list[i].x + dotSize - dotSize / 2, list[i].y - dotSize / 2);
ctx.lineTo(
list[i].x + dotSize - dotSize / 2,
list[i].y + dotSize - dotSize / 2
);
ctx.lineTo(list[i].x - dotSize / 2, list[i].y + dotSize - dotSize / 2);
ctx.closePath();
ctx.fill();
}
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
class LineChart {
constructor(width = 300, height = 150) {
// 1.创建canvas
this.canvas = document.createElement("canvas");
this.canvas.width = width;
this.canvas.height = height;
document.body.appendChild(this.canvas);
// 2.拿到绘图工具
this.ctx = this.canvas.getContext("2d");
}
//画小格子
drawGrid(gridSize = 20) {
let ctx = this.ctx;
//拿到 canvas 的宽高
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
// 计算在垂直和水平方向可以画多少条横线
let row = Math.floor(canvasHeight / gridSize);
let col = Math.floor(canvasWidth / gridSize);
//绘制垂直方向的横线
for (let i = 0; i < row; i++) {
ctx.beginPath();
ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点
ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点
ctx.strokeStyle = "#ccc";
ctx.stroke();
}
//绘制水平方向的横线
for (let i = 0; i < col; i++) {
ctx.beginPath();
ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点
ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点
ctx.strokeStyle = "#ccc";
ctx.stroke();
}
}
//画坐标系
drawCoor(gridSize = 20) {
let ctx = this.ctx;
let canvasWidth = this.ctx.canvas.width;
let canvasHeight = this.ctx.canvas.height;
//计算坐标系原点的位置
let originX = gridSize;
let originY = canvasHeight - gridSize;
//计算X轴终点位置
let endX = canvasWidth - gridSize;
//绘制X轴
ctx.beginPath();
ctx.moveTo(originX, originY);
ctx.lineTo(endX, originY);
ctx.strokeStyle = "#f40";
ctx.stroke();
//绘制X轴的箭头
ctx.lineTo(endX - 10, originY + 5);
ctx.lineTo(endX - 10, originY - 5);
ctx.lineTo(endX, originY);
ctx.fill();
//计算Y轴终点位置
let endY = gridSize;
//绘制Y轴
ctx.beginPath();
ctx.moveTo(originX, originY);
ctx.lineTo(originX, endY);
ctx.strokeStyle = "#f40";
ctx.stroke();
//绘制Y轴的箭头
ctx.lineTo(originX - 5, endY + 10);
ctx.lineTo(originX + 5, endY + 10);
ctx.lineTo(originX, endY);
ctx.fill();
}
//绘制数据点
drawDot(list, dotSize = 10) {
let ctx = this.ctx;
for (let i = 0; i < list.length; i++) {
ctx.beginPath();
ctx.moveTo(list[i].x - dotSize / 2, list[i].y - dotSize / 2);
ctx.lineTo(
list[i].x + dotSize - dotSize / 2,
list[i].y - dotSize / 2
);
ctx.lineTo(
list[i].x + dotSize - dotSize / 2,
list[i].y + dotSize - dotSize / 2
);
ctx.lineTo(
list[i].x - dotSize / 2,
list[i].y + dotSize - dotSize / 2
);
ctx.closePath();
ctx.fill();
}
}
//绘制折线
drawLine(list) {
let ctx = this.ctx;
ctx.beginPath();
for (let i = 0; i < list.length; i++) {
if (i === 0) {
ctx.moveTo(list[i].x, list[i].y);
} else {
ctx.lineTo(list[i].x, list[i].y);
}
}
ctx.stroke();
}
}
// 拿到服务器返回数据
let list = [
{
x: 100,
y: 300,
},
{
x: 200,
y: 200,
},
{
x: 300,
y: 250,
},
{
x: 400,
y: 100,
},
];
let dotLocation = {
x: 100,
y: 300,
};
let lineChart = new LineChart(500, 400);
lineChart.drawGrid(50);
lineChart.drawCoor(50);
lineChart.drawDot(list, 20);
lineChart.drawLine(list);
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
class LineChart {
constructor(width = 300, height = 150) {
// 1.创建canvas
this.canvas = document.createElement("canvas");
this.canvas.width = width;
this.canvas.height = height;
document.body.appendChild(this.canvas);
// 2.拿到绘图工具
this.ctx = this.canvas.getContext("2d");
}
//画小格子
drawGrid(gridSize = 20) {
let ctx = this.ctx;
//拿到 canvas 的宽高
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
// 计算在垂直和水平方向可以画多少条横线
let row = Math.floor(canvasHeight / gridSize);
let col = Math.floor(canvasWidth / gridSize);
//绘制垂直方向的横线
for (let i = 0; i < row; i++) {
ctx.beginPath();
ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点
ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点
ctx.strokeStyle = "#ccc";
ctx.stroke();
}
//绘制水平方向的横线
for (let i = 0; i < col; i++) {
ctx.beginPath();
ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点
ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点
ctx.strokeStyle = "#ccc";
ctx.stroke();
}
}
//画坐标系
drawCoor(gridSize = 20) {
let ctx = this.ctx;
let canvasWidth = this.ctx.canvas.width;
let canvasHeight = this.ctx.canvas.height;
//计算坐标系原点的位置
let originX = gridSize;
let originY = canvasHeight - gridSize;
//计算X轴终点位置
let endX = canvasWidth - gridSize;
//绘制X轴
ctx.beginPath();
ctx.moveTo(originX, originY);
ctx.lineTo(endX, originY);
ctx.strokeStyle = "#f40";
ctx.stroke();
//绘制X轴的箭头
ctx.lineTo(endX - 10, originY + 5);
ctx.lineTo(endX - 10, originY - 5);
ctx.lineTo(endX, originY);
ctx.fill();
//计算Y轴终点位置
let endY = gridSize;
//绘制Y轴
ctx.beginPath();
ctx.moveTo(originX, originY);
ctx.lineTo(originX, endY);
ctx.strokeStyle = "#f40";
ctx.stroke();
//绘制Y轴的箭头
ctx.lineTo(originX - 5, endY + 10);
ctx.lineTo(originX + 5, endY + 10);
ctx.lineTo(originX, endY);
ctx.fill();
}
//绘制矩形
drawRectangle(list,gridSize=20) {
let ctx = this.ctx;
let canvasHeight = this.ctx.canvas.height;
let originY = canvasHeight - gridSize;
//绘制矩形
for (let i = 0; i < list.length; i++) {
let barHeight = originY - list[i].y;
ctx.fillRect(list[i].x, list[i].y, gridSize, barHeight);
}
}
}
// 拿到服务器返回数据
let list = [
{
x: 100,
y: 300,
},
{
x: 200,
y: 200,
},
{
x: 300,
y: 250,
},
];
let dotLocation = {
x: 100,
y: 300,
};
let lineChart = new LineChart(500, 400);
lineChart.drawGrid(50);
lineChart.drawCoor(50);
lineChart.drawRectangle(list,50);
和普通标签一样我们也可以给填充的图形设置线性渐变和径向渐变的背景颜色
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
/* 1.创建渐变方案
可以通过x0,y0 / x1,y1确定渐变的方向和渐变的范围
* */
let linearGradient = ctx.createLinearGradient(100, 100, 300, 300);
// ctx.createRadialGradient();//径向渐变
/*2.指定渐变的范围
第一个参数是一个百分比 0~1
第二个参数是一个颜色
* */
linearGradient.addColorStop(0, "green");
linearGradient.addColorStop(0.5, "yellow");
linearGradient.addColorStop(1, "blue");
/*3.将渐变背景颜色设置给对应的图形
**/
ctx.fillStyle = linearGradient;
ctx.fillRect(100, 100, 200, 200);
a.基本概念(请翻开初中数学课本) 哈哈~
角度: 一个圆360度, 一个半圆是180度
弧度: 一个圆2π, 一个半圆π
b.角度转换弧度公式:
∵ 180角度 = π弧度
∴ 1角度 = π/180;
∴ 弧度 = 角度 * π/180;
90角度 * π/180 = π/2
c.弧度转换角度公式:
∵ π弧度 = 180角度
∴ 1弧度 = 180/π
∴ 角度 = 弧度 * 180/π
π/2 * 180/π = 180/2 = 90度
ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);
ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,true);
false就是顺时针绘制, true就是逆时针绘制
false先开始后结束, true是先结束后开始,都是顺时针方向画弧
示例1:画圆和半圆
canvas {
border: 1px solid;
}
var huaban = document.querySelector('canvas');
var ctx = huaban.getContext('2d');
ctx.beginPath(); //开始落脚
//ctx.arc(150, 150, 50, 0 * Math.PI, 1 * Math.PI, false);//半圆
ctx.arc(150, 150, 50, 0 * Math.PI, 2 * Math.PI, false);//圆
// ctx.stroke();
ctx.fillStyle = 'skyblue'; //填充
ctx.fill();
ctx.closePath(); //结束
示例1:绘制扇形
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
// 1.拿到canvas
let canvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let ctx = canvas.getContext("2d");
//设置起点
ctx.moveTo(100,100);
//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);
ctx.arc(100,100,100,0,Math.PI/2);
ctx.closePath();
// ctx.stroke();
ctx.fill();
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
// 1.拿到canvas
let canvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let ctx = canvas.getContext("2d");
//计算圆心的位置
let rx = ctx.canvas.width / 2;
let ry = ctx.canvas.height / 2;
/*
//绘制第一个扇形
//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);
ctx.moveTo(rx, ry);
ctx.arc(rx, ry, 100, 0, Math.PI / 2);
ctx.fillStyle = randomColor();
ctx.fill();
//绘制第二个扇形
//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);
ctx.beginPath(); // 开启新路径
ctx.moveTo(rx, ry);
ctx.arc(rx, ry, 100, Math.PI / 2, Math.PI);
ctx.fillStyle = randomColor();
ctx.fill();
//绘制第三个扇形
//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);
ctx.beginPath(); // 开启新路径
ctx.moveTo(rx, ry);
ctx.arc(rx, ry, 100, Math.PI, Math.PI + Math.PI / 2);
ctx.fillStyle = randomColor();
ctx.fill();
//绘制第四个扇形
//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);
ctx.beginPath(); // 开启新路径
ctx.moveTo(rx, ry);
ctx.arc(rx, ry, 100, Math.PI + Math.PI / 2, Math.PI * 2);
ctx.fillStyle = randomColor();
ctx.fill();
*/
let startAngle = 0;//开始的弧度
for (let i = 1; i <= 4; i++) {
// 结束的弧度
let endAngle = i * Math.PI / 2;
//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);
ctx.beginPath(); // 开启新路径
ctx.moveTo(rx, ry);
ctx.arc(rx, ry, 100, startAngle, endAngle);
ctx.fillStyle = randomColor();
ctx.fill();
// 上一次结束的角度是下一次的起始角度
startAngle = endAngle;
}
//随机生成圆弧填充颜色
function randomColor() {
let r = Math.floor(Math.random() * 256);
let g = Math.floor(Math.random() * 256);
let b = Math.floor(Math.random() * 256);
return `rgb(${r},${g},${b})`;
}
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
// 1.拿到canvas
let canvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let ctx = canvas.getContext("2d");
//3.绘制参考线
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
ctx.moveTo(0,canvasHeight / 2);
ctx.lineTo(canvasWidth,canvasHeight / 2);
ctx.stroke();
ctx.moveTo(canvasWidth / 2,0);
ctx.lineTo(canvasWidth / 2,canvasHeight);
ctx.stroke();
//4.绘制文字
let str = '世界很大';
//通过 font 属性可以设置文字的大小和样式
ctx.font = "50px 微软雅黑";
//textBaseline:修改文字垂直方向的对齐方式
// 在对齐的时候是以绘制文字的y作为参考点进行对齐的
//textBaseline = top/middle/bottom
ctx.textBaseline = "middle";
//textAlign:修改文字水平方向对齐方式
// 在对齐的时候是以文字的x作为参考点进行的
//textAlign = star/end/center
ctx.textAlign = "end";
/**
* ctx.strokeText(需要绘制的文字,绘制的位置);
* 在绘制文字的时候是以文字的左下角作为参考点进行绘制
*/
// ctx.strokeText(str,canvasWidth / 2,canvasHeight / 2); 或
// fillText()绘制的文字是实心;strokeText()绘制的文字是空心
ctx.fillText(str,canvasWidth / 2,canvasHeight / 2);
描述:canvas中绘制图片必须等到图片完全加载成功之后再上屏,否则就会绘制失败。
方法:
ctx.drawImage();
语法:
如果只有三个参数, 那么第一个参数就是需要绘制的图片,后面的两个参数是指定图片从什么位置开始绘制
oCtx.drawImage(oImg, 100, 100);
如果只有五个参数, 那么第一个参数就是需要绘制的图片,第二和第三个参数是指定图片从什么位置开始绘制,第四、第五两个参数是指定图片需要拉伸到多大
oCtx.drawImage(oImg, 100, 100, 100, 100);
如果有九个参数, 那么第一个参数就是需要绘制的图片,第2~3个参数指定图片上定位的位置,第4~5个参数指定从定位的位置开始截取多大的图片,第6~7个参数指定图片从什么位置开始绘制,最后的两个参数是指定图片需要拉伸到多大
示例:
canvas {
border: 1px solid;
}
var huaban = document.querySelector('canvas');
var ctx = huaban.getContext('2d');
ctx.beginPath(); //开始
//创建图片
var tempImage = new Image();
//加载图片
tempImage.src = 'img/timg.jpg';
//图片完全加载后再绘制
tempImage.onload = function() {
//将加载的图片绘制到canvas上
ctx.drawImage(tempImage, 190, 65, 210, 80, 50, 50, 80, 100);
};
ctx.closePath(); //结束
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
// 1.拿到canvas
let canvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let ctx = canvas.getContext("2d");
//3.加载图片
let oImg = new Image();
oImg.onload = function (){
//3.1计算每一张图片的宽高
let imageWidth = oImg.width;
let imageHeight = oImg.height;
let personWidth = imageWidth / 4;
let personHeight = imageHeight / 4;
//3.2计算绘制的位置
let canvasWidth = ctx.canvas.width;
let canvasHeight = ctx.canvas.height;
let originX = canvasWidth / 2 - personWidth / 2;
let originY = canvasHeight / 2 - personHeight / 2;
//3.3绘制图片
ctx.drawImage(oImg,0,personHeight *2,personWidth,personHeight,originX,originY,personWidth,personHeight);
//3.4实现逐帧动画
let index = 1;
setInterval(function(){
// 清除以前绘制的图片
ctx.clearRect(0,0,canvasWidth,canvasHeight);
//重新绘制
ctx.drawImage(oImg,index * personWidth,personHeight *2,personWidth,personHeight,originX,originY,personWidth,personHeight);
index++;
if(index > 3){
index = 0;
}
},50);
};
oImg.src = "images/person.png";
对上面的代码进行封装:
// 1.拿到canvas
let canvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let ctx = canvas.getContext("2d");
/*
面向对象思想:
找到小人对象, 你给我画到指定的位置, 你给我走起来, 你给我停下来
* */
class Person {
constructor(canvas, x, y) {
this.canvas = canvas;
this.x = x;
this.y = y;
this.ctx = this.canvas.getContext("2d");
this.index = 1;
this.timeId = null;
// 0正面/1左面/2右面/3后面
this.direction = 0;
}
//绘制
render() {
//1.加载图片
let oImg = new Image();
oImg.onload = () => {
//1.1计算每一张图片的宽高
let imageWidth = oImg.width;
let imageHeight = oImg.height;
let personWidth = imageWidth / 4;
let personHeight = imageHeight / 4;
//1.2绘制图片
this.ctx.drawImage(
oImg, // 需要绘制的图片
0, //图片定位的位置
this.direction * personHeight, //图片定位的位置
personWidth, // 图片裁剪的大小
personHeight, // 图片裁剪的大小
this.x, // 图片绘制的位置
this.y, // 图片绘制的位置
personWidth, // 指定图片绘制大小
personHeight // 指定图片绘制大小
);
this.oImg = oImg;
this.personWidth = personWidth;
this.personHeight = personHeight;
};
oImg.src = "images/person.png";
}
//运动方法
run(stepX, stepY) {
let canvasWidth = this.ctx.canvas.width;
let canvasHeight = this.ctx.canvas.height;
clearInterval(this.timeId);
this.timeId = setInterval(() => {
if (stepX !== 0) {
this.x += stepX;
}
if (stepY !== 0) {
this.y += stepY;
}
// 清除以前绘制的图片
this.ctx.clearRect(0, 0, canvasWidth, canvasHeight);
//重新绘制
this.ctx.drawImage(
this.oImg, // 需要绘制的图片
this.index * this.personWidth, //图片定位的位置
this.direction * this.personHeight, //图片定位的位置
this.personWidth, // 图片裁剪的大小
this.personHeight, // 图片裁剪的大小
this.x, // 图片绘制的位置
this.y, // 图片绘制的位置
this.personWidth, // 指定图片绘制大小
this.personHeight // 指定图片绘制大小
);
this.index++;
if (this.index > 3) {
this.index = 0;
}
}, 200);
}
moveDown() {
this.direction = 0;
this.run(0, 5);
}
moveUp() {
this.direction = 3;
this.run(0, -5);
}
moveLeft() {
this.direction = 1;
this.run(-5, 0);
}
moveRight() {
this.direction = 2;
this.run(5, 0);
}
//停止运动方法
stop() {
clearInterval(this.timeId);
}
}
let person = new Person(canvas, 100, 100);
person.render();
// person.moveDown();
// person.stop();
window.onkeydown = function (e) {
let key = e.key;
// console.log(key);
switch (key.toLowerCase()) {
case "w":
person.moveUp();
break;
case "s":
person.moveDown();
break;
case "a":
person.moveLeft();
break;
case "d":
person.moveRight();
break;
}
};
在canvas中所有的形变属性操作的都是坐标系, 而不是图形!!!
* {
margin: 0;
padding: 0;
}
canvas {
/* background: red; */
display: block;
margin: 0 auto;
margin: 50px auto;
}
// 1.拿到canvas
let canvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let ctx = canvas.getContext("2d");
ctx.translate(100,0);//位移
ctx.scale(.8,.6);//缩放
ctx.rotate(Math.PI/6);//旋转
// 3.绘制一个矩形
ctx.strokeRect(100, 100, 200, 100);
因为整个canvas是一个标签, 所以只能通过监听鼠标在canvas上(事件只能绑定到canvas标签上)的位置来判断是否需要处理对应的图形,当然也可以通过第三方框架来解决交互问题,诸如: zrender.js / Knova.js /three.js / egret.js / pixi.js等等
isPointInPath方法如果开启了一个新的路径, 那么判断的就是该点是否在新的路径的图形中
示例:
*{
margin: 0;
padding: 0;
}
canvas{
display: block;
margin: 0 auto;
/* background: red; */
margin: 50px auto;
}
let oCanvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let oCtx = oCanvas.getContext("2d");
// 3.绘制矩形
let rectX = 100;
let rectY = 100;
let rectWidth = 100;
let rectHeight = 100;
oCtx.rect(rectX, rectY, rectWidth, rectHeight);
oCtx.fill();
oCtx.beginPath();
oCtx.rect(200, 200, 100, 100);
oCtx.fill();
// 4.添加点击事件
oCanvas.onclick = function (event) {
let x = event.offsetX;
let y = event.offsetY;
if(x >= rectX && x <= rectX + rectWidth &&
y >= rectY && y <= rectY + rectHeight){
console.log("矩形被点击了");
}else{
console.log("矩形没有被点击");
}
console.log(oCtx.isPointInPath(x, y));
}