更新页面效果,但是会卡顿
This commit is contained in:
@@ -8,6 +8,8 @@ import { onMounted, onUnmounted, watch, ref } from 'vue'
|
||||
const props = defineProps({
|
||||
petalEnabled: { type: Boolean, default: true },
|
||||
bubbleEnabled: { type: Boolean, default: true },
|
||||
active: { type: Boolean, default: true },
|
||||
performanceMode: { type: Boolean, default: false },
|
||||
})
|
||||
|
||||
const canvasRef = ref(null)
|
||||
@@ -22,6 +24,7 @@ let width = 0
|
||||
let height = 0
|
||||
let dpr = 1
|
||||
let lastTime = 0
|
||||
let lastPaint = 0
|
||||
let resizeObserver = null
|
||||
let reduceMotion = false
|
||||
|
||||
@@ -52,14 +55,16 @@ function resetHeart(h, initial = false) {
|
||||
}
|
||||
|
||||
function seedParticles() {
|
||||
const petalCount = props.performanceMode ? 8 : 18
|
||||
const heartCount = props.performanceMode ? 5 : 12
|
||||
petals.length = 0
|
||||
hearts.length = 0
|
||||
for (let i = 0; i < 18; i += 1) {
|
||||
for (let i = 0; i < petalCount; i += 1) {
|
||||
const p = {}
|
||||
resetPetal(p, true)
|
||||
petals.push(p)
|
||||
}
|
||||
for (let i = 0; i < 12; i += 1) {
|
||||
for (let i = 0; i < heartCount; i += 1) {
|
||||
const h = {}
|
||||
resetHeart(h, true)
|
||||
hearts.push(h)
|
||||
@@ -72,7 +77,7 @@ function resize() {
|
||||
const rect = canvas.getBoundingClientRect()
|
||||
width = Math.max(1, rect.width)
|
||||
height = Math.max(1, rect.height)
|
||||
dpr = Math.min(window.devicePixelRatio || 1, 2)
|
||||
dpr = props.performanceMode ? 1 : Math.min(window.devicePixelRatio || 1, 1.5)
|
||||
canvas.width = Math.round(width * dpr)
|
||||
canvas.height = Math.round(height * dpr)
|
||||
ctx = canvas.getContext('2d')
|
||||
@@ -119,11 +124,24 @@ function drawHeart(h, now) {
|
||||
|
||||
function tick(now) {
|
||||
if (!ctx) return
|
||||
if (!props.active || reduceMotion || (!props.petalEnabled && !props.bubbleEnabled)) {
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
rafId = 0
|
||||
return
|
||||
}
|
||||
|
||||
const frameInterval = props.performanceMode ? 50 : 16.7
|
||||
if (lastPaint && now - lastPaint < frameInterval) {
|
||||
rafId = requestAnimationFrame(tick)
|
||||
return
|
||||
}
|
||||
|
||||
const delta = Math.min(48, now - (lastTime || now)) / 1000
|
||||
lastTime = now
|
||||
lastPaint = now
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
|
||||
if (!reduceMotion && props.petalEnabled) {
|
||||
if (props.petalEnabled) {
|
||||
for (const p of petals) {
|
||||
p.y += p.speed * delta
|
||||
p.rotation += p.rotationSpeed * delta
|
||||
@@ -132,7 +150,7 @@ function tick(now) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!reduceMotion && props.bubbleEnabled) {
|
||||
if (props.bubbleEnabled) {
|
||||
for (const h of hearts) {
|
||||
h.y -= h.speed * delta
|
||||
if (h.y < -80) resetHeart(h)
|
||||
@@ -146,6 +164,12 @@ function tick(now) {
|
||||
function start() {
|
||||
cancelAnimationFrame(rafId)
|
||||
lastTime = 0
|
||||
lastPaint = 0
|
||||
if (!props.active || reduceMotion || (!props.petalEnabled && !props.bubbleEnabled)) {
|
||||
ctx?.clearRect(0, 0, width, height)
|
||||
rafId = 0
|
||||
return
|
||||
}
|
||||
rafId = requestAnimationFrame(tick)
|
||||
}
|
||||
|
||||
@@ -157,7 +181,13 @@ onMounted(() => {
|
||||
start()
|
||||
})
|
||||
|
||||
watch(() => [props.petalEnabled, props.bubbleEnabled], start)
|
||||
watch(
|
||||
() => [props.petalEnabled, props.bubbleEnabled, props.active, props.performanceMode],
|
||||
() => {
|
||||
resize()
|
||||
start()
|
||||
}
|
||||
)
|
||||
|
||||
onUnmounted(() => {
|
||||
cancelAnimationFrame(rafId)
|
||||
@@ -173,5 +203,7 @@ onUnmounted(() => {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
pointer-events: none;
|
||||
contain: strict;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user