Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c94f2db87 | ||
|
|
f01870c072 |
No files matched your search
@@ -14,28 +14,36 @@ const EMOJI_SVGS = [
|
||||
// 将 emoji SVG 转成 confetti 可用的彩色位图 Shape,缓存后供重复调用复用
|
||||
let emojiShapesPromise: Promise<confetti.Shape[]> | null = null
|
||||
|
||||
/**
|
||||
* 表情在屏幕上的边长(px)。位图就按这个大小画,放的时候 `scalar: 1`、矩阵不缩放。
|
||||
*
|
||||
* **别改回「位图画大、矩阵缩小、scalar 放大」**:canvas-confetti 画位图粒子是每帧
|
||||
* `fillRect(位图边长 × scalar)` 再用图案填,填的矩形和表情实际多大无关。原来位图 64、
|
||||
* scalar 5,表情显示 50px,每个粒子每帧却要填 320×320 —— 两团 32 个粒子一帧三百多万像素,
|
||||
* 机房电脑(显卡弱、Chrome 常走软件渲染)放到这一种就卡(用户 2026-11 反馈)。
|
||||
* 现在填的正好是 50×50,同样大小、同样轨迹,像素少到四十分之一。
|
||||
*/
|
||||
const EMOJI_PX = 50
|
||||
|
||||
function svgToBitmapShape(svg: string): Promise<confetti.Shape> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const blob = new Blob([svg], { type: 'image/svg+xml' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const img = new Image()
|
||||
img.onload = async () => {
|
||||
const renderSize = 64
|
||||
const baseUnit = 10
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = renderSize
|
||||
canvas.height = renderSize
|
||||
canvas.width = EMOJI_PX
|
||||
canvas.height = EMOJI_PX
|
||||
const ctx = canvas.getContext('2d')!
|
||||
ctx.drawImage(img, 0, 0, renderSize, renderSize)
|
||||
ctx.drawImage(img, 0, 0, EMOJI_PX, EMOJI_PX)
|
||||
URL.revokeObjectURL(url)
|
||||
|
||||
try {
|
||||
const bitmap = await createImageBitmap(canvas)
|
||||
const scale = baseUnit / renderSize
|
||||
resolve({
|
||||
type: 'bitmap',
|
||||
bitmap,
|
||||
matrix: [scale, 0, 0, scale, (-renderSize * scale) / 2, (-renderSize * scale) / 2],
|
||||
matrix: [1, 0, 0, 1, -EMOJI_PX / 2, -EMOJI_PX / 2],
|
||||
} as unknown as confetti.Shape)
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
@@ -415,7 +423,8 @@ export function useFireworks() {
|
||||
const options: confetti.Options = {
|
||||
shapes: emojiShapes,
|
||||
flat: true,
|
||||
scalar: 5,
|
||||
// 大小在位图里(EMOJI_PX),这里放大的话填的矩形跟着放大,见 EMOJI_PX
|
||||
scalar: 1,
|
||||
particleCount: 16,
|
||||
spread: 360,
|
||||
startVelocity: 40,
|
||||
|
||||
@@ -13,4 +13,13 @@ import { createGlobalState, useDark as useVueUseDark } from '@vueuse/core'
|
||||
* 切筛选再来 30 次,右栏换一条又是三四次。2026-11 实测(生产构建、CPU 降速 6 倍)首屏
|
||||
* 光这一处就占了 1.3 秒。全站共用一个之后只在第一次挂载时同步,后面的调用都是读同一个 ref。
|
||||
*/
|
||||
export const useDark = createGlobalState(() => useVueUseDark())
|
||||
export const useDark = createGlobalState(() =>
|
||||
useVueUseDark({
|
||||
// 剩下的那一次(一进页面它还要同步两遍)也省掉:<html> 上的 class 已经对了就不动。
|
||||
// 只有真要切换时才走它原来那套(关过渡 + 重算),切暗色不会有颜色慢慢渐变的过渡
|
||||
onChanged(dark, defaultHandler, mode) {
|
||||
if (document.documentElement.classList.contains('dark') === dark) return
|
||||
defaultHandler(mode)
|
||||
},
|
||||
}),
|
||||
)
|
||||
Reference in new issue
Block a user