Przeglądaj źródła

fix(student view): 修复iframe截图的动画干扰和渲染不稳定问题

1. 新增全局禁用动画的style标签来避免截图时的动画闪烁
2. 强制触发重排确保样式生效
3. 针对ECharts图表增加等待渲染完成的延迟逻辑
4. 使用try-finally确保临时添加的样式标签会被清理
lsc 1 tydzień temu
rodzic
commit
321c465848
1 zmienionych plików z 43 dodań i 18 usunięć
  1. 43 18
      src/views/Student/index.vue

+ 43 - 18
src/views/Student/index.vue

@@ -2193,24 +2193,49 @@ const handleHomeworkSubmit = async () => {
             for (let i = 0;i < b.length;i++) {
               b[i].crossOrigin = 'anonymous'
             }
-            
-            // 直接对iframe内部的body进行截图
-            const html2canvas = await import('html2canvas')
-            const canvas = await html2canvas.default(iframeBody, {
-              // useCORS: true,
-              // allowTaint: true,
-              // scale: 1,
-              // backgroundColor: '#ffffff',
-              // logging: false,
-              // foreignObjectRendering: true,
-              // removeContainer: true
-              scale: 2, // 提高清晰度
-              allowTaint: false, // 是否允许跨域污染画布
-              useCORS: true, // 尝试跨域加载图片
-              logging: true,
-            })
-            imageData = canvas.toDataURL('image/png', 0.95)
-            
+
+            // 1. 创建全局禁用动画的 style 标签
+            const style = document.createElement('style')
+            style.id = 'html2canvas-freeze'
+            style.textContent = `
+        *, *::before, *::after {
+            animation: none !important;
+            transition: none !important;
+        }
+    `
+            iframeElement.contentWindow.document.head.appendChild(style)
+
+            // 2. 强制重排,确保禁用生效
+            iframeElement.contentWindow.document.body.offsetHeight
+
+            // 3. 如果词云图使用 ECharts 且存在,等它渲染稳定
+            if (typeof iframeElement.contentWindow.myChart !== 'undefined' && iframeElement.contentWindow.myChart && !iframeElement.contentWindow.myChart.isDisposed()) {
+              // 延迟 500ms 等待 ECharts 内部的 Canvas 动画结束
+              await new Promise(resolve => setTimeout(resolve, 500))
+            }
+
+            try {
+              // 直接对iframe内部的body进行截图
+              const html2canvas = await import('html2canvas')
+              const canvas = await html2canvas.default(iframeBody, {
+                // useCORS: true,
+                // allowTaint: true,
+                // scale: 1,
+                // backgroundColor: '#ffffff',
+                // logging: false,
+                // foreignObjectRendering: true,
+                // removeContainer: true
+                scale: 2, // 提高清晰度
+                allowTaint: false, // 是否允许跨域污染画布
+                useCORS: true, // 尝试跨域加载图片
+                logging: true,
+              })
+              imageData = canvas.toDataURL('image/png', 0.95)
+            }
+            finally {
+              const freezeStyle = iframeElement.contentWindow.document.getElementById('html2canvas-freeze')
+              if (freezeStyle) freezeStyle.remove()
+            }
             console.log('成功截图iframe内部内容')
           }
           catch (html2canvasError) {