优化,贴图
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
} from '@lucide/vue'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
||||
import { Slider } from '@/components/ui/slider'
|
||||
import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'
|
||||
import {
|
||||
TOOLS, COLORS, BLOCK_SIZES, ALPHAS, HANDLES, HANDLE_HIT, DRAG_THRESHOLD,
|
||||
type Phase, type ToolType, type Annotation, type DrawableAnnotation,
|
||||
@@ -1779,7 +1780,16 @@ async function finish() {
|
||||
}
|
||||
}
|
||||
if (!out) return
|
||||
await emit(EVENTS.screenshotExported, { pngBase64: out.b64, width: out.w, height: out.h })
|
||||
// 附带框选区域的屏幕逻辑坐标(DIP):窗口逻辑位置 + 选区图像坐标。
|
||||
// 截图图像按虚拟屏 DIP 捕获,坐标按 DIP 传递,贴图窗口按 DIP 布局即可 1:1 还原
|
||||
const spPos = selPhys.value
|
||||
await emit(EVENTS.screenshotExported, {
|
||||
pngBase64: out.b64,
|
||||
width: out.w,
|
||||
height: out.h,
|
||||
posX: Math.round(winOuterX / dpr + spPos.x),
|
||||
posY: Math.round(winOuterY / dpr + spPos.y),
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('[screenshot] 完成失败', e)
|
||||
} finally {
|
||||
@@ -1801,7 +1811,14 @@ async function doSave() {
|
||||
})
|
||||
if (!path) return
|
||||
await commands.screenshotSavePng(out.b64, path)
|
||||
await emit(EVENTS.screenshotExported, { pngBase64: out.b64, width: out.w, height: out.h })
|
||||
const spPos = selPhys.value
|
||||
await emit(EVENTS.screenshotExported, {
|
||||
pngBase64: out.b64,
|
||||
width: out.w,
|
||||
height: out.h,
|
||||
posX: Math.round(winOuterX / dpr + spPos.x),
|
||||
posY: Math.round(winOuterY / dpr + spPos.y),
|
||||
})
|
||||
await win.hide().catch(() => {})
|
||||
} catch (e) {
|
||||
console.error('[screenshot] 保存失败', e)
|
||||
@@ -1985,6 +2002,7 @@ onUnmounted(() => {
|
||||
@mousemove="onMouseMove"
|
||||
@mouseup="onMouseUp"
|
||||
>
|
||||
<TooltipProvider>
|
||||
<!-- 冻结的屏幕底图 -->
|
||||
<img
|
||||
v-if="imgSrc"
|
||||
@@ -2094,31 +2112,37 @@ onUnmounted(() => {
|
||||
<div v-if="showToolbar" ref="toolbarRef" class="toolbar" :style="toolbarPos" @mousedown.stop>
|
||||
<!-- 标注工具 -->
|
||||
<div class="tb-group">
|
||||
<button
|
||||
v-for="t in TOOLS"
|
||||
:key="t.value"
|
||||
class="tb-icon"
|
||||
:class="{ active: phase === 'editing' && currentTool === t.value }"
|
||||
:title="t.label"
|
||||
@click="onSelectTool(t.value)"
|
||||
>
|
||||
<component :is="t.icon" class="tb-svg" />
|
||||
</button>
|
||||
<Tooltip v-for="t in TOOLS" :key="t.value">
|
||||
<TooltipTrigger as-child>
|
||||
<button
|
||||
class="tb-icon"
|
||||
:class="{ active: phase === 'editing' && currentTool === t.value }"
|
||||
@click="onSelectTool(t.value)"
|
||||
>
|
||||
<component :is="t.icon" class="tb-svg" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t.label }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div class="tb-sep" />
|
||||
|
||||
<!-- 颜色色卡:显示当前颜色,点击打开选色板 -->
|
||||
<Popover v-model:open="colorPickerOpen">
|
||||
<PopoverTrigger as-child>
|
||||
<button
|
||||
class="color-badge"
|
||||
:class="{ disabled: !colorEnabled }"
|
||||
:style="{ '--swatch-color': effectiveColor }"
|
||||
:disabled="!colorEnabled"
|
||||
title="颜色"
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<PopoverTrigger as-child>
|
||||
<button
|
||||
class="color-badge"
|
||||
:class="{ disabled: !colorEnabled }"
|
||||
:style="{ '--swatch-color': effectiveColor }"
|
||||
:disabled="!colorEnabled"
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>颜色</TooltipContent>
|
||||
</Tooltip>
|
||||
<PopoverContent class="w-auto p-3" align="start">
|
||||
<div class="color-popover">
|
||||
<input
|
||||
@@ -2128,15 +2152,17 @@ onUnmounted(() => {
|
||||
@input="onCustomColorPick(($event.target as HTMLInputElement).value)"
|
||||
/>
|
||||
<div class="color-swatches">
|
||||
<button
|
||||
v-for="c in COLORS"
|
||||
:key="c"
|
||||
class="color-swatch-mini"
|
||||
:class="{ active: effectiveColor === c }"
|
||||
:style="{ backgroundColor: c }"
|
||||
:title="c"
|
||||
@click="effectiveColor = c"
|
||||
/>
|
||||
<Tooltip v-for="c in COLORS" :key="c">
|
||||
<TooltipTrigger as-child>
|
||||
<button
|
||||
class="color-swatch-mini"
|
||||
:class="{ active: effectiveColor === c }"
|
||||
:style="{ backgroundColor: c }"
|
||||
@click="effectiveColor = c"
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ c }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
@@ -2144,14 +2170,18 @@ onUnmounted(() => {
|
||||
|
||||
<!-- 粗细 badge:点击打开 Slider -->
|
||||
<Popover v-model:open="lineWidthPickerOpen">
|
||||
<PopoverTrigger as-child>
|
||||
<button
|
||||
class="width-badge"
|
||||
:class="{ disabled: !lineWidthEnabled }"
|
||||
:disabled="!lineWidthEnabled"
|
||||
title="粗细"
|
||||
>{{ effectiveLineWidth }}</button>
|
||||
</PopoverTrigger>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<PopoverTrigger as-child>
|
||||
<button
|
||||
class="width-badge"
|
||||
:class="{ disabled: !lineWidthEnabled }"
|
||||
:disabled="!lineWidthEnabled"
|
||||
>{{ effectiveLineWidth }}</button>
|
||||
</PopoverTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>粗细</TooltipContent>
|
||||
</Tooltip>
|
||||
<PopoverContent class="w-auto p-3" align="start">
|
||||
<div class="width-popover">
|
||||
<div class="width-popover-header">
|
||||
@@ -2174,43 +2204,62 @@ onUnmounted(() => {
|
||||
<template v-if="currentTool === 'mosaic'">
|
||||
<div class="tb-sep" />
|
||||
<div class="tb-group">
|
||||
<button
|
||||
v-for="b in BLOCK_SIZES"
|
||||
:key="b"
|
||||
class="tb-num"
|
||||
:class="{ active: blockSize === b }"
|
||||
title="马赛克块大小"
|
||||
@click="blockSize = b"
|
||||
>{{ b }}</button>
|
||||
<Tooltip v-for="b in BLOCK_SIZES" :key="b">
|
||||
<TooltipTrigger as-child>
|
||||
<button
|
||||
class="tb-num"
|
||||
:class="{ active: blockSize === b }"
|
||||
@click="blockSize = b"
|
||||
>{{ b }}</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>马赛克块大小</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="currentTool === 'highlight'">
|
||||
<div class="tb-sep" />
|
||||
<div class="tb-group">
|
||||
<button
|
||||
v-for="a in ALPHAS"
|
||||
:key="a"
|
||||
class="tb-num"
|
||||
:class="{ active: highlightAlpha === a }"
|
||||
title="高亮透明度"
|
||||
@click="highlightAlpha = a"
|
||||
>{{ Math.round(a * 100) }}%</button>
|
||||
<Tooltip v-for="a in ALPHAS" :key="a">
|
||||
<TooltipTrigger as-child>
|
||||
<button
|
||||
class="tb-num"
|
||||
:class="{ active: highlightAlpha === a }"
|
||||
@click="highlightAlpha = a"
|
||||
>{{ Math.round(a * 100) }}%</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>高亮透明度</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="tb-sep" />
|
||||
|
||||
<div class="tb-group">
|
||||
<button class="tb-icon" :disabled="!canUndo" title="撤销" @click="undo">
|
||||
<Undo2 class="tb-svg" />
|
||||
</button>
|
||||
<button class="tb-icon" :disabled="!canRedo" title="重做" @click="redo">
|
||||
<Redo2 class="tb-svg" />
|
||||
</button>
|
||||
<button class="tb-icon" :disabled="!canUndo" title="清空标注" @click="clearAnnotations">
|
||||
<Eraser class="tb-svg" />
|
||||
</button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<button class="tb-icon" :disabled="!canUndo" @click="undo">
|
||||
<Undo2 class="tb-svg" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>撤销</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<button class="tb-icon" :disabled="!canRedo" @click="redo">
|
||||
<Redo2 class="tb-svg" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>重做</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<button class="tb-icon" :disabled="!canUndo" @click="clearAnnotations">
|
||||
<Eraser class="tb-svg" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>清空标注</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div class="tb-sep" />
|
||||
@@ -2221,12 +2270,22 @@ onUnmounted(() => {
|
||||
|
||||
<!-- 复制 / 保存(置末) -->
|
||||
<div class="tb-group">
|
||||
<button class="tb-icon" title="保存到文件" @click="doSave">
|
||||
<Save class="tb-svg" />
|
||||
</button>
|
||||
<button class="tb-icon primary" title="复制到剪贴板 (Enter)" @click="finish">
|
||||
<Copy class="tb-svg" />
|
||||
</button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<button class="tb-icon" @click="doSave">
|
||||
<Save class="tb-svg" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>保存到文件</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<button class="tb-icon primary" @click="finish">
|
||||
<Copy class="tb-svg" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>复制到剪贴板 (Enter)</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2245,6 +2304,7 @@ onUnmounted(() => {
|
||||
<div class="mag-hint">{{ hint.split(' · ').join('\n') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user