1
1
<template >
2
2
<div class =" w-[80rem] md:w-full flex md:flex-col items-start justify-between p-6 md:p-0" >
3
3
4
- <div class =" w-3/5 mb-4 mr-8 md:w-full" >
4
+ <div class =" relative w-3/5 mb-4 mr-8 md:w-full" >
5
+ <!-- Skeleton loading -->
6
+ <div v-if =" isLoading" class =" absolute top-0 w-full aspect-[500/660] rounded-xl overflow-hidden bg-gray-50" >
7
+ <!-- 主体骨架 -->
8
+ <div class =" absolute inset-0 bg-gradient-to-br from-gray-200 to-gray-100" ></div >
9
+ <!-- 文字区域骨架 -->
10
+ <div class =" absolute inset-0 flex flex-col items-center justify-center p-8 space-y-4" >
11
+ <div class =" w-1/2 h-4 bg-gray-300 rounded animate-pulse" ></div >
12
+ <div class =" w-2/3 h-4 bg-gray-300 rounded animate-pulse" ></div >
13
+ <div class =" w-2/3 h-4 bg-gray-300 rounded animate-pulse" ></div >
14
+ <div class =" w-3/4 h-4 bg-gray-300 rounded animate-pulse" ></div >
15
+ <div class =" w-2/3 h-4 bg-gray-300 rounded animate-pulse" ></div >
16
+ <div class =" w-1/2 h-4 bg-gray-300 rounded animate-pulse" ></div >
17
+ </div >
18
+ <!-- 闪光效果 -->
19
+ <div class =" absolute inset-0" >
20
+ <div class =" absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent animate-shimmer" >
21
+ </div >
22
+ </div >
23
+ </div >
24
+ <!-- Canvas content -->
5
25
<canvas id =" digest" ref =" canvasRef" width =" 500" height =" 660" class =" w-full border rounded-xl" ></canvas >
6
26
</div >
7
27
71
91
<!-- 背景选择部分的修改 -->
72
92
<strong class =" text-lg font-medium" >选择背景</strong >
73
93
<div class =" grid grid-cols-3 gap-6 md:grid-cols-2" >
74
- <!-- 现有背景选项部分保持不变 -->
75
94
<div v-for =" (bg, index) in backgrounds" :key =" index"
76
- class =" w-24 h-24 overflow-hidden border rounded-lg cursor-pointer"
77
- :class =" { 'ring-2 ring-blue-500': selectedBg === index }" @click =" selectedBg = index" >
78
- <img :src =" bg" class =" object-cover w-full h-full" />
95
+ class =" w-24 h-24 overflow-hidden transition-all duration-200 border rounded-lg cursor-pointer group hover:shadow-md"
96
+ :class =" { 'ring-2 ring-blue-500 shadow-lg': selectedBg === index }" @click =" selectedBg = index"
97
+ role =" button" :aria-label =" `选择文摘背景图片 ${index + 1}`" :title =" `背景图片 ${index + 1}`" >
98
+ <img :src =" bg" class =" object-cover w-full h-full transition-transform duration-300 group-hover:scale-110"
99
+ loading =" lazy" :alt =" `文摘背景图片 ${index + 1}`" @error =" handleImageError(index)"
100
+ @load =" handleImageLoad(index)" />
79
101
</div >
80
102
</div >
81
103
@@ -138,6 +160,7 @@ const letterSpacing = ref(100)
138
160
const fontWeight = ref (' normal' )
139
161
const textColor = ref (' #000000' )
140
162
const selectedBg = ref (0 )
163
+ const isLoading = ref (true )
141
164
const { proxy } = getCurrentInstance () as any
142
165
143
166
// 添加字重选项配置
@@ -181,22 +204,26 @@ onMounted(() => {
181
204
loadBackgroundImage ()
182
205
})
183
206
184
- // 加载背景图
207
+ // 修改 loadBackgroundImage 函数
185
208
const loadBackgroundImage = () => {
209
+ isLoading .value = true
186
210
const img = new Image ()
187
211
img .onload = () => {
188
212
drawCanvas (img )
213
+ isLoading .value = false
214
+ }
215
+ img .onerror = () => {
216
+ toast .show (' 背景图片加载失败' )
217
+ isLoading .value = false
189
218
}
190
219
img .src = backgrounds .value [selectedBg .value ]
191
220
}
192
221
193
- // 绘制 canvas
194
222
const drawCanvas = async (backgroundImage ) => {
195
223
const canvas = canvasRef .value
196
224
const context = ctx .value
197
225
const padding = 10 // 设置内边距
198
226
199
- // 清空画布
200
227
context .clearRect (0 , 0 , canvas .width , canvas .height )
201
228
202
229
// 绘制背景
@@ -293,10 +320,12 @@ function onCopyImage() {
293
320
})
294
321
])
295
322
toast .show (' 已复制图片至您的剪切板' )
323
+ proxy .$reortGaEvent (' copy-image' , ' digest' )
296
324
})
297
325
.catch ((error ) => {
298
326
console .error (' 复制图片失败:' , error )
299
327
toast .show (' 复制图片失败,请重试' )
328
+ proxy .$reortGaEvent (' copy-image-failed' , ' digest' )
300
329
})
301
330
}
302
331
@@ -307,10 +336,12 @@ function onSave2Image() {
307
336
.then ((blob ) => {
308
337
download2png (blob )
309
338
toast .show (' 已成功为你保存图片' )
339
+ proxy .$reortGaEvent (' save-image' , ' digest' )
310
340
})
311
341
.catch ((error ) => {
312
342
console .error (' 保存图片失败:' , error )
313
343
toast .show (' 保存图片失败,请重试' )
344
+ proxy .$reortGaEvent (' save-image-failed' , ' digest' )
314
345
})
315
346
}
316
347
// 处理图片上传
@@ -324,15 +355,10 @@ const handleImageUpload = (event: Event) => {
324
355
return
325
356
}
326
357
327
- // 创建临时URL
328
358
const imageUrl = URL .createObjectURL (file )
329
-
330
- // 添加到背景列表的开头
331
359
backgrounds .value .unshift (imageUrl )
332
-
333
360
// 选中新上传的图片
334
361
selectedBg .value = 0 ;
335
-
336
362
// 清空 input,允许重复上传同一张图片
337
363
(event .target as HTMLInputElement ).value = ' '
338
364
}
@@ -346,6 +372,15 @@ function handleSelectFont(item) {
346
372
fontFamily .value = item .id
347
373
proxy .$reortGaEvent (' select-font' , ' digest' )
348
374
}
375
+
376
+ const handleImageError = (index : number ) => {
377
+ console .debug (` 背景图片 ${index + 1 } 加载失败 ` )
378
+ proxy .$reortGaEvent (' load-bg-failed' , ' digest' )
379
+ }
380
+
381
+ const handleImageLoad = (index : number ) => {
382
+ console .debug (` 背景图片 ${index + 1 } 加载成功 ` )
383
+ }
349
384
</script >
350
385
351
386
<style scoped>
@@ -357,6 +392,21 @@ input[type="range"]::-webkit-slider-thumb {
357
392
@apply appearance-none w- 4 h- 4 bg-blue- 500 rounded-full cursor-pointer ;
358
393
}
359
394
395
+ /* 添加闪光动画 */
396
+ @keyframes shimmer {
397
+ 0% {
398
+ transform : translateX (-100% );
399
+ }
400
+
401
+ 100% {
402
+ transform : translateX (100% );
403
+ }
404
+ }
405
+
406
+ .animate-shimmer {
407
+ animation : shimmer 1.5s infinite ;
408
+ }
409
+
360
410
@font-face {
361
411
font-family : ' ShouJinTi' ;
362
412
font-style : normal ;
@@ -379,4 +429,4 @@ input[type="range"]::-webkit-slider-thumb {
379
429
@import url (' https://fonts.googleapis.com/css2?family=Noto+Sans+SC&display=swap' );
380
430
@import url (' https://static.zeoseven.com/zsft/440/main/result.css' );
381
431
@import url (' https://static.zeoseven.com/zsft/5/main/result.css' );
382
- </style >
432
+ </style >
0 commit comments