diff --git a/frontend/src/views/CaptureOverlay.vue b/frontend/src/views/CaptureOverlay.vue
index 633b75a..1408449 100644
--- a/frontend/src/views/CaptureOverlay.vue
+++ b/frontend/src/views/CaptureOverlay.vue
@@ -24,7 +24,7 @@ interface Rect {
h: number
}
-type Tool = 'pen' | 'rect' | 'ellipse' | 'text' | 'mosaic-brush' | 'mosaic-rect'
+type Tool = 'pen' | 'line' | 'arrow' | 'rect' | 'ellipse' | 'text' | 'mosaic-brush' | 'mosaic-rect'
type MosaicMode = 'brush' | 'rect'
interface Point {
x: number
@@ -150,18 +150,18 @@ const sizeLabel = computed(() => {
return `${Math.round(rect.value.w)} × ${Math.round(rect.value.h)}`
})
-const MARK_TOOLBAR_W = 212
+const MARK_TOOLBAR_W = 280
const ACTION_TOOLBAR_W = 288
const TOOLBAR_GROUP_GAP = 8
-const toolOrder: Tool[] = ['pen', 'rect', 'ellipse', 'text', 'mosaic-brush', 'mosaic-rect']
+const toolOrder: Tool[] = ['pen', 'line', 'arrow', 'rect', 'ellipse', 'text', 'mosaic-brush', 'mosaic-rect']
const toolSettingsPos = computed(() => {
if (!leftToolbarPos.value || !rect.value || !activeTool.value) return null
const isMosaic = activeTool.value.startsWith('mosaic-')
const menuW = isMosaic ? (mosaicMode.value === 'brush' ? 328 : 112) : activeTool.value === 'text' ? 462 : 398
const menuH = 58
- const buttonIndex = isMosaic ? 4 : toolOrder.indexOf(activeTool.value)
+ const buttonIndex = isMosaic ? 6 : toolOrder.indexOf(activeTool.value)
const buttonCenter = 4 + buttonIndex * 34 + 14
let x = leftToolbarPos.value.x
let y = leftToolbarPos.value.y + 44
@@ -315,6 +315,28 @@ function textRenderBox(annotation: Annotation) {
}
}
+function arrowHeadPoints(annotation: Annotation) {
+ if (annotation.points.length < 2) return ''
+ const start = annotation.points[0]
+ const end = annotation.points[annotation.points.length - 1]
+ const dx = end.x - start.x
+ const dy = end.y - start.y
+ const length = Math.hypot(dx, dy)
+ if (length < 1) return ''
+ const headLength = Math.min(length * 0.45, Math.max(10, (annotation.strokeWidth || 3) * 4))
+ const angle = Math.atan2(dy, dx)
+ const spread = Math.PI / 6
+ const left = {
+ x: end.x - headLength * Math.cos(angle - spread),
+ y: end.y - headLength * Math.sin(angle - spread),
+ }
+ const right = {
+ x: end.x - headLength * Math.cos(angle + spread),
+ y: end.y - headLength * Math.sin(angle + spread),
+ }
+ return `${left.x},${left.y} ${end.x},${end.y} ${right.x},${right.y}`
+}
+
function textAnnotationIndexAtPoint(p: Point) {
if (!rect.value) return null
for (let i = annotations.value.length - 1; i >= 0; i--) {
@@ -795,6 +817,35 @@ onUnmounted(() => {
stroke-linejoin="round"
fill="none"
/>
+
+
+
+
+
{
+
+