@libresign/pdf-elements 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/pdf-elements.common.js +25126 -24680
- package/dist/pdf-elements.common.js.map +1 -1
- package/dist/pdf-elements.css +1 -1
- package/dist/pdf-elements.umd.js +25126 -24680
- package/dist/pdf-elements.umd.js.map +1 -1
- package/dist/pdf-elements.umd.min.js +2 -2
- package/dist/pdf-elements.umd.min.js.map +1 -1
- package/package.json +1 -2
- package/src/components/DraggableElement.vue +29 -5
- package/src/components/PDFElements.vue +389 -173
- package/src/components/PDFPage.vue +31 -8
- package/src/index.js +0 -5
- package/src/utils/geometry.js +20 -0
- package/src/utils/measurements.js +16 -0
- package/src/utils/objectStore.js +35 -0
- package/src/utils/pageBounds.js +13 -0
- package/src/utils/zoom.js +8 -0
|
@@ -60,6 +60,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
60
60
|
:read-only="readOnly"
|
|
61
61
|
:on-update="(payload) => updateObject(docIndex, object.id, payload)"
|
|
62
62
|
:on-delete="() => deleteObject(docIndex, object.id)"
|
|
63
|
+
:on-duplicate="() => duplicateObject(docIndex, object.id)"
|
|
63
64
|
:on-drag-start="(mouseX, mouseY, pointerOffset, dragShift) => startDraggingElement(docIndex, pIndex, object, mouseX, mouseY, pointerOffset, dragShift)"
|
|
64
65
|
:on-drag-move="updateDraggingPosition"
|
|
65
66
|
:on-drag-end="stopDraggingElement"
|
|
@@ -71,6 +72,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
71
72
|
:global-drag-page-index="draggingPageIndex"
|
|
72
73
|
:show-selection-ui="showSelectionHandles && !hideSelectionUI && object.resizable !== false"
|
|
73
74
|
:show-default-actions="showElementActions && !hideSelectionUI"
|
|
75
|
+
:ignore-click-outside-selectors="ignoreClickOutsideSelectors"
|
|
74
76
|
>
|
|
75
77
|
<template #default="slotProps">
|
|
76
78
|
<slot
|
|
@@ -92,6 +94,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
92
94
|
name="actions"
|
|
93
95
|
:object="slotProps.object"
|
|
94
96
|
:onDelete="slotProps.onDelete"
|
|
97
|
+
:onDuplicate="slotProps.onDuplicate"
|
|
95
98
|
/>
|
|
96
99
|
</template>
|
|
97
100
|
</DraggableElement>
|
|
@@ -138,6 +141,11 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
138
141
|
import PDFPage from './PDFPage.vue'
|
|
139
142
|
import DraggableElement from './DraggableElement.vue'
|
|
140
143
|
import { readAsPDF, readAsArrayBuffer } from '../utils/asyncReader.js'
|
|
144
|
+
import { clampPosition, getVisibleArea } from '../utils/geometry.js'
|
|
145
|
+
import { getViewportWindow, isPageInViewport } from '../utils/pageBounds.js'
|
|
146
|
+
import { applyScaleToDocs } from '../utils/zoom.js'
|
|
147
|
+
import { objectIdExistsInDoc, findObjectPageIndex, updateObjectInDoc, removeObjectFromDoc } from '../utils/objectStore.js'
|
|
148
|
+
import { getCachedMeasurement } from '../utils/measurements.js'
|
|
141
149
|
|
|
142
150
|
export default {
|
|
143
151
|
name: 'PDFElements',
|
|
@@ -186,6 +194,10 @@ export default {
|
|
|
186
194
|
type: Boolean,
|
|
187
195
|
default: false,
|
|
188
196
|
},
|
|
197
|
+
ignoreClickOutsideSelectors: {
|
|
198
|
+
type: Array,
|
|
199
|
+
default: () => [],
|
|
200
|
+
},
|
|
189
201
|
pageCountFormat: {
|
|
190
202
|
type: String,
|
|
191
203
|
default: '{currentPage} of {totalPages}',
|
|
@@ -208,7 +220,16 @@ export default {
|
|
|
208
220
|
previewPageDocIndex: -1,
|
|
209
221
|
previewPageIndex: -1,
|
|
210
222
|
previewVisible: false,
|
|
211
|
-
|
|
223
|
+
hoverRafId: 0,
|
|
224
|
+
pendingHoverClientPos: null,
|
|
225
|
+
lastHoverRect: null,
|
|
226
|
+
addingListenersAttached: false,
|
|
227
|
+
dragRafId: 0,
|
|
228
|
+
pendingDragClientPos: null,
|
|
229
|
+
pageBoundsVersion: 0,
|
|
230
|
+
lastScrollTop: 0,
|
|
231
|
+
lastClientWidth: 0,
|
|
232
|
+
nextObjectCounter: 0,
|
|
212
233
|
isDraggingElement: false,
|
|
213
234
|
draggingObject: null,
|
|
214
235
|
draggingDocIndex: -1,
|
|
@@ -228,14 +249,16 @@ export default {
|
|
|
228
249
|
lastContainerWidth: 0,
|
|
229
250
|
}
|
|
230
251
|
},
|
|
252
|
+
created() {
|
|
253
|
+
this._pagesBoundingRects = {}
|
|
254
|
+
this._pagesBoundingRectsList = []
|
|
255
|
+
this._pageMeasurementCache = {}
|
|
256
|
+
this._lastPageBoundsScrollTop = 0
|
|
257
|
+
this._lastPageBoundsClientHeight = 0
|
|
258
|
+
},
|
|
231
259
|
mounted() {
|
|
232
260
|
this.boundHandleWheel = this.handleWheel.bind(this)
|
|
233
261
|
this.init()
|
|
234
|
-
document.addEventListener('mousemove', this.handleMouseMove)
|
|
235
|
-
document.addEventListener('touchmove', this.handleMouseMove, { passive: true })
|
|
236
|
-
document.addEventListener('mouseup', this.finishAdding)
|
|
237
|
-
document.addEventListener('touchend', this.finishAdding)
|
|
238
|
-
document.addEventListener('keydown', this.handleKeyDown)
|
|
239
262
|
window.addEventListener('scroll', this.onViewportScroll, { passive: true })
|
|
240
263
|
window.addEventListener('resize', this.onViewportScroll)
|
|
241
264
|
this.$el?.addEventListener('scroll', this.onViewportScroll, { passive: true })
|
|
@@ -252,11 +275,7 @@ export default {
|
|
|
252
275
|
if (this.boundHandleWheel) {
|
|
253
276
|
this.$el?.removeEventListener('wheel', this.boundHandleWheel)
|
|
254
277
|
}
|
|
255
|
-
|
|
256
|
-
document.removeEventListener('touchmove', this.handleMouseMove)
|
|
257
|
-
document.removeEventListener('mouseup', this.finishAdding)
|
|
258
|
-
document.removeEventListener('touchend', this.finishAdding)
|
|
259
|
-
document.removeEventListener('keydown', this.handleKeyDown)
|
|
278
|
+
this.detachAddingListeners()
|
|
260
279
|
window.removeEventListener('scroll', this.onViewportScroll)
|
|
261
280
|
window.removeEventListener('resize', this.onViewportScroll)
|
|
262
281
|
this.$el?.removeEventListener('scroll', this.onViewportScroll)
|
|
@@ -264,6 +283,14 @@ export default {
|
|
|
264
283
|
window.cancelAnimationFrame(this.viewportRafId)
|
|
265
284
|
this.viewportRafId = 0
|
|
266
285
|
}
|
|
286
|
+
if (this.hoverRafId) {
|
|
287
|
+
window.cancelAnimationFrame(this.hoverRafId)
|
|
288
|
+
this.hoverRafId = 0
|
|
289
|
+
}
|
|
290
|
+
if (this.dragRafId) {
|
|
291
|
+
window.cancelAnimationFrame(this.dragRafId)
|
|
292
|
+
this.dragRafId = 0
|
|
293
|
+
}
|
|
267
294
|
},
|
|
268
295
|
methods: {
|
|
269
296
|
async init() {
|
|
@@ -288,7 +315,7 @@ export default {
|
|
|
288
315
|
for (let p = 1; p <= pdfDoc.numPages; p++) {
|
|
289
316
|
const pagePromise = pdfDoc.getPage(p)
|
|
290
317
|
pagePromise.then((page) => {
|
|
291
|
-
pageWidths
|
|
318
|
+
pageWidths.splice(p - 1, 1, page.getViewport({ scale: 1 }).width)
|
|
292
319
|
if (this.autoFitZoom) {
|
|
293
320
|
this.scheduleAutoFitZoom()
|
|
294
321
|
}
|
|
@@ -309,6 +336,7 @@ export default {
|
|
|
309
336
|
}
|
|
310
337
|
|
|
311
338
|
this.pdfDocuments = docs
|
|
339
|
+
this._pageMeasurementCache = {}
|
|
312
340
|
if (docs.length) {
|
|
313
341
|
this.selectedDocIndex = 0
|
|
314
342
|
this.selectedPageIndex = 0
|
|
@@ -338,11 +366,8 @@ export default {
|
|
|
338
366
|
? dragShift
|
|
339
367
|
: { x: 0, y: 0 }
|
|
340
368
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
this.cachePageBounds()
|
|
344
|
-
}
|
|
345
|
-
const pageRect = this.pagesBoundingRects[pageKey]?.rect
|
|
369
|
+
this.cachePageBounds()
|
|
370
|
+
const pageRect = this.getPageRect(docIndex, pageIndex)
|
|
346
371
|
if (pointerOffset && typeof pointerOffset.x === 'number' && typeof pointerOffset.y === 'number') {
|
|
347
372
|
this.draggingInitialMouseOffset.x = pointerOffset.x
|
|
348
373
|
this.draggingInitialMouseOffset.y = pointerOffset.y
|
|
@@ -358,17 +383,22 @@ export default {
|
|
|
358
383
|
this.draggingClientPosition.y = mouseY - this.draggingInitialMouseOffset.y
|
|
359
384
|
}
|
|
360
385
|
|
|
361
|
-
this.cachePageBounds()
|
|
362
386
|
},
|
|
363
387
|
|
|
364
388
|
updateDraggingPosition(clientX, clientY) {
|
|
365
389
|
if (!this.isDraggingElement) return
|
|
366
390
|
|
|
367
|
-
this.
|
|
368
|
-
this.
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
391
|
+
this.pendingDragClientPos = { x: clientX, y: clientY }
|
|
392
|
+
if (this.dragRafId) return
|
|
393
|
+
this.dragRafId = window.requestAnimationFrame(() => {
|
|
394
|
+
this.dragRafId = 0
|
|
395
|
+
const pending = this.pendingDragClientPos
|
|
396
|
+
if (!pending) return
|
|
397
|
+
this.lastMouseClientPos.x = pending.x
|
|
398
|
+
this.lastMouseClientPos.y = pending.y
|
|
399
|
+
this.draggingClientPosition.x = pending.x - this.draggingInitialMouseOffset.x
|
|
400
|
+
this.draggingClientPosition.y = pending.y - this.draggingInitialMouseOffset.y
|
|
401
|
+
})
|
|
372
402
|
},
|
|
373
403
|
|
|
374
404
|
stopDraggingElement() {
|
|
@@ -400,10 +430,12 @@ export default {
|
|
|
400
430
|
this.draggingDocIndex = -1
|
|
401
431
|
this.draggingPageIndex = -1
|
|
402
432
|
this.draggingElementShift = { x: 0, y: 0 }
|
|
433
|
+
this.pendingDragClientPos = null
|
|
403
434
|
},
|
|
404
435
|
|
|
405
436
|
startAddingElement(templateObject) {
|
|
406
437
|
if (!this.pdfDocuments.length) return
|
|
438
|
+
this.attachAddingListeners()
|
|
407
439
|
this.isAddingMode = true
|
|
408
440
|
this.previewElement = { ...templateObject }
|
|
409
441
|
this.previewPageDocIndex = 0
|
|
@@ -415,10 +447,29 @@ export default {
|
|
|
415
447
|
|
|
416
448
|
cachePageBounds() {
|
|
417
449
|
const nextRects = {}
|
|
450
|
+
const container = this.$el
|
|
451
|
+
const scrollTop = container?.scrollTop || 0
|
|
452
|
+
const viewHeight = container?.clientHeight || 0
|
|
453
|
+
if (!this.isAddingMode && !this.isDraggingElement &&
|
|
454
|
+
scrollTop === this._lastPageBoundsScrollTop &&
|
|
455
|
+
viewHeight === this._lastPageBoundsClientHeight) {
|
|
456
|
+
return
|
|
457
|
+
}
|
|
458
|
+
this._lastPageBoundsScrollTop = scrollTop
|
|
459
|
+
this._lastPageBoundsClientHeight = viewHeight
|
|
460
|
+
const { minY, maxY } = getViewportWindow(scrollTop, viewHeight)
|
|
418
461
|
for (let docIdx = 0; docIdx < this.pdfDocuments.length; docIdx++) {
|
|
419
462
|
for (let pageIdx = 0; pageIdx < this.pdfDocuments[docIdx].pages.length; pageIdx++) {
|
|
420
463
|
const canvas = this.getPageCanvasElement(docIdx, pageIdx)
|
|
421
464
|
if (!canvas) continue
|
|
465
|
+
if (viewHeight) {
|
|
466
|
+
const wrapper = canvas.closest('.page-wrapper') || canvas
|
|
467
|
+
const offsetTop = wrapper.offsetTop || 0
|
|
468
|
+
const offsetHeight = wrapper.offsetHeight || 0
|
|
469
|
+
if (!isPageInViewport(offsetTop, offsetHeight, minY, maxY)) {
|
|
470
|
+
continue
|
|
471
|
+
}
|
|
472
|
+
}
|
|
422
473
|
const rect = canvas.getBoundingClientRect()
|
|
423
474
|
nextRects[`${docIdx}-${pageIdx}`] = {
|
|
424
475
|
docIndex: docIdx,
|
|
@@ -427,31 +478,71 @@ export default {
|
|
|
427
478
|
}
|
|
428
479
|
}
|
|
429
480
|
}
|
|
430
|
-
this.
|
|
481
|
+
this._pagesBoundingRects = nextRects
|
|
482
|
+
this._pagesBoundingRectsList = Object.values(nextRects)
|
|
483
|
+
this.pageBoundsVersion++
|
|
484
|
+
},
|
|
485
|
+
cachePageBoundsForPage(docIndex, pageIndex) {
|
|
486
|
+
const canvas = this.getPageCanvasElement(docIndex, pageIndex)
|
|
487
|
+
if (!canvas) return
|
|
488
|
+
const rect = canvas.getBoundingClientRect()
|
|
489
|
+
this._pagesBoundingRects = {
|
|
490
|
+
...this._pagesBoundingRects,
|
|
491
|
+
[`${docIndex}-${pageIndex}`]: {
|
|
492
|
+
docIndex,
|
|
493
|
+
pageIndex,
|
|
494
|
+
rect,
|
|
495
|
+
},
|
|
496
|
+
}
|
|
497
|
+
this._pagesBoundingRectsList = Object.values(this._pagesBoundingRects)
|
|
498
|
+
this.pageBoundsVersion++
|
|
499
|
+
},
|
|
500
|
+
getPageBoundsMap() {
|
|
501
|
+
return this._pagesBoundingRects || {}
|
|
502
|
+
},
|
|
503
|
+
getPageBoundsList() {
|
|
504
|
+
return this._pagesBoundingRectsList || []
|
|
505
|
+
},
|
|
506
|
+
getPageRect(docIndex, pageIndex) {
|
|
507
|
+
return this.getPageBoundsMap()[`${docIndex}-${pageIndex}`]?.rect || null
|
|
508
|
+
},
|
|
509
|
+
getPointerPosition(event) {
|
|
510
|
+
if (event?.type?.includes?.('touch')) {
|
|
511
|
+
return {
|
|
512
|
+
x: event.touches?.[0]?.clientX,
|
|
513
|
+
y: event.touches?.[0]?.clientY,
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return {
|
|
517
|
+
x: event?.clientX,
|
|
518
|
+
y: event?.clientY,
|
|
519
|
+
}
|
|
431
520
|
},
|
|
432
521
|
|
|
433
522
|
getDisplayedPageScale(docIndex, pageIndex) {
|
|
523
|
+
this.pageBoundsVersion
|
|
434
524
|
const doc = this.pdfDocuments[docIndex]
|
|
435
525
|
if (!doc) return 1
|
|
436
526
|
const baseWidth = doc.pageWidths?.[pageIndex] || 0
|
|
437
|
-
const
|
|
527
|
+
const pageBoundsMap = this.getPageBoundsMap()
|
|
528
|
+
if (!pageBoundsMap[`${docIndex}-${pageIndex}`]) {
|
|
529
|
+
this.cachePageBoundsForPage(docIndex, pageIndex)
|
|
530
|
+
}
|
|
531
|
+
const rectWidth = this.getPageBoundsMap()[`${docIndex}-${pageIndex}`]?.rect?.width || 0
|
|
438
532
|
if (rectWidth && baseWidth) {
|
|
439
533
|
return rectWidth / baseWidth
|
|
440
534
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
535
|
+
if (this.isAddingMode || this.isDraggingElement) {
|
|
536
|
+
const canvas = this.getPageCanvasElement(docIndex, pageIndex)
|
|
537
|
+
const fallbackRectWidth = canvas?.getBoundingClientRect?.().width || 0
|
|
538
|
+
if (fallbackRectWidth && baseWidth) {
|
|
539
|
+
return fallbackRectWidth / baseWidth
|
|
540
|
+
}
|
|
445
541
|
}
|
|
446
542
|
const base = doc.pagesScale[pageIndex] || 1
|
|
447
543
|
const factor = this.visualScale && this.scale ? (this.visualScale / this.scale) : 1
|
|
448
544
|
return base * factor
|
|
449
545
|
},
|
|
450
|
-
getRenderPageScale(docIndex, pageIndex) {
|
|
451
|
-
const doc = this.pdfDocuments[docIndex]
|
|
452
|
-
if (!doc) return 1
|
|
453
|
-
return doc.pagesScale[pageIndex] || 1
|
|
454
|
-
},
|
|
455
546
|
getPageComponent(docIndex, pageIndex) {
|
|
456
547
|
const pageRef = this.$refs[`page${docIndex}-${pageIndex}`]
|
|
457
548
|
return pageRef && Array.isArray(pageRef) && pageRef[0] ? pageRef[0] : null
|
|
@@ -464,13 +555,22 @@ export default {
|
|
|
464
555
|
onViewportScroll() {
|
|
465
556
|
if (this.viewportRafId) return
|
|
466
557
|
this.viewportRafId = window.requestAnimationFrame(() => {
|
|
558
|
+
const container = this.$el
|
|
559
|
+
const scrollTop = container?.scrollTop || 0
|
|
560
|
+
const clientWidth = container?.clientWidth || 0
|
|
561
|
+
const scrollChanged = scrollTop !== this.lastScrollTop
|
|
562
|
+
const widthChanged = clientWidth !== this.lastClientWidth
|
|
563
|
+
this.lastScrollTop = scrollTop
|
|
564
|
+
this.lastClientWidth = clientWidth
|
|
565
|
+
|
|
467
566
|
if (this.isAddingMode || this.isDraggingElement) {
|
|
468
|
-
|
|
567
|
+
if (scrollChanged || widthChanged) {
|
|
568
|
+
this.cachePageBounds()
|
|
569
|
+
}
|
|
469
570
|
}
|
|
470
571
|
if (this.autoFitZoom && !this.isAddingMode && !this.isDraggingElement) {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
this.lastContainerWidth = containerWidth
|
|
572
|
+
if (clientWidth && widthChanged) {
|
|
573
|
+
this.lastContainerWidth = clientWidth
|
|
474
574
|
this.autoFitApplied = false
|
|
475
575
|
this.scheduleAutoFitZoom()
|
|
476
576
|
}
|
|
@@ -481,49 +581,75 @@ export default {
|
|
|
481
581
|
|
|
482
582
|
handleMouseMove(event) {
|
|
483
583
|
if (!this.isAddingMode || !this.previewElement) return
|
|
584
|
+
const { x, y } = this.getPointerPosition(event)
|
|
585
|
+
if (x === undefined || y === undefined) return
|
|
586
|
+
this.pendingHoverClientPos = { x, y }
|
|
587
|
+
if (this.hoverRafId) return
|
|
588
|
+
this.hoverRafId = window.requestAnimationFrame(() => {
|
|
589
|
+
this.hoverRafId = 0
|
|
590
|
+
const pending = this.pendingHoverClientPos
|
|
591
|
+
if (!pending) return
|
|
592
|
+
|
|
593
|
+
const cursorX = pending.x
|
|
594
|
+
const cursorY = pending.y
|
|
595
|
+
let target = null
|
|
596
|
+
|
|
597
|
+
if (this.lastHoverRect &&
|
|
598
|
+
cursorX >= this.lastHoverRect.left && cursorX <= this.lastHoverRect.right &&
|
|
599
|
+
cursorY >= this.lastHoverRect.top && cursorY <= this.lastHoverRect.bottom) {
|
|
600
|
+
target = {
|
|
601
|
+
docIndex: this.previewPageDocIndex,
|
|
602
|
+
pageIndex: this.previewPageIndex,
|
|
603
|
+
rect: this.lastHoverRect,
|
|
604
|
+
}
|
|
605
|
+
} else {
|
|
606
|
+
const rects = this.getPageBoundsList().length
|
|
607
|
+
? this.getPageBoundsList()
|
|
608
|
+
: Object.values(this.getPageBoundsMap())
|
|
609
|
+
for (let i = 0; i < rects.length; i++) {
|
|
610
|
+
const entry = rects[i]
|
|
611
|
+
const rect = entry.rect
|
|
612
|
+
if (cursorX >= rect.left && cursorX <= rect.right &&
|
|
613
|
+
cursorY >= rect.top && cursorY <= rect.bottom) {
|
|
614
|
+
target = entry
|
|
615
|
+
break
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
484
619
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
const { docIndex, pageIndex, rect } = this.pagesBoundingRects[key]
|
|
491
|
-
if (clientX >= rect.left && clientX <= rect.right &&
|
|
492
|
-
clientY >= rect.top && clientY <= rect.bottom) {
|
|
493
|
-
this.previewPageDocIndex = docIndex
|
|
494
|
-
this.previewPageIndex = pageIndex
|
|
495
|
-
foundPage = true
|
|
496
|
-
|
|
497
|
-
const canvasEl = this.getPageCanvasElement(docIndex, pageIndex)
|
|
498
|
-
const pagesScale = this.pdfDocuments[docIndex]?.pagesScale?.[pageIndex] || 1
|
|
499
|
-
const renderWidth = canvasEl?.width || rect.width
|
|
500
|
-
const renderHeight = canvasEl?.height || rect.height
|
|
501
|
-
const layoutScaleX = renderWidth ? rect.width / renderWidth : 1
|
|
502
|
-
const layoutScaleY = renderHeight ? rect.height / renderHeight : 1
|
|
503
|
-
const relX = (clientX - rect.left) / layoutScaleX / pagesScale
|
|
504
|
-
const relY = (clientY - rect.top) / layoutScaleY / pagesScale
|
|
505
|
-
|
|
506
|
-
const pageWidth = renderWidth / pagesScale
|
|
507
|
-
const pageHeight = renderHeight / pagesScale
|
|
508
|
-
this.previewScale.x = pagesScale
|
|
509
|
-
this.previewScale.y = pagesScale
|
|
510
|
-
let x = relX - this.previewElement.width / 2
|
|
511
|
-
let y = relY - this.previewElement.height / 2
|
|
512
|
-
|
|
513
|
-
x = Math.max(0, Math.min(x, pageWidth - this.previewElement.width))
|
|
514
|
-
y = Math.max(0, Math.min(y, pageHeight - this.previewElement.height))
|
|
515
|
-
|
|
516
|
-
this.previewPosition.x = x
|
|
517
|
-
this.previewPosition.y = y
|
|
518
|
-
this.previewVisible = true
|
|
519
|
-
break
|
|
620
|
+
if (!target) {
|
|
621
|
+
this.previewVisible = false
|
|
622
|
+
this.previewScale = { x: 1, y: 1 }
|
|
623
|
+
this.lastHoverRect = null
|
|
624
|
+
return
|
|
520
625
|
}
|
|
521
|
-
}
|
|
522
626
|
|
|
523
|
-
|
|
524
|
-
this.
|
|
525
|
-
this.
|
|
526
|
-
|
|
627
|
+
this.previewPageDocIndex = target.docIndex
|
|
628
|
+
this.previewPageIndex = target.pageIndex
|
|
629
|
+
this.lastHoverRect = target.rect
|
|
630
|
+
const canvasEl = this.getPageCanvasElement(target.docIndex, target.pageIndex)
|
|
631
|
+
const pagesScale = this.pdfDocuments[target.docIndex]?.pagesScale?.[target.pageIndex] || 1
|
|
632
|
+
const renderWidth = canvasEl?.width || target.rect.width
|
|
633
|
+
const renderHeight = canvasEl?.height || target.rect.height
|
|
634
|
+
const layoutScaleX = renderWidth ? target.rect.width / renderWidth : 1
|
|
635
|
+
const layoutScaleY = renderHeight ? target.rect.height / renderHeight : 1
|
|
636
|
+
const relX = (cursorX - target.rect.left) / layoutScaleX / pagesScale
|
|
637
|
+
const relY = (cursorY - target.rect.top) / layoutScaleY / pagesScale
|
|
638
|
+
|
|
639
|
+
const pageWidth = renderWidth / pagesScale
|
|
640
|
+
const pageHeight = renderHeight / pagesScale
|
|
641
|
+
this.previewScale.x = pagesScale
|
|
642
|
+
this.previewScale.y = pagesScale
|
|
643
|
+
let x = relX - this.previewElement.width / 2
|
|
644
|
+
let y = relY - this.previewElement.height / 2
|
|
645
|
+
|
|
646
|
+
x = Math.max(0, Math.min(x, pageWidth - this.previewElement.width))
|
|
647
|
+
y = Math.max(0, Math.min(y, pageHeight - this.previewElement.height))
|
|
648
|
+
|
|
649
|
+
this.previewPosition.x = x
|
|
650
|
+
this.previewPosition.y = y
|
|
651
|
+
this.previewVisible = true
|
|
652
|
+
})
|
|
527
653
|
},
|
|
528
654
|
|
|
529
655
|
handleKeyDown(event) {
|
|
@@ -551,10 +677,9 @@ export default {
|
|
|
551
677
|
|
|
552
678
|
this.scale = newScale
|
|
553
679
|
|
|
554
|
-
this.pdfDocuments.
|
|
555
|
-
doc.pagesScale = doc.pagesScale.map(() => this.scale)
|
|
556
|
-
})
|
|
680
|
+
applyScaleToDocs(this.pdfDocuments, this.scale)
|
|
557
681
|
|
|
682
|
+
this._pageMeasurementCache = {}
|
|
558
683
|
this.cachePageBounds()
|
|
559
684
|
},
|
|
560
685
|
|
|
@@ -564,7 +689,7 @@ export default {
|
|
|
564
689
|
|
|
565
690
|
const objectToAdd = {
|
|
566
691
|
...this.previewElement,
|
|
567
|
-
id:
|
|
692
|
+
id: this.generateObjectId(),
|
|
568
693
|
x: Math.round(this.previewPosition.x),
|
|
569
694
|
y: Math.round(this.previewPosition.y),
|
|
570
695
|
}
|
|
@@ -601,6 +726,30 @@ export default {
|
|
|
601
726
|
this.isAddingMode = false
|
|
602
727
|
this.previewElement = null
|
|
603
728
|
this.previewVisible = false
|
|
729
|
+
this.detachAddingListeners()
|
|
730
|
+
},
|
|
731
|
+
generateObjectId() {
|
|
732
|
+
const counter = this.nextObjectCounter++
|
|
733
|
+
const rand = Math.random().toString(36).slice(2, 8)
|
|
734
|
+
return `obj-${Date.now()}-${counter}-${rand}`
|
|
735
|
+
},
|
|
736
|
+
attachAddingListeners() {
|
|
737
|
+
if (this.addingListenersAttached) return
|
|
738
|
+
this.addingListenersAttached = true
|
|
739
|
+
document.addEventListener('mousemove', this.handleMouseMove)
|
|
740
|
+
document.addEventListener('touchmove', this.handleMouseMove, { passive: true })
|
|
741
|
+
document.addEventListener('mouseup', this.finishAdding)
|
|
742
|
+
document.addEventListener('touchend', this.finishAdding)
|
|
743
|
+
document.addEventListener('keydown', this.handleKeyDown)
|
|
744
|
+
},
|
|
745
|
+
detachAddingListeners() {
|
|
746
|
+
if (!this.addingListenersAttached) return
|
|
747
|
+
this.addingListenersAttached = false
|
|
748
|
+
document.removeEventListener('mousemove', this.handleMouseMove)
|
|
749
|
+
document.removeEventListener('touchmove', this.handleMouseMove, { passive: true })
|
|
750
|
+
document.removeEventListener('mouseup', this.finishAdding)
|
|
751
|
+
document.removeEventListener('touchend', this.finishAdding)
|
|
752
|
+
document.removeEventListener('keydown', this.handleKeyDown)
|
|
604
753
|
},
|
|
605
754
|
|
|
606
755
|
addObjectToPage(object, pageIndex = this.selectedPageIndex, docIndex = this.selectedDocIndex) {
|
|
@@ -611,20 +760,39 @@ export default {
|
|
|
611
760
|
const pageRef = this.getPageComponent(docIndex, pageIndex)
|
|
612
761
|
if (!pageRef) return false
|
|
613
762
|
|
|
763
|
+
let objectToAdd = object
|
|
764
|
+
if (!objectToAdd.id || this.objectIdExists(docIndex, objectToAdd.id)) {
|
|
765
|
+
objectToAdd = { ...objectToAdd, id: this.generateObjectId() }
|
|
766
|
+
}
|
|
767
|
+
|
|
614
768
|
const pageWidth = this.getPageWidth(docIndex, pageIndex)
|
|
615
769
|
const pageHeight = this.getPageHeight(docIndex, pageIndex)
|
|
616
770
|
|
|
617
|
-
if (
|
|
618
|
-
|
|
619
|
-
|
|
771
|
+
if (objectToAdd.x < 0 || objectToAdd.y < 0 ||
|
|
772
|
+
objectToAdd.x + objectToAdd.width > pageWidth ||
|
|
773
|
+
objectToAdd.y + objectToAdd.height > pageHeight) {
|
|
620
774
|
return false
|
|
621
775
|
}
|
|
622
776
|
|
|
623
|
-
doc.allObjects
|
|
624
|
-
|
|
625
|
-
)
|
|
777
|
+
doc.allObjects[pageIndex].push(objectToAdd)
|
|
778
|
+
this.objectIndexCache[`${docIndex}-${objectToAdd.id}`] = pageIndex
|
|
626
779
|
return true
|
|
627
780
|
},
|
|
781
|
+
objectIdExists(docIndex, objectId) {
|
|
782
|
+
if (!objectId) return false
|
|
783
|
+
const cacheKey = `${docIndex}-${objectId}`
|
|
784
|
+
if (this.objectIndexCache[cacheKey] !== undefined) return true
|
|
785
|
+
const doc = this.pdfDocuments[docIndex]
|
|
786
|
+
return objectIdExistsInDoc(doc, objectId)
|
|
787
|
+
},
|
|
788
|
+
updateObjectInPage(docIndex, pageIndex, objectId, payload) {
|
|
789
|
+
const doc = this.pdfDocuments[docIndex]
|
|
790
|
+
updateObjectInDoc(doc, pageIndex, objectId, payload)
|
|
791
|
+
},
|
|
792
|
+
removeObjectFromPage(docIndex, pageIndex, objectId) {
|
|
793
|
+
const doc = this.pdfDocuments[docIndex]
|
|
794
|
+
removeObjectFromDoc(doc, pageIndex, objectId)
|
|
795
|
+
},
|
|
628
796
|
|
|
629
797
|
getAllObjects(docIndex = this.selectedDocIndex) {
|
|
630
798
|
if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return []
|
|
@@ -635,9 +803,9 @@ export default {
|
|
|
635
803
|
doc.allObjects.forEach((pageObjects, pageIndex) => {
|
|
636
804
|
const pageRef = this.getPageComponent(docIndex, pageIndex)
|
|
637
805
|
if (!pageRef) return
|
|
638
|
-
const measurement =
|
|
806
|
+
const measurement = this.getCachedMeasurement(docIndex, pageIndex, pageRef)
|
|
807
|
+
const normalizedCanvasHeight = measurement.height
|
|
639
808
|
const pagesScale = doc.pagesScale[pageIndex] || 1
|
|
640
|
-
const normalizedCanvasHeight = measurement.canvasHeight / pagesScale
|
|
641
809
|
|
|
642
810
|
pageObjects.forEach(object => {
|
|
643
811
|
result.push({
|
|
@@ -667,12 +835,10 @@ export default {
|
|
|
667
835
|
let currentPageIndex = this.objectIndexCache[cacheKey]
|
|
668
836
|
|
|
669
837
|
if (currentPageIndex === undefined) {
|
|
670
|
-
doc
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
675
|
-
})
|
|
838
|
+
currentPageIndex = findObjectPageIndex(doc, objectId)
|
|
839
|
+
if (currentPageIndex !== undefined) {
|
|
840
|
+
this.objectIndexCache[cacheKey] = currentPageIndex
|
|
841
|
+
}
|
|
676
842
|
}
|
|
677
843
|
|
|
678
844
|
if (currentPageIndex === undefined) return
|
|
@@ -684,19 +850,18 @@ export default {
|
|
|
684
850
|
const mouseX = payload._mouseX
|
|
685
851
|
const mouseY = payload._mouseY
|
|
686
852
|
|
|
687
|
-
|
|
853
|
+
const pageBoundsMap = this.getPageBoundsMap()
|
|
854
|
+
if (!pageBoundsMap || Object.keys(pageBoundsMap).length === 0) {
|
|
688
855
|
this.cachePageBounds()
|
|
689
856
|
}
|
|
690
857
|
|
|
691
|
-
const currentPageRect = this.
|
|
858
|
+
const currentPageRect = this.getPageRect(docIndex, currentPageIndex)
|
|
692
859
|
if (currentPageRect) {
|
|
693
860
|
const pagesScale = this.getDisplayedPageScale(docIndex, currentPageIndex)
|
|
694
861
|
const relX = (mouseX - currentPageRect.left - this.draggingElementShift.x) / pagesScale - (this.draggingInitialMouseOffset.x / pagesScale)
|
|
695
862
|
const relY = (mouseY - currentPageRect.top - this.draggingElementShift.y) / pagesScale - (this.draggingInitialMouseOffset.y / pagesScale)
|
|
696
863
|
|
|
697
|
-
|
|
698
|
-
obj.id === objectId ? { ...obj, x: relX, y: relY } : obj
|
|
699
|
-
)
|
|
864
|
+
this.updateObjectInPage(docIndex, currentPageIndex, objectId, { x: relX, y: relY })
|
|
700
865
|
}
|
|
701
866
|
return
|
|
702
867
|
}
|
|
@@ -707,6 +872,14 @@ export default {
|
|
|
707
872
|
const objWidth = payload.width !== undefined ? payload.width : targetObject.width
|
|
708
873
|
const objHeight = payload.height !== undefined ? payload.height : targetObject.height
|
|
709
874
|
|
|
875
|
+
const { width: currentPageWidth, height: currentPageHeight } = this.getPageSize(docIndex, currentPageIndex)
|
|
876
|
+
if (newX >= 0 && newY >= 0 &&
|
|
877
|
+
newX + objWidth <= currentPageWidth &&
|
|
878
|
+
newY + objHeight <= currentPageHeight) {
|
|
879
|
+
this.updateObjectInPage(docIndex, currentPageIndex, objectId, payload)
|
|
880
|
+
return
|
|
881
|
+
}
|
|
882
|
+
|
|
710
883
|
let bestPageIndex = currentPageIndex
|
|
711
884
|
let maxVisibleArea = 0
|
|
712
885
|
|
|
@@ -714,30 +887,18 @@ export default {
|
|
|
714
887
|
const pageWidth = this.getPageWidth(docIndex, pIndex)
|
|
715
888
|
const pageHeight = this.getPageHeight(docIndex, pIndex)
|
|
716
889
|
|
|
717
|
-
const
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if (visibleRight > visibleLeft && visibleBottom > visibleTop) {
|
|
723
|
-
const visibleArea = (visibleRight - visibleLeft) * (visibleBottom - visibleTop)
|
|
724
|
-
if (visibleArea > maxVisibleArea) {
|
|
725
|
-
maxVisibleArea = visibleArea
|
|
726
|
-
bestPageIndex = pIndex
|
|
727
|
-
}
|
|
890
|
+
const visibleArea = getVisibleArea(newX, newY, objWidth, objHeight, pageWidth, pageHeight)
|
|
891
|
+
if (visibleArea > maxVisibleArea) {
|
|
892
|
+
maxVisibleArea = visibleArea
|
|
893
|
+
bestPageIndex = pIndex
|
|
728
894
|
}
|
|
729
895
|
}
|
|
730
896
|
|
|
731
897
|
if (bestPageIndex !== currentPageIndex) {
|
|
732
|
-
const pageWidth = this.
|
|
733
|
-
const
|
|
734
|
-
|
|
735
|
-
const adjustedX = Math.max(0, Math.min(newX, pageWidth - objWidth))
|
|
736
|
-
const adjustedY = Math.max(0, Math.min(newY, pageHeight - objHeight))
|
|
898
|
+
const { width: pageWidth, height: pageHeight } = this.getPageSize(docIndex, bestPageIndex)
|
|
899
|
+
const { x: adjustedX, y: adjustedY } = clampPosition(newX, newY, objWidth, objHeight, pageWidth, pageHeight)
|
|
737
900
|
|
|
738
|
-
|
|
739
|
-
obj => obj.id !== objectId
|
|
740
|
-
)
|
|
901
|
+
this.removeObjectFromPage(docIndex, currentPageIndex, objectId)
|
|
741
902
|
const updatedObject = {
|
|
742
903
|
...targetObject,
|
|
743
904
|
...payload,
|
|
@@ -749,8 +910,7 @@ export default {
|
|
|
749
910
|
return
|
|
750
911
|
}
|
|
751
912
|
|
|
752
|
-
const pageWidth = this.
|
|
753
|
-
const pageHeight = this.getPageHeight(docIndex, currentPageIndex)
|
|
913
|
+
const { width: pageWidth, height: pageHeight } = this.getPageSize(docIndex, currentPageIndex)
|
|
754
914
|
|
|
755
915
|
if (newX < 0 || newY < 0 ||
|
|
756
916
|
newX + objWidth > pageWidth ||
|
|
@@ -759,9 +919,7 @@ export default {
|
|
|
759
919
|
}
|
|
760
920
|
}
|
|
761
921
|
|
|
762
|
-
|
|
763
|
-
objects.map(object => (object.id === objectId ? { ...object, ...payload } : object)),
|
|
764
|
-
)
|
|
922
|
+
this.updateObjectInPage(docIndex, currentPageIndex, objectId, payload)
|
|
765
923
|
},
|
|
766
924
|
|
|
767
925
|
deleteObject(docIndex, objectId) {
|
|
@@ -770,16 +928,16 @@ export default {
|
|
|
770
928
|
let deletedObject = null
|
|
771
929
|
let deletedPageIndex = -1
|
|
772
930
|
|
|
773
|
-
doc.allObjects
|
|
774
|
-
objects.
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
)
|
|
931
|
+
doc.allObjects.some((objects, pageIndex) => {
|
|
932
|
+
const objectIndex = objects.findIndex(object => object.id === objectId)
|
|
933
|
+
if (objectIndex === -1) {
|
|
934
|
+
return false
|
|
935
|
+
}
|
|
936
|
+
deletedObject = objects[objectIndex]
|
|
937
|
+
deletedPageIndex = pageIndex
|
|
938
|
+
objects.splice(objectIndex, 1)
|
|
939
|
+
return true
|
|
940
|
+
})
|
|
783
941
|
delete this.objectIndexCache[`${docIndex}-${objectId}`]
|
|
784
942
|
if (deletedObject) {
|
|
785
943
|
this.$emit('pdf-elements:delete-object', {
|
|
@@ -789,6 +947,64 @@ export default {
|
|
|
789
947
|
})
|
|
790
948
|
}
|
|
791
949
|
},
|
|
950
|
+
duplicateObject(docIndex, objectId) {
|
|
951
|
+
if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return
|
|
952
|
+
const doc = this.pdfDocuments[docIndex]
|
|
953
|
+
|
|
954
|
+
const cacheKey = `${docIndex}-${objectId}`
|
|
955
|
+
let pageIndex = this.objectIndexCache[cacheKey]
|
|
956
|
+
|
|
957
|
+
if (pageIndex === undefined) {
|
|
958
|
+
pageIndex = findObjectPageIndex(doc, objectId)
|
|
959
|
+
if (pageIndex !== undefined) {
|
|
960
|
+
this.objectIndexCache[cacheKey] = pageIndex
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
if (pageIndex === undefined) return
|
|
965
|
+
|
|
966
|
+
const sourceObject = doc.allObjects[pageIndex]?.find(o => o.id === objectId)
|
|
967
|
+
if (!sourceObject) return
|
|
968
|
+
|
|
969
|
+
const { width: pageWidth, height: pageHeight } = this.getPageSize(docIndex, pageIndex)
|
|
970
|
+
const offset = 12
|
|
971
|
+
const { x, y } = clampPosition(
|
|
972
|
+
sourceObject.x + offset,
|
|
973
|
+
sourceObject.y + offset,
|
|
974
|
+
sourceObject.width,
|
|
975
|
+
sourceObject.height,
|
|
976
|
+
pageWidth,
|
|
977
|
+
pageHeight,
|
|
978
|
+
)
|
|
979
|
+
|
|
980
|
+
let duplicatedSigner = sourceObject.signer
|
|
981
|
+
if (duplicatedSigner?.element && Object.prototype.hasOwnProperty.call(duplicatedSigner.element, 'elementId')) {
|
|
982
|
+
duplicatedSigner = {
|
|
983
|
+
...duplicatedSigner,
|
|
984
|
+
element: { ...duplicatedSigner.element },
|
|
985
|
+
}
|
|
986
|
+
delete duplicatedSigner.element.elementId
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
const duplicatedObject = {
|
|
990
|
+
...sourceObject,
|
|
991
|
+
id: this.generateObjectId(),
|
|
992
|
+
x,
|
|
993
|
+
y,
|
|
994
|
+
signer: duplicatedSigner,
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
doc.allObjects[pageIndex].push(duplicatedObject)
|
|
998
|
+
this.objectIndexCache[`${docIndex}-${duplicatedObject.id}`] = pageIndex
|
|
999
|
+
|
|
1000
|
+
this.$nextTick(() => {
|
|
1001
|
+
const refKey = `draggable${docIndex}-${pageIndex}-${duplicatedObject.id}`
|
|
1002
|
+
const draggableRefs = this.$refs[refKey]
|
|
1003
|
+
if (draggableRefs && Array.isArray(draggableRefs) && draggableRefs[0]) {
|
|
1004
|
+
draggableRefs[0].isSelected = true
|
|
1005
|
+
}
|
|
1006
|
+
})
|
|
1007
|
+
},
|
|
792
1008
|
|
|
793
1009
|
checkAndMoveObjectPage(docIndex, objectId, mouseX, mouseY) {
|
|
794
1010
|
if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return undefined
|
|
@@ -798,12 +1014,10 @@ export default {
|
|
|
798
1014
|
let currentPageIndex = this.objectIndexCache[cacheKey]
|
|
799
1015
|
|
|
800
1016
|
if (currentPageIndex === undefined) {
|
|
801
|
-
doc
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
}
|
|
806
|
-
})
|
|
1017
|
+
currentPageIndex = findObjectPageIndex(doc, objectId)
|
|
1018
|
+
if (currentPageIndex !== undefined) {
|
|
1019
|
+
this.objectIndexCache[cacheKey] = currentPageIndex
|
|
1020
|
+
}
|
|
807
1021
|
}
|
|
808
1022
|
|
|
809
1023
|
if (currentPageIndex === undefined) return undefined
|
|
@@ -812,8 +1026,9 @@ export default {
|
|
|
812
1026
|
if (!targetObject) return currentPageIndex
|
|
813
1027
|
|
|
814
1028
|
let targetPageIndex = currentPageIndex
|
|
815
|
-
|
|
816
|
-
|
|
1029
|
+
const pageBoundsMap = this.getPageBoundsMap()
|
|
1030
|
+
for (const key in pageBoundsMap) {
|
|
1031
|
+
const { docIndex: rectDocIndex, pageIndex, rect } = pageBoundsMap[key]
|
|
817
1032
|
if (rectDocIndex === docIndex &&
|
|
818
1033
|
mouseX >= rect.left && mouseX <= rect.right &&
|
|
819
1034
|
mouseY >= rect.top && mouseY <= rect.bottom) {
|
|
@@ -822,23 +1037,25 @@ export default {
|
|
|
822
1037
|
}
|
|
823
1038
|
}
|
|
824
1039
|
|
|
825
|
-
const targetPageRect = this.
|
|
1040
|
+
const targetPageRect = this.getPageRect(docIndex, targetPageIndex)
|
|
826
1041
|
if (!targetPageRect) return currentPageIndex
|
|
827
1042
|
|
|
828
1043
|
const pagesScale = this.getDisplayedPageScale(docIndex, targetPageIndex)
|
|
829
1044
|
const relX = (mouseX - targetPageRect.left - this.draggingElementShift.x) / pagesScale - (this.draggingInitialMouseOffset.x / pagesScale)
|
|
830
1045
|
const relY = (mouseY - targetPageRect.top - this.draggingElementShift.y) / pagesScale - (this.draggingInitialMouseOffset.y / pagesScale)
|
|
831
1046
|
|
|
832
|
-
const pageWidth = this.
|
|
833
|
-
const
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1047
|
+
const { width: pageWidth, height: pageHeight } = this.getPageSize(docIndex, targetPageIndex)
|
|
1048
|
+
const { x: clampedX, y: clampedY } = clampPosition(
|
|
1049
|
+
relX,
|
|
1050
|
+
relY,
|
|
1051
|
+
targetObject.width,
|
|
1052
|
+
targetObject.height,
|
|
1053
|
+
pageWidth,
|
|
1054
|
+
pageHeight,
|
|
1055
|
+
)
|
|
837
1056
|
|
|
838
1057
|
if (targetPageIndex !== currentPageIndex) {
|
|
839
|
-
|
|
840
|
-
obj => obj.id !== objectId
|
|
841
|
-
)
|
|
1058
|
+
this.removeObjectFromPage(docIndex, currentPageIndex, objectId)
|
|
842
1059
|
doc.allObjects[targetPageIndex].push({
|
|
843
1060
|
...targetObject,
|
|
844
1061
|
x: clampedX,
|
|
@@ -846,9 +1063,7 @@ export default {
|
|
|
846
1063
|
})
|
|
847
1064
|
this.objectIndexCache[cacheKey] = targetPageIndex
|
|
848
1065
|
} else if (clampedX !== targetObject.x || clampedY !== targetObject.y) {
|
|
849
|
-
|
|
850
|
-
obj.id === objectId ? { ...obj, x: clampedX, y: clampedY } : obj
|
|
851
|
-
)
|
|
1066
|
+
this.updateObjectInPage(docIndex, currentPageIndex, objectId, { x: clampedX, y: clampedY })
|
|
852
1067
|
}
|
|
853
1068
|
|
|
854
1069
|
return targetPageIndex
|
|
@@ -856,8 +1071,9 @@ export default {
|
|
|
856
1071
|
|
|
857
1072
|
onMeasure(e, docIndex, pageIndex) {
|
|
858
1073
|
if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return
|
|
859
|
-
this.pdfDocuments[docIndex].pagesScale
|
|
860
|
-
this.
|
|
1074
|
+
this.pdfDocuments[docIndex].pagesScale.splice(pageIndex, 1, e.scale)
|
|
1075
|
+
this._pageMeasurementCache[`${docIndex}-${pageIndex}`] = null
|
|
1076
|
+
this.cachePageBoundsForPage(docIndex, pageIndex)
|
|
861
1077
|
if (this.autoFitZoom) {
|
|
862
1078
|
this.scheduleAutoFitZoom()
|
|
863
1079
|
}
|
|
@@ -871,16 +1087,26 @@ export default {
|
|
|
871
1087
|
getPageWidth(docIndex, pageIndex) {
|
|
872
1088
|
const pageRef = this.getPageComponent(docIndex, pageIndex)
|
|
873
1089
|
if (!pageRef) return 0
|
|
874
|
-
const
|
|
875
|
-
|
|
876
|
-
return pageRef.getCanvasMeasurement().canvasWidth / pagesScale
|
|
1090
|
+
const measurement = this.getCachedMeasurement(docIndex, pageIndex, pageRef)
|
|
1091
|
+
return measurement.width
|
|
877
1092
|
},
|
|
878
1093
|
getPageHeight(docIndex, pageIndex) {
|
|
879
1094
|
const pageRef = this.getPageComponent(docIndex, pageIndex)
|
|
880
1095
|
if (!pageRef) return 0
|
|
1096
|
+
const measurement = this.getCachedMeasurement(docIndex, pageIndex, pageRef)
|
|
1097
|
+
return measurement.height
|
|
1098
|
+
},
|
|
1099
|
+
getPageSize(docIndex, pageIndex) {
|
|
1100
|
+
return {
|
|
1101
|
+
width: this.getPageWidth(docIndex, pageIndex),
|
|
1102
|
+
height: this.getPageHeight(docIndex, pageIndex),
|
|
1103
|
+
}
|
|
1104
|
+
},
|
|
1105
|
+
getCachedMeasurement(docIndex, pageIndex, pageRef) {
|
|
1106
|
+
const cacheKey = `${docIndex}-${pageIndex}`
|
|
881
1107
|
const doc = this.pdfDocuments[docIndex]
|
|
882
1108
|
const pagesScale = doc.pagesScale[pageIndex] || 1
|
|
883
|
-
return
|
|
1109
|
+
return getCachedMeasurement(this._pageMeasurementCache, cacheKey, pageRef, pagesScale)
|
|
884
1110
|
},
|
|
885
1111
|
calculateOptimalScale(maxPageWidth) {
|
|
886
1112
|
const containerWidth = this.$el?.clientWidth || 0
|
|
@@ -924,9 +1150,8 @@ export default {
|
|
|
924
1150
|
if (Math.abs(optimalScale - this.scale) > 0.01) {
|
|
925
1151
|
this.scale = optimalScale
|
|
926
1152
|
this.visualScale = optimalScale
|
|
927
|
-
this.pdfDocuments.
|
|
928
|
-
|
|
929
|
-
})
|
|
1153
|
+
applyScaleToDocs(this.pdfDocuments, this.scale)
|
|
1154
|
+
this._pageMeasurementCache = {}
|
|
930
1155
|
this.cachePageBounds()
|
|
931
1156
|
}
|
|
932
1157
|
},
|
|
@@ -968,15 +1193,6 @@ export default {
|
|
|
968
1193
|
opacity: 0.7;
|
|
969
1194
|
pointer-events: none;
|
|
970
1195
|
}
|
|
971
|
-
.drag-ghost {
|
|
972
|
-
position: fixed;
|
|
973
|
-
opacity: 0.9;
|
|
974
|
-
pointer-events: none;
|
|
975
|
-
z-index: 10000;
|
|
976
|
-
transform-origin: top left;
|
|
977
|
-
transition: none;
|
|
978
|
-
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
|
979
|
-
}
|
|
980
1196
|
.overlay {
|
|
981
1197
|
position: absolute;
|
|
982
1198
|
top: 0;
|