功能很鸡肋,直接上代码
<template>
<div class="screenshot-container">
<button @click="startScreenshot" class="screenshot-btn">开始截图</button>
<div v-if="isSelecting" class="selection-area" :style="selectionStyle" @mousedown="startSelection"
@mousemove="updateSelection" @mouseup="endSelection" @touchstart="startTouchSelection"
@touchmove="updateTouchSelection" @touchend="endSelection">
<div class="selection-box" :style="boxStyle"></div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import html2canvas from 'html2canvas'
const isSelecting = ref(false)
const startPos = ref({ x: 0, y: 0 })
const currentPos = ref({ x: 0, y: 0 })
const selectionBox = ref({ width: 0, height: 0, left: 0, top: 0 })
const isTouching = ref(false)
const selectionStyle = computed(() => ({
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100vh',
background: 'rgba(0, 0, 0, 0.3)',
cursor: 'crosshair',
zIndex: 9999,
touchAction: 'none' // 防止触摸事件触发浏览器默认行为
}))
const boxStyle = computed(() => ({
position: 'absolute',
border: '2px solid #1890ff',
background: 'rgba(24, 144, 255, 0.1)',
left: `${selectionBox.value.left}px`,
top: `${selectionBox.value.top}px`,
width: `${selectionBox.value.width}px`,
height: `${selectionBox.value.height}px`
}))
const startScreenshot = () => {
isSelecting.value = true
}
// 鼠标事件处理
const startSelection = (e) => {
if (isTouching.value) return
startPos.value = {
x: e.clientX,
y: e.clientY
}
}
const updateSelection = (e) => {
if (e.buttons !== 1 || isTouching.value) return
currentPos.value = {
x: e.clientX,
y: e.clientY
}
updateSelectionBox()
}
// 触摸事件处理
const startTouchSelection = (e) => {
e.preventDefault()
isTouching.value = true
const touch = e.touches[0]
startPos.value = {
x: touch.clientX,
y: touch.clientY
}
}
const updateTouchSelection = (e) => {
e.preventDefault()
if (!isTouching.value) return
const touch = e.touches[0]
currentPos.value = {
x: touch.clientX,
y: touch.clientY
}
updateSelectionBox()
}
// 更新选择框
const updateSelectionBox = () => {
selectionBox.value = {
left: Math.min(startPos.value.x, currentPos.value.x),
top: Math.min(startPos.value.y, currentPos.value.y),
width: Math.abs(currentPos.value.x - startPos.value.x),
height: Math.abs(currentPos.value.y - startPos.value.y)
}
}
const endSelection = async () => {
try {
isTouching.value = false
// 隐藏选择框
isSelecting.value = false
// 等待一下以确保选择框被隐藏
await new Promise(resolve => setTimeout(resolve, 100))
// 获取整个文档的截图
const canvas = await html2canvas(document.body, {
scale: window.devicePixelRatio, // 使用设备像素比
useCORS: true, // 允许跨域图片
allowTaint: true, // 允许跨域图片
backgroundColor: '#ffffff', // 设置白色背景
logging: false, // 关闭日志
x: window.scrollX + selectionBox.value.left,
y: window.scrollY + selectionBox.value.top,
width: selectionBox.value.width,
height: selectionBox.value.height,
windowWidth: document.documentElement.offsetWidth,
windowHeight: document.documentElement.offsetHeight
})
// 将截图转换为图片
const imageUrl = canvas.toDataURL('image/png')
// 创建一个临时链接并触发下载
const link = document.createElement('a')
link.href = imageUrl
link.download = `screenshot-${Date.now()}.png`
link.click()
} catch (err) {
console.error('截图失败:', err)
}
}
</script>
<style scoped>
.screenshot-container {
position: relative;
}
.screenshot-btn {
padding: 8px 16px;
background: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.screenshot-btn:hover {
background: #40a9ff;
}
/* 移动端样式优化 */
@media (max-width: 768px) {
.screenshot-btn {
padding: 12px 20px;
font-size: 16px;
}
.selection-box {
min-width: 30px;
min-height: 30px;
}
}
</style>