利用敷面膜的时间写一个简易的星空

「时光不负,创作不停,本文正在参加2021年终总结征文大赛

2021马上结束了,回首一年也不知道自己都干了什么...感觉浪费了很多时间,所以打算利用一些空闲时间,
写一写东西记录一下自己的学习过程,不至于回头望时什么都没有留下..
复制代码

技术栈

vue3vitecanvas

项目搭建

可以参考 怎么使用 vite 创建一个 vue3 的项目

实现过程

想法: 1.需要画一个简易的星星模样; 大概就是下边这个样子

在这里插入图片描述

2.在指定区域随机生成n个大小不一的星星;

3.星星可以移动、闪烁;

4.当星星移动出区域后消失,并且重新生成一个新的;

在 views 目录下创建一个star文件夹其中创建 index.vue 然后进行第二步,在画布上画出星星(需要使用到canvas的 ctx.lineTo(x, y))方法以及 Class

<template>
  <canvas id="canvas"></canvas>
</template>

<script setup>
import { ref, onMounted } from "vue";
import BgImg from "../../assets/images/bg.jpg";
let canvas = ref(null);
let ctx = ref(null);
let w = ref(0);
let h = ref(0);
const num = 10;
let stars = [];

onMounted(() => {
  initCanvas();
  // 根据 num 循环生成多个星星
  for (let i = 0; i < num; i++) {
    let obj = new Star();
    stars.push(obj);
    stars[i].init();
  }
  // 向画布绘制星星
  for (let i = 0; i < stars.length; i++) {
    const star = stars[i];
    star.draw();
  }
});

function initCanvas() {
  canvas.value = document.getElementById("canvas");
  ctx.value = canvas.value.getContext("2d");
  w.value = document.body.offsetWidth;
  h.value = document.body.offsetHeight;
  canvas.value.height = h.value;
  canvas.value.width = w.value;
}
// 星星类
class Star {
  constructor() {
    this.x;
    this.y;
    this.start;
  }
  // 星星初始化方法 初始化星星基础数据
  init() {
    // Math.floor() 返回小于或等于一个给定数字的最大整数
    this.x = 200;
    this.y = 200;
    this.start = 50;
  }
  // 画星星
  draw() {
    ctx.value.beginPath();
    let startM = this.start / 3;
    ctx.value.lineTo(this.x + startM, this.y - startM);
    ctx.value.lineTo(this.x + this.start, this.y);
    ctx.value.lineTo(this.x + startM, this.y + startM);
    ctx.value.lineTo(this.x, this.y + this.start);
    ctx.value.lineTo(this.x - startM, this.y + startM);
    ctx.value.lineTo(this.x - this.start, this.y);
    ctx.value.lineTo(this.x - startM, this.y - startM);
    ctx.value.lineTo(this.x, this.y - this.start);
    ctx.value.strokeStyle = "#fff";
    ctx.value.fillStyle = "#fff";
    ctx.value.fill();
    ctx.value.closePath();
  }
}
</script>

<style lang="scss" scoped>
#canvas {
  background: #000;
}
</style>
复制代码

效果

在这里插入图片描述

这个时候星星还是固定的位置无论我们画多少个都是同一个位置且大小也是相同的,所以我们需要将每个星星的坐标以及大小值设置为动态,这里使用 Math.random() Math.floor() 获取。

修改 Star 的 init 方法

 // 星星初始化方法 初始化星星基础数据
  init() {
    // Math.floor() 返回小于或等于一个给定数字的最大整数
    this.x = Math.floor(Math.random() * w.value);
    this.y = Math.floor(Math.random() * h.value);
    this.start = Math.floor(Math.random() * 10);
  }
复制代码

效果

在这里插入图片描述

这个时候简单的星星就画好了,接下来需要让星星闪烁起来,这里改变 start 值就可以达到星星闪烁的效果。(使用 window.requestAnimationFrame 执行动画效果)

<template>
  <canvas id="canvas"></canvas>
</template>

<script setup>
import { ref, onMounted } from "vue";
import BgImg from "../../assets/images/bg.jpg";
let canvas = ref(null);
let ctx = ref(null);
let w = ref(0);
let h = ref(0);
const num = 10;
let stars = [];
// 定义时间变量 控制星星更新频率
let lastTime = ref(0);
let deltaTime = ref(0);
let timer = ref(0);

onMounted(() => {
  initCanvas();
  // 根据 num 循环生成多个星星
  for (let i = 0; i < num; i++) {
    let obj = new Star();
    stars.push(obj);
    stars[i].init();
  }
  lastTime.value = Date.now();
  loop();
});

function initCanvas() {
  canvas.value = document.getElementById("canvas");
  ctx.value = canvas.value.getContext("2d");
  w.value = document.body.offsetWidth;
  h.value = document.body.offsetHeight;
  canvas.value.height = h.value;
  canvas.value.width = w.value;
}
function loop() {
  window.requestAnimationFrame(loop);
  let nowTime = Date.now();
  deltaTime.value = nowTime - lastTime.value;
  lastTime.value = Date.now();
  timer.value += deltaTime.value;
  if (timer.value > 160) {
    drawStar();
    timer.value = 0;
  }
}
function drawStar() {
  ctx.value.clearRect(0, 0, w.value, h.value);
  // 向画布绘制星星
  for (let i = 0; i < stars.length; i++) {
    const star = stars[i];
    star.update();
    star.draw();
  }
}
// 星星类
class Star {
  constructor() {
    this.x;
    this.y;
    this.start;
  }
  // 星星初始化方法 初始化星星基础数据
  init() {
    // Math.floor() 返回小于或等于一个给定数字的最大整数
    this.x = Math.floor(Math.random() * w.value);
    this.y = Math.floor(Math.random() * h.value);
    this.start = Math.floor(Math.random() * 10);
  }
  // 更新星星
  update() {
    this.start += 1;
    this.start %= 5;
  }
  // 画星星
  draw() {
    ctx.value.save();
    ctx.value.beginPath();
    let startM = this.start / 3;
    ctx.value.lineTo(this.x + startM, this.y - startM);
    ctx.value.lineTo(this.x + this.start, this.y);
    ctx.value.lineTo(this.x + startM, this.y + startM);
    ctx.value.lineTo(this.x, this.y + this.start);
    ctx.value.lineTo(this.x - startM, this.y + startM);
    ctx.value.lineTo(this.x - this.start, this.y);
    ctx.value.lineTo(this.x - startM, this.y - startM);
    ctx.value.lineTo(this.x, this.y - this.start);
    ctx.value.strokeStyle = "#fff";
    ctx.value.fillStyle = "#fff";
    ctx.value.fill();
    ctx.value.closePath();
    ctx.value.stroke();
    ctx.value.restore();
  }
}
</script>

<style lang="scss" scoped>
#canvas {
  background: #000;
}
</style>
复制代码

效果 在这里插入图片描述 这个时候星星可以进行闪烁了,但是位置还是固定的所以我们在更新的时候将星星坐标进行变化。

// 更新星星
constructor() {
    this.x;
    this.y;
    this.xNum;
    this.yNum;
    this.start;
  }
  // 星星初始化方法 初始化星星基础数据
  init() {
    // Math.floor() 返回小于或等于一个给定数字的最大整数
    this.x = Math.floor(Math.random() * w.value);
    this.y = Math.floor(Math.random() * h.value);
    this.start = Math.floor(Math.random() * 10);
    this.xNum = Math.random() * 3 - 1.5;
    this.yNum = Math.random() * 3 - 1.5;
  }
  update() {
    this.x += this.xNum * deltaTime.value * 0.3;
    this.y += this.yNum * deltaTime.value * 0.3;
    this.start += 1;
    this.start %= 5;
  }
复制代码

效果 在这里插入图片描述 接下来需要判断一下星星是否移动出了区域,超出区域后重新生成一个新的星星。

// 更新星星
  update() {
    this.x += this.xNum * deltaTime.value * 0.3;
    this.y += this.yNum * deltaTime.value * 0.3;
    this.start += 1;
    this.start %= 5;
    // 当 x 或 y < 0 时 或 x > w 或 y < h 时判定星星已经超出了区域
    if (this.x < 0 || this.y < 0 || this.x > w.value || this.y > h.value) {
      this.init();
    }
  }
复制代码

效果 在这里插入图片描述 到这里,基础功能就实现了,黑色背景属实不好看,后边再抽时间进行一些背景调整吧....

代码地址

Guess you like

Origin juejin.im/post/7041481823565643812