Canvas

154 阅读2分钟

参考文档:canvas中文网mdn中的canvas

Canvas API 主要聚焦于 2D 图形。而同样使用<canvas>元素的 WebGL API 则用于绘制硬件加速的 2D 和 3D 图形。

基本用法

...
// html部分
<canvas class="myCanvas" height="500px" width="500px"></canvas>
...

...
// css部分
  * {
    padding: 0;
    margin: 0;
  }

  body {
    display: grid;
    place-content: center;
    height: 100vh;
  }

  .myCanvas {
    background-color: aquamarine;
    border: 1px solid black;
    margin: auto;
    display: block;
    /* height: 600px;
  width: 600px; */
    /* canvas中的宽度和高度只能写成行内样式,不能这样写,且默认大小是300*150大小的形状 */
    box-sizing: border-box;
  }
...


...
// js部分
// 这行注释可以开启canvas的代码提示,不写没有关于canvas的代码提示
/**
 * @type {HTMLCanvasElement}
 */
let myCanvas = document.querySelector('.myCanvas')
// 获取上下文对象
let ctx = myCanvas.getContext('2d')
// 开启一条路径
ctx.beginPath()
// 起始点
ctx.moveTo(0,0)
// ctx.moveTo(300,600)
// 结束点
ctx.lineTo(500,500)
// 进行上色
ctx.stroke()
// 关闭路径
ctx.closePath()
...

image.png

例子:用canvas制作一个简单的canvas小球运动

// html文件
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<canvas class="myCanvas" height="500px" width="500px"></canvas>
<script src="./5.js"></script>

<style>
  * {
    padding: 0;
    margin: 0;
  }

  body {
    display: grid;
    place-content: center;
    height: 100vh;
  }

  .myCanvas {
    background-color: pink;
    border: 1px solid black;
    margin: auto;
    display: block;
    box-sizing: border-box;
  }

</style>

</html>

// js文件
/**
 * @type {HTMLCanvasElement}
 */
let myCanvas = document.querySelector(".myCanvas");
let ctx = myCanvas.getContext("2d");
/**
 *
 */
let x = 100,
  y = 100,
  radius = 40,
  startAngle = 0,
  endAngle = Math.PI * 2,
  couterclockwise = false,
  yInitSpeed = 6, // y轴方向初始速度
  xInitSpeed = 7; // x轴方向初始速度
// ctx.stroke(); // Stroke(笔触)是一个形状的轮廓,类似画边框
/**
 * 画运动的球
 * @param {圆心x轴坐标} x
 * @param {圆心y轴坐标} y
 * @param {半径} radius
 * @param {开始角度} startAngle
 * @param {结束角度} endAngle
 * @param {是否逆时针} couterclockwise
 */
function drawCircle(x, y, radius, startAngle, endAngle, couterclockwise) {
  ctx.beginPath(); // 新建一条绘画路径
  ctx.arc(x, y, radius, startAngle, endAngle, couterclockwise);
  ctx.fillStyle = "white"; // 先选好颜色再画图,先fillStyle再fill才生效
  ctx.fill(); // Fill(填充)是在形状内部的内容
}

setInterval(() => {
  ctx.clearRect(0, 0, 500, 500); // 清除指定矩形区域,让清除部分完全透明。
  if (x - radius <= 0 || x + radius >= 500) {
    xInitSpeed = -xInitSpeed;
  }
  x = x + xInitSpeed;
  if (y - radius <= 0 || y + radius >= 500) {
    yInitSpeed = -yInitSpeed;
  }
  y = y + yInitSpeed;
  drawCircle(x, y, radius, startAngle, endAngle, couterclockwise);
}, 50);

setInterval(() => {
  console.log("小球的速度为:", x);
}, 4000);

录制2.gif

例子改写:用canvas制作多个不规则的canvas小球运动

// js文件
/**
 * @type {HTMLCanvasElement}
 */
let myCanvas = document.querySelector(".myCanvas");
let ctx = myCanvas.getContext("2d");
let w = 500,
  h = 500;

// 多个小球运动,采用面向对象的思想
function Ball() {
  // Math.random():[0,1)
  this.x = (Math.random() * w) / 100 + 70;
  this.y = (Math.random() * h) / 100 + 70;
  this.radius = Math.random() * 60 + 10;
  this.color = "#" + parseInt(Math.random() * 0xffffff).toString(16);
  this.xInitSpeed = Math.random() * 5 + 11;
  this.yInitSpeed = Math.random() * 10 + 10;
  this.startAngle = 0;
  this.endAngle = Math.PI * 2;
  this.couterclockwise = false;
  this;
}

// 定义小球显示的方法
Ball.prototype.show = function() {
  ctx.beginPath(); // 新建一条绘画路径
  ctx.arc(
    this.x,
    this.y,
    this.radius,
    this.startAngle,
    this.endAngle,
    this.couterclockwise
  );
  ctx.fillStyle = this.color; // 先选好颜色再画图,先fillStyle再fill才生效
  ctx.fill(); // Fill(填充)是在形状内部的内容
};
// 创建出现多个小球
let ballArr = []; // 记录生成的小球,方便后续操作创建的小球
for (let i = 0; i < Math.random() * 10 + 5; i++) {
  // new Ball().show()
  let ball = new Ball();
  ballArr.push(ball);
  ball.show();
}
console.log(ballArr);
// 小球的运动
Ball.prototype.run = function() {
  if (this.x - this.radius <= 0 || this.x + this.radius >= w) {
    this.xInitSpeed = -this.xInitSpeed;
  }
  this.x = this.x + this.xInitSpeed;

  if (this.y - this.radius <= 0 || this.y + this.radius >= h) {
    this.yInitSpeed = -this.yInitSpeed;
  }
  this.y = this.y + this.yInitSpeed;
};

// 给创建的小球加运动

setInterval(() => {
  ctx.clearRect(0, 0, w, h);
  for (const item of ballArr) {
    item.run();
    item.show();
  }
}, 50);

录制.gif

这让我想起了一个自己线下碰到的一个面试题:如果前端页面中需要根据后端返回的数据,绘制对应的不同形状的图片,怎么实现?我当时居然连canvas都不想上去!想必面试官应该很无语吧,作为前端居然不知道canvas,简直是离离原谱!!!**