Skip to content

Commit

Permalink
添加鼠标单击烟花特效
Browse files Browse the repository at this point in the history
  • Loading branch information
tangly1024 committed Apr 29, 2022
1 parent 2496908 commit c7908a5
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 2 deletions.
3 changes: 3 additions & 0 deletions blog.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ const BLOG = {
CONTACT_GITHUB: 'https://github.com/tangly1024',
CONTACT_TELEGRAM: '',

// 鼠标点击烟花特效
FIREWORKS: process.env.NEXT_PUBLIC_FIREWORKS || true, // 鼠标点击烟花特效

// 悬浮挂件
WIDGET_PET: process.env.NEXT_PUBLIC_WIDGET_PET || true, // 是否显示宠物挂件
WIDGET_PET_LINK:
Expand Down
209 changes: 209 additions & 0 deletions components/Fireworks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/**
* https://codepen.io/juliangarnier/pen/gmOwJX
* custom by hexo-theme-yun @YunYouJun
*/
import React from 'react'
import anime from 'animejs'

export const Fireworks = () => {
React.useEffect(() => {
createFireworks({})
}, [])
return <canvas id='fireworks' className='fireworks'></canvas>
}

/**
* 创建烟花
* @param config
*/
function createFireworks(config) {
const defaultColors = ['102, 167, 221', '62, 131, 225', '33, 78, 194']
const defaultConfig = {
colors: defaultColors,
numberOfParticules: 20,
orbitRadius: {
min: 50,
max: 100
},
circleRadius: {
min: 10,
max: 20
},
diffuseRadius: {
min: 50,
max: 100
},
animeDuration: {
min: 900,
max: 1500
}
}
config = Object.assign(defaultConfig, config)

let pointerX = 0
let pointerY = 0

// sky blue
const colors = config.colors || defaultColors

const canvasEl = document.querySelector('.fireworks')
const ctx = canvasEl.getContext('2d')

/**
* 设置画布尺寸
*/
function setCanvasSize(canvasEl) {
canvasEl.width = window.innerWidth
canvasEl.height = window.innerHeight
canvasEl.style.width = `${window.innerWidth}px`
canvasEl.style.height = `${window.innerHeight}px`
}

/**
* update pointer
* @param {TouchEvent} e
*/
function updateCoords(e) {
pointerX =
e.clientX ||
(e.touches[0] ? e.touches[0].clientX : e.changedTouches[0].clientX)
pointerY =
e.clientY ||
(e.touches[0] ? e.touches[0].clientY : e.changedTouches[0].clientY)
}

function setParticuleDirection(p) {
const angle = (anime.random(0, 360) * Math.PI) / 180
const value = anime.random(
config.diffuseRadius.min,
config.diffuseRadius.max
)
const radius = [-1, 1][anime.random(0, 1)] * value
return {
x: p.x + radius * Math.cos(angle),
y: p.y + radius * Math.sin(angle)
}
}

/**
* 在指定位置创建粒子
* @param {number} x
* @param {number} y
* @returns
*/
function createParticule(x, y) {
const p = {
x,
y,
color: `rgba(${
colors[anime.random(0, colors.length - 1)]
},${
anime.random(0.2, 0.8)
})`,
radius: anime.random(config.circleRadius.min, config.circleRadius.max),
endPos: null,
draw() {}
}
p.endPos = setParticuleDirection(p)
p.draw = function() {
ctx.beginPath()
ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true)
ctx.fillStyle = p.color
ctx.fill()
}
return p
}

function createCircle(x, y) {
const p = {
x,
y,
color: '#000',
radius: 0.1,
alpha: 0.5,
lineWidth: 6,
draw() {}
}
p.draw = function() {
ctx.globalAlpha = p.alpha
ctx.beginPath()
ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true)
ctx.lineWidth = p.lineWidth
ctx.strokeStyle = p.color
ctx.stroke()
ctx.globalAlpha = 1
}
return p
}

function renderParticule(anim) {
for (let i = 0; i < anim.animatables.length; i++) { anim.animatables[i].target.draw() }
}

function animateParticules(x, y) {
const circle = createCircle(x, y)
const particules = []
for (let i = 0; i < config.numberOfParticules; i++) { particules.push(createParticule(x, y)) }

anime
.timeline()
.add({
targets: particules,
x(p) {
return p.endPos.x
},
y(p) {
return p.endPos.y
},
radius: 0.1,
duration: anime.random(
config.animeDuration.min,
config.animeDuration.max
),
easing: 'easeOutExpo',
update: renderParticule
})
.add(
{
targets: circle,
radius: anime.random(config.orbitRadius.min, config.orbitRadius.max),
lineWidth: 0,
alpha: {
value: 0,
easing: 'linear',
duration: anime.random(600, 800)
},
duration: anime.random(1200, 1800),
easing: 'easeOutExpo',
update: renderParticule
},
0
)
}

const render = anime({
duration: Infinity,
update: () => {
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height)
}
})

document.addEventListener(
'mousedown',
(e) => {
render.play()
updateCoords(e)
animateParticules(pointerX, pointerY)
},
false
)

setCanvasSize(canvasEl)
window.addEventListener(
'resize',
() => {
setCanvasSize(canvasEl)
},
false
)
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@next/bundle-analyzer": "^12.1.1",
"@popperjs/core": "^2.9.3",
"animate.css": "^4.1.1",
"animejs": "^3.2.1",
"axios": ">=0.21.1",
"copy-to-clipboard": "^3.3.1",
"feed": "^4.2.2",
Expand Down
4 changes: 3 additions & 1 deletion pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import dynamic from 'next/dynamic'
import { GlobalContextProvider } from '@/lib/global'
import { DebugPanel } from '@/components/DebugPanel'
import { ThemeSwitch } from '@/components/ThemeSwitch'
import { Fireworks } from '@/components/Fireworks'

const Ackee = dynamic(() => import('@/components/Ackee'), { ssr: false })
const Gtag = dynamic(() => import('@/components/Gtag'), { ssr: false })
Expand All @@ -36,13 +37,14 @@ const MyApp = ({ Component, pageProps }) => {
{JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && <Busuanzi />}
{BLOG.ADSENSE_GOOGLE_ID && <GoogleAdsense />}
{BLOG.FACEBOOK_APP_ID && BLOG.FACEBOOK_PAGE_ID && <Messenger />}
{JSON.parse(BLOG.FIREWORKS) && <Fireworks/>}
</>

return (
<GlobalContextProvider>
{externalPlugins}
{/* FontawesomeCDN */}
<link rel="stylesheet" href={BLOG.FONT_AWESOME_PATH} referrerPolicy="no-referrer" />
{externalPlugins}
<Component {...pageProps} />
</GlobalContextProvider>
)
Expand Down
9 changes: 8 additions & 1 deletion styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,11 @@ nav {

.notion-code-copy-button > svg{
pointer-events:none
}
}

.fireworks{
position: fixed;
left: 0;
top: 0;
z-index: 11;
pointer-events: none;}

0 comments on commit c7908a5

Please sign in to comment.