canvas是什么
<canvas> 元素可被用来通过 JavaScript(Canvas API 或 WebGL API)绘制图形及图形动画。
canvas绘制的是位图。
canvas绘制线段
使用HTMLCanvasElement.getContext()获得一个绘图上下文并开始绘制。
- 效果图
- 代码
<canvas id="canvas" width="600" height="500"> 抱歉,您的浏览器不支持 canvas 元素
(这些内容将会在不支持<canvas>元素的浏览器或是禁用了 JavaScript 的浏览器内渲染并展现)</canvas>
const canvas = document.getElementById("canvas");
// 使用HTMLCanvasElement.getContext()获得一个绘图上下文并开始绘制
// HTMLCanvasElement.getContext() 方法返回canvas 的上下文,如果上下文没有定义则返回 null .
// 在同一个 canvas 上以相同的 contextType 多次调用此方法只会返回同一个上下文。
const ctx =canvas.getContext('2d');
// 创建一个新的路径时
ctx.beginPath();
// 将一个新的子路径的起始点移动到 (x,y) 坐标的方法。
ctx.moveTo(100, 100);
// 使用直线连接子路径的终点到 x,y 坐标的方法(并不会真正地绘制)。
ctx.lineTo(300, 300);
ctx.lineTo(300, 100);
ctx.lineWidth = 4;
ctx.strokeStyle = 'blue';
// 将笔点返回到当前子路径起始点的方法。它尝试从当前点到起始点绘制一条直线。如果图形已经是封闭的或者只有一个点,那么此方法不会做任何操作。
ctx.closePath()
// 根据当前的画线样式,绘制当前或已经存在的路径的方法。
ctx.stroke();
canvas高清绘制操作
当物理设备的像素分辨率大于css像素的分辨率时,显示的会模糊,反之则会清晰。
代码实现:
<canvas id="canvas" width="600" height="500"
>您的浏览器当前不支持 canvas</canvas
>
const canvas = document.getElementById("canvas");
// 使用HTMLCanvasElement.getContext()获得一个绘图上下文并开始绘制
const ctx = canvas.getContext("2d");
/**像素大小的比率*/
const getPixelRatio = (context) => {
// 当前显示设备的物理像素分辨率与CSS 像素分辨率之比
return window.devicePixelRatio || 1;
};
/*
01 放大 canvas
02 再在 css 里将宽高设置为原来的大小
03 考虑到内容的缩放,因此也需将 ctx 缩放
*/
// 像素大小的比率
const ratio = getPixelRatio();
// 绘制区域的宽
const oldWidth = canvas.width;
// 绘制区域的高
const oldHeight = canvas.height;
// 设置当前像素比下,绘制区域的大小
canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;
// 设置canvas大小
canvas.style.width = oldWidth + "px";
canvas.style.height = oldHeight + "px";
// 为 canvas 单位添加缩放变换
ctx.scale(ratio, ratio)
// 创建一个新的路径时
ctx.beginPath();
// 线段宽度
ctx.lineWidth = 10;
// 线段颜色
ctx.strokeStyle = "red";
// 将一个新的子路径的起始点移动到 (x,y) 坐标
ctx.moveTo(100, 100);
ctx.lineTo(300, 300);
ctx.lineTo(500, 100);
ctx.stroke(); // 绘制一条路径
ctx.closePath();
图示
-
未考虑设备像素比:
-
考虑设备像素比,更为清晰
canvas画坐标系
效果
代码
<canvas id="canvas" width="600" height="400"
>抱歉,您的浏览器不支持 canvas 元素
(这些内容将会在不支持<canvas>元素的浏览器或是禁用了 JavaScript 的浏览器内渲染并展现)</canvas
>
const canvas=document.querySelector('#canvas')
// 使用HTMLCanvasElement.getContext()获得一个绘图上下文并开始绘制
const ctx=canvas.getContext('2d')
console.log(ctx);
// 设置canvas大小
canvas.style.width = canvas.width + 'px'
canvas.style.height = canvas.height + 'px'
// 设置canvas绘制区域大小
canvas.width = canvas.width * 1.5
canvas.height = canvas.height * 1.5
// 获取canvas元素宽高
const ht = canvas.clientHeight
const wd = canvas.clientWidth
const pad = 20
const bottomPad = 20
const step = 100
const drawAxis=(options)=>{
const { ht, wd, pad, bottomPad, step, ctx } = options
// 绘制X、Y轴
ctx.beginPath();
ctx.lineWidth = 2
ctx.strokeStyle = 'lightblue'
ctx.moveTo(pad, pad);
ctx.lineTo(pad, ht * 1.5 - bottomPad );
ctx.lineTo(wd * 1.5 - pad, ht * 1.5 - bottomPad );
ctx.stroke()
ctx.closePath();
// 绘制X轴刻度
ctx.beginPath()
ctx.lineWidth = 1
ctx.strokeStyle = '#666'
for (let i = 1; i < Math.floor(wd * 1.5 / step); i++) {
ctx.moveTo(pad + i * step, ht * 1.5 - bottomPad)
ctx.lineTo(pad + i * step, ht * 1.5 - bottomPad - 10)
}
ctx.stroke()
ctx.closePath()
// 绘制Y轴刻度
ctx.beginPath()
ctx.lineWidth = 1
ctx.strokeStyle = '#666'
for (let i = 1; i < Math.floor(ht * 1.5 / step); i++) {
ctx.moveTo(pad, (ht * 1.5 - bottomPad) - (i * step))
ctx.lineTo(pad + 10, (ht * 1.5 - bottomPad) - (i * step))
}
ctx.stroke()
ctx.closePath()
}
drawAxis({
ht: ht,
wd: wd,
pad: pad,
bottomPad: bottomPad,
step: step,
ctx: ctx
})
canvas绘制直方图
矩形
- 矩形
ctx.beginPath()
ctx.lineWidth = 5
ctx.strokeStyle = 'orange'
// 创建矩形路径
ctx.rect(100, 100, 300, 200)
ctx.stroke()
ctx.closePath()
- 填充矩形
ctx.beginPath()
ctx.fillStyle = 'skyblue'
ctx.fillRect(410, 310, 300, 200)
ctx.closePath()
直方图
// 绘制直方图
ctx.beginPath();
for (var i = 1; i < Math.floor(wd * 1.5 / step); i++) {
// 矩形高度
const height = Math.random() * 300 + 50;
// 矩形填充颜色
ctx.fillStyle = '#' + parseInt(Math.random() * 0xFFFFFF).toString(16);
// 绘制矩形
ctx.fillRect((i * step), ht * 1.5 - bottomPad - height, 40, height)
}
ctx.closePath()
canvas绘制圆形
- 圆
ctx.beginPath()
ctx.lineWidth = 2
ctx.strokeStyle = 'orange'
// 绘制圆弧路径
ctx.arc(400, 300, 200, 0, 2*Math.PI, true)
ctx.stroke()
ctx.closePath()
- 填充圆
ctx.beginPath()
ctx.fillStyle = 'skyblue'
ctx.arc(400, 300, 100, 0, 2*Math.PI, true)
ctx.fill()
ctx.closePath()
canvas绘制饼状图
ctx.beginPath();
// 阴影偏移距离
ctx.shadowOffsetX = 0
ctx.shadowOffsetY = 0
// 模糊效果程度
ctx.shadowBlur = 4
ctx.shadowColor = '#333'
// 填充样式
ctx.fillStyle = '#5C1918'
ctx.moveTo(400, 300);
ctx.arc(400, 300, 100, -Math.PI / 2, -Math.PI / 4);
ctx.fill()
ctx.closePath()
ctx.beginPath();
ctx.shadowOffsetX = 0
ctx.shadowOffsetY = 0
ctx.shadowBlur = 4
ctx.shadowColor = '#5C1918'
ctx.fillStyle = '#A32D29'
ctx.moveTo(400, 300);
ctx.arc(400, 300, 110, -Math.PI / 4, Math.PI / 4);
ctx.fill()
ctx.closePath()
ctx.beginPath()
ctx.shadowOffsetX = 0
ctx.shadowOffsetY = 0
ctx.shadowBlur = 4
ctx.shadowColor = '#A32D29'
ctx.fillStyle = '#B9332E'
ctx.moveTo(400, 300)
ctx.arc(400, 300, 120, Math.PI / 4, Math.PI * 5 / 8)
ctx.fill()
ctx.closePath()
ctx.beginPath()
ctx.shadowOffsetX = 0
ctx.shadowOffsetY = 0
ctx.shadowBlur = 4
ctx.shadowColor = '#B9332E'
ctx.fillStyle = '#842320'
ctx.moveTo(400, 300)
ctx.arc(400, 300, 130, Math.PI * 5 / 8, Math.PI)
ctx.fill()
ctx.closePath()
ctx.beginPath()
ctx.shadowOffsetX = 0
ctx.shadowOffsetY = 0
ctx.shadowBlur = 4
ctx.shadowColor = '#842320'
ctx.fillStyle = '#D76662'
ctx.moveTo(400, 300)
ctx.arc(400, 300, 140, Math.PI, Math.PI * 3 / 2)
ctx.fill()
ctx.closePath()
canvas绘制文字
// 实心、描边文字
ctx.fillStyle = 'orange'
ctx.strokeStyle = "hotpink"
ctx.font = 'bold 60px 微软雅黑'
ctx.fillText('canvas', 100, 100, 100)
ctx.strokeText('前端', 100, 200)
// 对齐属性设置
ctx.textAlign = 'center'
ctx.textBaseline = "middle"
ctx.fillText('我的天哪', 200, 300)
canvas碰撞检测
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
canvas.width = canvas.width * 1.5;
canvas.height = canvas.height * 1.5;
/**
*绘制圆形
*/
const drawCircle = (x, y, r) => {
ctx.beginPath();
ctx.fillStyle = "orange";
ctx.arc(x, y, r, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
};
// 绘制区域大小
const wd = canvas.clientWidth * 1.5;
const ht = canvas.clientHeight * 1.5;
// 圆心位置
let x = (y = 100);
// 圆的半径
const r = 20;
// x轴方向移动大小
let xSpeed = 6;
// y轴方向移动大小
let ySpeed = 4;
setInterval(() => {
// 清空画布
ctx.clearRect(0, 0, wd, ht);
// 当圆要碰到边界时,改变移动方向
if (x - r <= 0 || x + r >= wd) {
xSpeed = -xSpeed;
}
if (y - r <= 0 || y + r >= ht) {
ySpeed = -ySpeed;
}
// 再次绘制圆时,圆心位置
x += xSpeed;
y += ySpeed;
drawCircle(x, y, r);
}, 20);
canvas动画
下图中的小球会不停运动
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
canvas.width = canvas.width * 1.5;
canvas.height = canvas.height * 1.5;
// 定义圆形小球类
class Ball {
constructor(canvas) {
// 当前小球所处的canvas
this.canvas = canvas;
// 绘制的上下文
this.ctx = this.canvas.getContext("2d");
// 绘制区域的宽度
this.wd = this.canvas.clientWidth * 1.5;
// 绘制区域的高度
this.ht = this.canvas.clientHeight * 1.5;
// 半径,随机大小
this.r = Math.random() * 40 + 10;
// 圆心的位置--X
this.x = Math.random() * (this.wd - this.r * 2) + this.r;
// 圆心的位置--Y
this.y = Math.random() * (this.ht - this.r * 2) + this.r;
// 圆的填充颜色
this.color =
"#" + parseInt(Math.random() * 0xffffff).toString(16);
// 圆的移动大小
this.xSpeed = Math.random() * 4 + 6;
this.ySpeed = Math.random() * 6 + 4;
// 初始化
this.init();
}
init() {
this.run();
this.draw();
}
// 画圆
draw() {
this.ctx.beginPath();
this.ctx.fillStyle = this.color;
this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
this.ctx.fill();
this.ctx.closePath();
}
// 圆的远动
run() {
if (this.x - this.r <= 0 || this.x + this.r >= this.wd) {
this.xSpeed = -this.xSpeed;
}
if (this.y - this.r <= 0 || this.y + this.r >= this.ht) {
this.ySpeed = -this.ySpeed;
}
this.x += this.xSpeed;
this.y += this.ySpeed;
}
}
// 记录小球
let ballArr = [];
// 创建小球
for (let i = 0; i < 50; i++) {
let ball = new Ball(canvas);
ballArr.push(ball);
}
// 动画操作
setInterval(() => {
// 清空画布
ctx.clearRect(
0,
0,
canvas.clientWidth * 1.5,
canvas.clientHeight * 1.5
);
// 绘制记录的小球
for (let i = 0; i < ballArr.length; i++) {
let ball = ballArr[i];
ball.init();
}
}, 15);