技术栈
项目搭建
实现过程
思路:
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();
}
}
效果
到这里,基础功能就实现了,黑色背景属实不好看,后边再抽时间进行一些背景调整吧…