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

本文介绍了如何利用Vue3、Vite和Canvas技术栈创建一个动态的星星闪烁动画。首先,通过Vite搭建Vue3项目,然后在Canvas上绘制星星并实现随机生成。接着,通过更新星星的位置和大小,让星星闪烁移动。最后,当星星移动出画布区域时,会自动消失并重新生成。通过不断调整和优化,最终实现了逼真的星星动画效果。
摘要由CSDN通过智能技术生成

技术栈

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();
    }
  }

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

代码地址

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值