让AI写了一个烟花和新年快乐的灯笼

This commit is contained in:
hi2hi 2024-12-31 07:51:53 +00:00
parent d3e549cad0
commit 3ede341f3d
5 changed files with 426 additions and 0 deletions

View File

@ -66,6 +66,7 @@ module.exports = {
'no-param-reassign': 'off', 'no-param-reassign': 'off',
'no-underscore-dangle': 'off', 'no-underscore-dangle': 'off',
'no-unsafe-optional-chaining': 'off', 'no-unsafe-optional-chaining': 'off',
'max-classes-per-file': 'off',
'max-len': ['warn', 120], 'max-len': ['warn', 120],
'vue/max-len': ['warn', 120], 'vue/max-len': ['warn', 120],
'object-property-newline': ['error', { 'object-property-newline': ['error', {

View File

@ -5,6 +5,8 @@ window.$$nazhuaConfig = {
// buyBtnText: '购买', // 购买按钮文案 // buyBtnText: '购买', // 购买按钮文案
// customBackgroundImage: '', // 自定义的背景图片地址 // customBackgroundImage: '', // 自定义的背景图片地址
// lightBackground: true, // 启用了浅色系背景图,会强制关闭点点背景 // lightBackground: true, // 启用了浅色系背景图,会强制关闭点点背景
// showFireworks: true, // 是否显示烟花,建议开启浅色系背景
// showLantern: true, // 是否显示灯笼
// listServerItemTypeToggle: true, // 服务器列表项类型切换 // listServerItemTypeToggle: true, // 服务器列表项类型切换
// listServerItemType: 'row', // 服务器列表项类型 card/row row列表模式移动端自动切换至card // listServerItemType: 'row', // 服务器列表项类型 card/row row列表模式移动端自动切换至card
// listServerStatusType: 'progress', // 服务器状态类型--列表 // listServerStatusType: 'progress', // 服务器状态类型--列表

View File

@ -0,0 +1,158 @@
<template>
<canvas
ref="canvas"
class="fireworks-canvas"
/>
</template>
<script setup>
import {
ref,
onMounted,
onUnmounted,
} from 'vue';
const canvas = ref(null);
let ctx = null;
let particles = [];
let rockets = [];
let animationFrameId = null;
class Particle {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.color = color;
this.velocity = {
x: (Math.random() - 0.5) * 8,
y: (Math.random() - 0.5) * 12 - 8,
};
this.alpha = 1;
this.decay = 0.02;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, 2, 0, Math.PI * 2);
ctx.fillStyle = `rgba(${this.color}, ${this.alpha})`;
ctx.fill();
}
update() {
this.velocity.y += 0.1;
this.x += this.velocity.x;
this.y += this.velocity.y;
this.alpha -= this.decay;
}
}
function createFirework(x, y) {
const colors = [
'255, 0, 0',
'0, 255, 0',
'0, 0, 255',
'255, 255, 0',
'255, 0, 255',
'0, 255, 255',
];
const color = colors[Math.floor(Math.random() * colors.length)];
for (let i = 0; i < 80; i += 1) {
particles.push(new Particle(x, y, color));
}
}
class Rocket {
constructor() {
this.x = Math.random() * canvas.value.width;
this.y = canvas.value.height;
this.targetY = canvas.value.height * 0.5;
this.speed = 15;
this.trail = [];
this.maxTrailLength = 5;
}
draw() {
//
ctx.beginPath();
this.trail.forEach((pos, index) => {
ctx.fillStyle = `rgba(255, 200, 0, ${index / this.trail.length})`;
ctx.fillRect(pos.x, pos.y, 2, 2);
});
//
ctx.fillStyle = 'rgba(255, 220, 0, 1)';
ctx.fillRect(this.x, this.y, 3, 3);
}
update() {
this.trail.push({
x: this.x,
y: this.y,
});
if (this.trail.length > this.maxTrailLength) {
this.trail.shift();
}
this.y -= this.speed;
if (this.y <= this.targetY) {
createFirework(this.x, this.y);
return false;
}
return true;
}
}
function animate() {
ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
//
rockets = rockets.filter((rocket) => {
rocket.draw();
return rocket.update();
});
//
particles = particles.filter((particle) => particle.alpha > 0);
particles.forEach((particle) => {
particle.draw();
particle.update();
});
//
if (Math.random() < 0.03 && rockets.length < 3) {
rockets.push(new Rocket());
}
animationFrameId = requestAnimationFrame(animate);
}
function resizeCanvas() {
if (canvas.value) {
canvas.value.width = window.innerWidth;
canvas.value.height = window.innerHeight;
}
}
onMounted(() => {
ctx = canvas.value.getContext('2d');
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
animate();
});
onUnmounted(() => {
window.removeEventListener('resize', resizeCanvas);
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
});
</script>
<style scoped>
.fireworks-canvas {
position: fixed;
top: 0;
left: 0;
z-index: 8;
pointer-events: none;
}
</style>

257
src/components/lantern.vue Normal file
View File

@ -0,0 +1,257 @@
<template>
<div class="lantern-container">
<div class="lantern-group right-group">
<div class="deng-box">
<div class="deng">
<div class="xian" />
<div class="deng-a">
<div class="deng-b">
<div class="deng-t"></div>
</div>
</div>
<div class="shui shui-a">
<div class="shui-c" />
<div class="shui-b" />
</div>
</div>
</div>
<div class="deng-box deng-box--2">
<div class="deng">
<div class="xian" />
<div class="deng-a">
<div class="deng-b">
<div class="deng-t"></div>
</div>
</div>
<div class="shui shui-a">
<div class="shui-c" />
<div class="shui-b" />
</div>
</div>
</div>
</div>
<div class="lantern-group left-group">
<div class="deng-box">
<div class="deng">
<div class="xian" />
<div class="deng-a">
<div class="deng-b">
<div class="deng-t"></div>
</div>
</div>
<div class="shui shui-a">
<div class="shui-c" />
<div class="shui-b" />
</div>
</div>
</div>
<div class="deng-box deng-box--2">
<div class="deng">
<div class="xian" />
<div class="deng-a">
<div class="deng-b">
<div class="deng-t"></div>
</div>
</div>
<div class="shui shui-a">
<div class="shui-c" />
<div class="shui-b" />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
//
// AI
</script>
<style lang="scss" scoped>
.lantern-container {
position: fixed;
top: calc(var(--layout-header-height) + 5px);
width: 100%;
z-index: 50;
pointer-events: none;
}
.lantern-group {
position: fixed;
top: 70px;
animation: swing 3s infinite ease-in-out;
transform-origin: 50% -10px;
&.left-group {
left: 40px;
animation-delay: -1.5s;
.deng-box:nth-child(2) {
margin-top: -12px;
.deng {
animation: swing-extra 2s infinite ease-in-out;
animation-delay: -0.5s;
}
}
}
&.right-group {
right: 30px;
animation-delay: -0.5s;
.deng-box:nth-child(2) {
.deng {
animation: swing-extra 2s infinite ease-in-out;
animation-delay: -1s;
}
}
}
.deng {
animation: none;
}
.deng-box {
position: relative;
top: -40px;
&:first-child {
z-index: 2;
.deng {
margin-bottom: 23px;
}
}
&:nth-child(2) {
z-index: 1;
}
}
}
.deng {
position: relative;
width: 120px;
height: 90px;
margin: 50px;
background: rgba(216, 0, 15, 0.8);
border-radius: 50% 50%;
transform-origin: 50% -100px;
animation: swing 3s infinite ease-in-out;
box-shadow: -5px 5px 50px 4px rgba(250, 108, 0, 1);
}
.deng-a {
width: 100px;
height: 90px;
background: rgba(216, 0, 15, 0.1);
margin: 12px 8px 8px 10px;
border-radius: 50% 50%;
border: 2px solid #dc8f03;
}
.deng-b {
width: 45px;
height: 90px;
background: rgba(216, 0, 15, 0.1);
margin: -4px 8px 8px 26px;
border-radius: 50% 50%;
border: 2px solid #dc8f03;
}
.xian {
position: absolute;
top: -20px;
left: 60px;
width: 2px;
height: 20px;
background: #dc8f03;
}
.shui-a {
position: relative;
width: 5px;
height: 20px;
margin: -5px 0 0 59px;
transform-origin: 50% -45px;
background: #ffa500;
border-radius: 0 0 5px 5px;
}
.shui-b {
position: absolute;
top: 14px;
left: -2px;
width: 10px;
height: 10px;
background: #dc8f03;
border-radius: 50%;
}
.shui-c {
position: absolute;
top: 18px;
left: -2px;
width: 10px;
height: 35px;
background: #ffa500;
border-radius: 0 0 0 5px;
}
.deng:before {
position: absolute;
top: -7px;
left: 29px;
height: 12px;
width: 60px;
content: " ";
display: block;
z-index: 999;
border-radius: 5px 5px 0 0;
border: solid 1px #dc8f03;
background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03, #ffa500, #dc8f03);
}
.deng:after {
position: absolute;
bottom: -7px;
left: 10px;
height: 12px;
width: 60px;
content: " ";
display: block;
margin-left: 20px;
border-radius: 0 0 5px 5px;
border: solid 1px #dc8f03;
background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03, #ffa500, #dc8f03);
}
.deng-t {
font-family: 华文行楷, Arial, Lucida Grande, Tahoma, sans-serif;
font-size: 3.2rem;
color: #ffd000;
line-height: 85px;
text-align: center;
margin-left: -5px;
}
@keyframes swing {
0% { transform: rotate(-6deg) }
50% { transform: rotate(6deg) }
100% { transform: rotate(-6deg) }
}
@keyframes swing-extra {
0% { transform: rotate(-3deg) }
50% { transform: rotate(3deg) }
100% { transform: rotate(-3deg) }
}
@media screen and (max-width: 1024px) {
.lantern-container {
display: none;
}
}
</style>

View File

@ -12,6 +12,12 @@
<slot /> <slot />
<layout-footer /> <layout-footer />
</div> </div>
<template v-if="config.nazhua.showFireworks">
<fireworks />
</template>
<template v-if="config.nazhua.showLantern">
<lantern />
</template>
</div> </div>
</template> </template>
@ -21,6 +27,8 @@
*/ */
import { computed } from 'vue'; import { computed } from 'vue';
import config from '@/config'; import config from '@/config';
import Fireworks from '@/components/fireworks.vue';
import Lantern from '@/components/lantern.vue';
import LayoutHeader from './components/header.vue'; import LayoutHeader from './components/header.vue';
import LayoutFooter from './components/footer.vue'; import LayoutFooter from './components/footer.vue';