1. 礼物特效

This commit is contained in:
李琦
2026-08-03 13:28:26 +08:00
parent 43957f6547
commit e9410c47a9
2 changed files with 127 additions and 39 deletions

View File

@@ -1,5 +1,7 @@
<template>
<canvas ref="canvasRef" class="gift-effect-canvas" aria-hidden="true" />
<Teleport to="body">
<canvas ref="canvasRef" class="gift-effect-canvas" aria-hidden="true" />
</Teleport>
</template>
<script setup>
@@ -252,12 +254,22 @@ function resizeCanvas() {
const canvas = canvasRef.value
if (!canvas) return
dpr = Math.min(window.devicePixelRatio || 1, DPR_CAP)
// iOS优先用 visualViewport,避免地址栏伸缩导致尺寸错乱
const vv = typeof window !== 'undefined' ? window.visualViewport : null
const cssW = Math.max(1, Math.floor((vv && vv.width) || window.innerWidth || canvas.clientWidth || 1))
const cssH = Math.max(1, Math.floor((vv && vv.height) || window.innerHeight || canvas.clientHeight || 1))
// 用布局视口铺满全屏。iOS visualViewport 常窄于整屏且有 offset
// 再叠 wrapper overflow 裁切,会出现「只盖住左侧一块」的灰幕。
const cssW = Math.max(
1,
Math.floor(window.innerWidth || 0),
Math.floor(document.documentElement?.clientWidth || 0),
)
const cssH = Math.max(
1,
Math.floor(window.innerHeight || 0),
Math.floor(document.documentElement?.clientHeight || 0),
)
W = cssW
H = cssH
canvas.style.left = '0px'
canvas.style.top = '0px'
canvas.style.width = `${cssW}px`
canvas.style.height = `${cssH}px`
canvas.style.writingMode = 'horizontal-tb'
@@ -819,7 +831,7 @@ function playOne(item) {
const payload = normalizePlayItem(item)
if (!payload) return 0
const { giftType, name, count } = payload
if (!W || !H) resizeCanvas()
resizeCanvas()
clearVisuals()
const now = performance.now()
const style = GIFT_STYLE[giftType]
@@ -1340,7 +1352,6 @@ onMounted(() => {
}
window.addEventListener('resize', onResize)
window.visualViewport?.addEventListener('resize', onResize)
window.visualViewport?.addEventListener('scroll', onResize)
})
onUnmounted(() => {
@@ -1353,7 +1364,6 @@ onUnmounted(() => {
if (rafId) cancelAnimationFrame(rafId)
window.removeEventListener('resize', onResize)
window.visualViewport?.removeEventListener('resize', onResize)
window.visualViewport?.removeEventListener('scroll', onResize)
texts = []
particles = []
rings = []
@@ -1379,9 +1389,11 @@ defineExpose({ play, playSequence, clear: clearAll, stop: clearAll })
<style scoped>
.gift-effect-canvas {
position: fixed;
inset: 0;
left: 0;
top: 0;
width: 100%;
width: 100vw;
width: 100dvw;
height: 100%;
height: 100dvh;
z-index: 46;
@@ -1391,9 +1403,9 @@ defineExpose({ play, playSequence, clear: clearAll, stop: clearAll })
text-orientation: mixed;
direction: ltr;
white-space: nowrap;
/* iOS独立合成层,避免和左侧点赞 canvas / transform 滚动打架 */
transform: translateZ(0);
-webkit-transform: translateZ(0);
/* 独立合成层;挂到 body 后不再受请柬 wrapper overflow 裁切 */
transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}