forked from zhongyidian/super_video
feat: 对接各个视频数据
This commit is contained in:
1 parent
6103453e32
commit
6ab98c4764
339 files changed
+17316
-1531
No files matched your search
@@ -0,0 +1,124 @@
|
||||
import { snapdom } from '@zumer/snapdom'
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
/**
|
||||
* 统一的高清截图功能
|
||||
* 使用 SnapDOM 提供更好的样式保留和更高的截图质量
|
||||
*/
|
||||
export function useScreenshot() {
|
||||
/**
|
||||
* 截取指定区域的高清截图
|
||||
* @param options.selector - 要截图的容器选择器
|
||||
* @param options.cropArea - 可选的裁剪区域 { x, y, width, height }
|
||||
* @param options.hideElements - 截图前要隐藏的元素选择器数组(会设置 display: none)
|
||||
* @param options.ignoreElements - 截图时要忽略的元素选择器数组(SnapDOM 会跳过渲染,但元素保持显示)
|
||||
* @param options.scale - 缩放比例,默认 2(高清)
|
||||
* @returns Promise<string> - 图片的 Data URL
|
||||
*/
|
||||
const captureArea = async (options: {
|
||||
selector: string
|
||||
cropArea?: { x: number; y: number; width: number; height: number }
|
||||
hideElements?: string[]
|
||||
ignoreElements?: string[]
|
||||
scale?: number
|
||||
}): Promise<string> => {
|
||||
const { selector, cropArea, hideElements = [], ignoreElements = [], scale = 2 } = options
|
||||
|
||||
try {
|
||||
// 1. 隐藏UI元素
|
||||
const hiddenElements: HTMLElement[] = []
|
||||
hideElements.forEach(sel => {
|
||||
const elements = document.querySelectorAll(sel)
|
||||
elements.forEach(el => {
|
||||
const htmlEl = el as HTMLElement
|
||||
if (htmlEl.style.display !== 'none') {
|
||||
hiddenElements.push(htmlEl)
|
||||
htmlEl.style.display = 'none'
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 2. 等待DOM更新
|
||||
await nextTick()
|
||||
|
||||
// 3. 获取目标元素
|
||||
const targetElement = document.querySelector(selector) as HTMLElement
|
||||
if (!targetElement) {
|
||||
throw new Error(`Target element not found: ${selector}`)
|
||||
}
|
||||
|
||||
// 4. 使用 SnapDOM 截图(高清模式)
|
||||
const canvas = await (snapdom as any).toCanvas(targetElement, {
|
||||
scale: scale,
|
||||
backgroundColor: null,
|
||||
ignore: (element: Element) => {
|
||||
// 检查元素是否匹配 ignoreElements 中的选择器
|
||||
if (ignoreElements.length > 0) {
|
||||
for (const sel of ignoreElements) {
|
||||
if (element.matches && element.matches(sel)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
// 5. 恢复隐藏的元素
|
||||
hiddenElements.forEach(el => {
|
||||
el.style.display = ''
|
||||
})
|
||||
|
||||
// 6. 如果需要裁剪
|
||||
if (cropArea) {
|
||||
const croppedCanvas = document.createElement('canvas')
|
||||
const ctx = croppedCanvas.getContext('2d')
|
||||
if (!ctx) {
|
||||
throw new Error('Cannot get canvas context')
|
||||
}
|
||||
|
||||
// 设置裁剪后的canvas尺寸
|
||||
croppedCanvas.width = cropArea.width * scale
|
||||
croppedCanvas.height = cropArea.height * scale
|
||||
|
||||
// 计算缩放比例
|
||||
const scaleX = canvas.width / targetElement.offsetWidth
|
||||
const scaleY = canvas.height / targetElement.offsetHeight
|
||||
|
||||
// 裁剪图像
|
||||
ctx.drawImage(
|
||||
canvas,
|
||||
cropArea.x * scaleX,
|
||||
cropArea.y * scaleY,
|
||||
cropArea.width * scaleX,
|
||||
cropArea.height * scaleY,
|
||||
0,
|
||||
0,
|
||||
cropArea.width * scale,
|
||||
cropArea.height * scale
|
||||
)
|
||||
|
||||
return croppedCanvas.toDataURL('image/png')
|
||||
}
|
||||
|
||||
// 7. 返回完整截图
|
||||
return canvas.toDataURL('image/png')
|
||||
} catch (error) {
|
||||
console.error('Screenshot failed:', error)
|
||||
|
||||
// 确保恢复所有元素
|
||||
hideElements.forEach(sel => {
|
||||
const elements = document.querySelectorAll(sel)
|
||||
elements.forEach(el => {
|
||||
;(el as HTMLElement).style.display = ''
|
||||
})
|
||||
})
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
captureArea
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user