@libresign/pdf-elements 0.2.3 → 0.2.5
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 -0
- package/dist/pdf-elements.common.js +25289 -24966
- package/dist/pdf-elements.common.js.map +1 -1
- package/dist/pdf-elements.css +1 -1
- package/dist/pdf-elements.umd.js +25289 -24966
- 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 +58 -22
- package/src/components/PDFElements.vue +377 -171
- 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
|
@@ -8,7 +8,6 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
8
8
|
<div
|
|
9
9
|
v-if="pdfDocuments.length"
|
|
10
10
|
class="pages-container"
|
|
11
|
-
:style="{ transform: `scale(${visualScale / scale})`, transformOrigin: 'top center' }"
|
|
12
11
|
>
|
|
13
12
|
<div v-for="(pdfDoc, docIndex) in pdfDocuments" :key="docIndex">
|
|
14
13
|
<div v-for="(page, pIndex) in pdfDoc.pages" :key="`${docIndex}-${pIndex}`" class="page-slot">
|
|
@@ -24,6 +23,8 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
24
23
|
/>
|
|
25
24
|
<div
|
|
26
25
|
class="overlay"
|
|
26
|
+
@mousemove="handleMouseMove"
|
|
27
|
+
@touchmove="handleMouseMove"
|
|
27
28
|
>
|
|
28
29
|
<div
|
|
29
30
|
v-if="isAddingMode && previewPageDocIndex === docIndex && previewPageIndex === pIndex && previewElement && previewVisible"
|
|
@@ -36,10 +37,16 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
36
37
|
}"
|
|
37
38
|
>
|
|
38
39
|
<slot
|
|
39
|
-
name="custom"
|
|
40
|
+
:name="previewElement.type ? `element-${previewElement.type}` : 'custom'"
|
|
40
41
|
:object="previewElement"
|
|
41
42
|
:isSelected="false"
|
|
42
|
-
|
|
43
|
+
>
|
|
44
|
+
<slot
|
|
45
|
+
name="custom"
|
|
46
|
+
:object="previewElement"
|
|
47
|
+
:isSelected="false"
|
|
48
|
+
/>
|
|
49
|
+
</slot>
|
|
43
50
|
</div>
|
|
44
51
|
|
|
45
52
|
<DraggableElement
|
|
@@ -47,9 +54,10 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
47
54
|
:key="object.id"
|
|
48
55
|
:ref="`draggable${docIndex}-${pIndex}-${object.id}`"
|
|
49
56
|
:object="object"
|
|
50
|
-
:pages-scale="
|
|
57
|
+
:pages-scale="getDisplayedPageScale(docIndex, pIndex)"
|
|
51
58
|
:page-width="getPageWidth(docIndex, pIndex)"
|
|
52
59
|
:page-height="getPageHeight(docIndex, pIndex)"
|
|
60
|
+
:read-only="readOnly"
|
|
53
61
|
:on-update="(payload) => updateObject(docIndex, object.id, payload)"
|
|
54
62
|
:on-delete="() => deleteObject(docIndex, object.id)"
|
|
55
63
|
:on-drag-start="(mouseX, mouseY, pointerOffset, dragShift) => startDraggingElement(docIndex, pIndex, object, mouseX, mouseY, pointerOffset, dragShift)"
|
|
@@ -127,10 +135,14 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
127
135
|
</template>
|
|
128
136
|
|
|
129
137
|
<script>
|
|
130
|
-
import debounce from 'debounce'
|
|
131
138
|
import PDFPage from './PDFPage.vue'
|
|
132
139
|
import DraggableElement from './DraggableElement.vue'
|
|
133
140
|
import { readAsPDF, readAsArrayBuffer } from '../utils/asyncReader.js'
|
|
141
|
+
import { clampPosition, getVisibleArea } from '../utils/geometry.js'
|
|
142
|
+
import { getViewportWindow, isPageInViewport } from '../utils/pageBounds.js'
|
|
143
|
+
import { applyScaleToDocs } from '../utils/zoom.js'
|
|
144
|
+
import { objectIdExistsInDoc, findObjectPageIndex, updateObjectInDoc, removeObjectFromDoc } from '../utils/objectStore.js'
|
|
145
|
+
import { getCachedMeasurement } from '../utils/measurements.js'
|
|
134
146
|
|
|
135
147
|
export default {
|
|
136
148
|
name: 'PDFElements',
|
|
@@ -175,6 +187,10 @@ export default {
|
|
|
175
187
|
type: Boolean,
|
|
176
188
|
default: true,
|
|
177
189
|
},
|
|
190
|
+
readOnly: {
|
|
191
|
+
type: Boolean,
|
|
192
|
+
default: false,
|
|
193
|
+
},
|
|
178
194
|
pageCountFormat: {
|
|
179
195
|
type: String,
|
|
180
196
|
default: '{currentPage} of {totalPages}',
|
|
@@ -197,7 +213,16 @@ export default {
|
|
|
197
213
|
previewPageDocIndex: -1,
|
|
198
214
|
previewPageIndex: -1,
|
|
199
215
|
previewVisible: false,
|
|
200
|
-
|
|
216
|
+
hoverRafId: 0,
|
|
217
|
+
pendingHoverClientPos: null,
|
|
218
|
+
lastHoverRect: null,
|
|
219
|
+
addingListenersAttached: false,
|
|
220
|
+
dragRafId: 0,
|
|
221
|
+
pendingDragClientPos: null,
|
|
222
|
+
pageBoundsVersion: 0,
|
|
223
|
+
lastScrollTop: 0,
|
|
224
|
+
lastClientWidth: 0,
|
|
225
|
+
nextObjectCounter: 0,
|
|
201
226
|
isDraggingElement: false,
|
|
202
227
|
draggingObject: null,
|
|
203
228
|
draggingDocIndex: -1,
|
|
@@ -210,21 +235,23 @@ export default {
|
|
|
210
235
|
viewportRafId: 0,
|
|
211
236
|
objectIndexCache: {},
|
|
212
237
|
zoomRafId: null,
|
|
238
|
+
wheelZoomRafId: null,
|
|
213
239
|
boundHandleWheel: null,
|
|
214
|
-
debouncedApplyZoom: null,
|
|
215
240
|
visualScale: this.initialScale,
|
|
216
241
|
autoFitApplied: false,
|
|
242
|
+
lastContainerWidth: 0,
|
|
217
243
|
}
|
|
218
244
|
},
|
|
245
|
+
created() {
|
|
246
|
+
this._pagesBoundingRects = {}
|
|
247
|
+
this._pagesBoundingRectsList = []
|
|
248
|
+
this._pageMeasurementCache = {}
|
|
249
|
+
this._lastPageBoundsScrollTop = 0
|
|
250
|
+
this._lastPageBoundsClientHeight = 0
|
|
251
|
+
},
|
|
219
252
|
mounted() {
|
|
220
253
|
this.boundHandleWheel = this.handleWheel.bind(this)
|
|
221
|
-
this.debouncedApplyZoom = debounce(this.commitZoom, 150)
|
|
222
254
|
this.init()
|
|
223
|
-
document.addEventListener('mousemove', this.handleMouseMove)
|
|
224
|
-
document.addEventListener('touchmove', this.handleMouseMove, { passive: true })
|
|
225
|
-
document.addEventListener('mouseup', this.finishAdding)
|
|
226
|
-
document.addEventListener('touchend', this.finishAdding)
|
|
227
|
-
document.addEventListener('keydown', this.handleKeyDown)
|
|
228
255
|
window.addEventListener('scroll', this.onViewportScroll, { passive: true })
|
|
229
256
|
window.addEventListener('resize', this.onViewportScroll)
|
|
230
257
|
this.$el?.addEventListener('scroll', this.onViewportScroll, { passive: true })
|
|
@@ -234,15 +261,14 @@ export default {
|
|
|
234
261
|
if (this.zoomRafId) {
|
|
235
262
|
cancelAnimationFrame(this.zoomRafId)
|
|
236
263
|
}
|
|
237
|
-
this.
|
|
264
|
+
if (this.wheelZoomRafId) {
|
|
265
|
+
cancelAnimationFrame(this.wheelZoomRafId)
|
|
266
|
+
this.wheelZoomRafId = null
|
|
267
|
+
}
|
|
238
268
|
if (this.boundHandleWheel) {
|
|
239
269
|
this.$el?.removeEventListener('wheel', this.boundHandleWheel)
|
|
240
270
|
}
|
|
241
|
-
|
|
242
|
-
document.removeEventListener('touchmove', this.handleMouseMove)
|
|
243
|
-
document.removeEventListener('mouseup', this.finishAdding)
|
|
244
|
-
document.removeEventListener('touchend', this.finishAdding)
|
|
245
|
-
document.removeEventListener('keydown', this.handleKeyDown)
|
|
271
|
+
this.detachAddingListeners()
|
|
246
272
|
window.removeEventListener('scroll', this.onViewportScroll)
|
|
247
273
|
window.removeEventListener('resize', this.onViewportScroll)
|
|
248
274
|
this.$el?.removeEventListener('scroll', this.onViewportScroll)
|
|
@@ -250,6 +276,14 @@ export default {
|
|
|
250
276
|
window.cancelAnimationFrame(this.viewportRafId)
|
|
251
277
|
this.viewportRafId = 0
|
|
252
278
|
}
|
|
279
|
+
if (this.hoverRafId) {
|
|
280
|
+
window.cancelAnimationFrame(this.hoverRafId)
|
|
281
|
+
this.hoverRafId = 0
|
|
282
|
+
}
|
|
283
|
+
if (this.dragRafId) {
|
|
284
|
+
window.cancelAnimationFrame(this.dragRafId)
|
|
285
|
+
this.dragRafId = 0
|
|
286
|
+
}
|
|
253
287
|
},
|
|
254
288
|
methods: {
|
|
255
289
|
async init() {
|
|
@@ -274,7 +308,7 @@ export default {
|
|
|
274
308
|
for (let p = 1; p <= pdfDoc.numPages; p++) {
|
|
275
309
|
const pagePromise = pdfDoc.getPage(p)
|
|
276
310
|
pagePromise.then((page) => {
|
|
277
|
-
pageWidths
|
|
311
|
+
pageWidths.splice(p - 1, 1, page.getViewport({ scale: 1 }).width)
|
|
278
312
|
if (this.autoFitZoom) {
|
|
279
313
|
this.scheduleAutoFitZoom()
|
|
280
314
|
}
|
|
@@ -295,6 +329,7 @@ export default {
|
|
|
295
329
|
}
|
|
296
330
|
|
|
297
331
|
this.pdfDocuments = docs
|
|
332
|
+
this._pageMeasurementCache = {}
|
|
298
333
|
if (docs.length) {
|
|
299
334
|
this.selectedDocIndex = 0
|
|
300
335
|
this.selectedPageIndex = 0
|
|
@@ -324,11 +359,8 @@ export default {
|
|
|
324
359
|
? dragShift
|
|
325
360
|
: { x: 0, y: 0 }
|
|
326
361
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
this.cachePageBounds()
|
|
330
|
-
}
|
|
331
|
-
const pageRect = this.pagesBoundingRects[pageKey]?.rect
|
|
362
|
+
this.cachePageBounds()
|
|
363
|
+
const pageRect = this.getPageRect(docIndex, pageIndex)
|
|
332
364
|
if (pointerOffset && typeof pointerOffset.x === 'number' && typeof pointerOffset.y === 'number') {
|
|
333
365
|
this.draggingInitialMouseOffset.x = pointerOffset.x
|
|
334
366
|
this.draggingInitialMouseOffset.y = pointerOffset.y
|
|
@@ -344,17 +376,22 @@ export default {
|
|
|
344
376
|
this.draggingClientPosition.y = mouseY - this.draggingInitialMouseOffset.y
|
|
345
377
|
}
|
|
346
378
|
|
|
347
|
-
this.cachePageBounds()
|
|
348
379
|
},
|
|
349
380
|
|
|
350
381
|
updateDraggingPosition(clientX, clientY) {
|
|
351
382
|
if (!this.isDraggingElement) return
|
|
352
383
|
|
|
353
|
-
this.
|
|
354
|
-
this.
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
384
|
+
this.pendingDragClientPos = { x: clientX, y: clientY }
|
|
385
|
+
if (this.dragRafId) return
|
|
386
|
+
this.dragRafId = window.requestAnimationFrame(() => {
|
|
387
|
+
this.dragRafId = 0
|
|
388
|
+
const pending = this.pendingDragClientPos
|
|
389
|
+
if (!pending) return
|
|
390
|
+
this.lastMouseClientPos.x = pending.x
|
|
391
|
+
this.lastMouseClientPos.y = pending.y
|
|
392
|
+
this.draggingClientPosition.x = pending.x - this.draggingInitialMouseOffset.x
|
|
393
|
+
this.draggingClientPosition.y = pending.y - this.draggingInitialMouseOffset.y
|
|
394
|
+
})
|
|
358
395
|
},
|
|
359
396
|
|
|
360
397
|
stopDraggingElement() {
|
|
@@ -386,10 +423,12 @@ export default {
|
|
|
386
423
|
this.draggingDocIndex = -1
|
|
387
424
|
this.draggingPageIndex = -1
|
|
388
425
|
this.draggingElementShift = { x: 0, y: 0 }
|
|
426
|
+
this.pendingDragClientPos = null
|
|
389
427
|
},
|
|
390
428
|
|
|
391
429
|
startAddingElement(templateObject) {
|
|
392
430
|
if (!this.pdfDocuments.length) return
|
|
431
|
+
this.attachAddingListeners()
|
|
393
432
|
this.isAddingMode = true
|
|
394
433
|
this.previewElement = { ...templateObject }
|
|
395
434
|
this.previewPageDocIndex = 0
|
|
@@ -400,33 +439,103 @@ export default {
|
|
|
400
439
|
},
|
|
401
440
|
|
|
402
441
|
cachePageBounds() {
|
|
403
|
-
|
|
442
|
+
const nextRects = {}
|
|
443
|
+
const container = this.$el
|
|
444
|
+
const scrollTop = container?.scrollTop || 0
|
|
445
|
+
const viewHeight = container?.clientHeight || 0
|
|
446
|
+
if (!this.isAddingMode && !this.isDraggingElement &&
|
|
447
|
+
scrollTop === this._lastPageBoundsScrollTop &&
|
|
448
|
+
viewHeight === this._lastPageBoundsClientHeight) {
|
|
449
|
+
return
|
|
450
|
+
}
|
|
451
|
+
this._lastPageBoundsScrollTop = scrollTop
|
|
452
|
+
this._lastPageBoundsClientHeight = viewHeight
|
|
453
|
+
const { minY, maxY } = getViewportWindow(scrollTop, viewHeight)
|
|
404
454
|
for (let docIdx = 0; docIdx < this.pdfDocuments.length; docIdx++) {
|
|
405
455
|
for (let pageIdx = 0; pageIdx < this.pdfDocuments[docIdx].pages.length; pageIdx++) {
|
|
406
456
|
const canvas = this.getPageCanvasElement(docIdx, pageIdx)
|
|
407
457
|
if (!canvas) continue
|
|
458
|
+
if (viewHeight) {
|
|
459
|
+
const wrapper = canvas.closest('.page-wrapper') || canvas
|
|
460
|
+
const offsetTop = wrapper.offsetTop || 0
|
|
461
|
+
const offsetHeight = wrapper.offsetHeight || 0
|
|
462
|
+
if (!isPageInViewport(offsetTop, offsetHeight, minY, maxY)) {
|
|
463
|
+
continue
|
|
464
|
+
}
|
|
465
|
+
}
|
|
408
466
|
const rect = canvas.getBoundingClientRect()
|
|
409
|
-
|
|
467
|
+
nextRects[`${docIdx}-${pageIdx}`] = {
|
|
410
468
|
docIndex: docIdx,
|
|
411
469
|
pageIndex: pageIdx,
|
|
412
470
|
rect,
|
|
413
471
|
}
|
|
414
472
|
}
|
|
415
473
|
}
|
|
474
|
+
this._pagesBoundingRects = nextRects
|
|
475
|
+
this._pagesBoundingRectsList = Object.values(nextRects)
|
|
476
|
+
this.pageBoundsVersion++
|
|
477
|
+
},
|
|
478
|
+
cachePageBoundsForPage(docIndex, pageIndex) {
|
|
479
|
+
const canvas = this.getPageCanvasElement(docIndex, pageIndex)
|
|
480
|
+
if (!canvas) return
|
|
481
|
+
const rect = canvas.getBoundingClientRect()
|
|
482
|
+
this._pagesBoundingRects = {
|
|
483
|
+
...this._pagesBoundingRects,
|
|
484
|
+
[`${docIndex}-${pageIndex}`]: {
|
|
485
|
+
docIndex,
|
|
486
|
+
pageIndex,
|
|
487
|
+
rect,
|
|
488
|
+
},
|
|
489
|
+
}
|
|
490
|
+
this._pagesBoundingRectsList = Object.values(this._pagesBoundingRects)
|
|
491
|
+
this.pageBoundsVersion++
|
|
492
|
+
},
|
|
493
|
+
getPageBoundsMap() {
|
|
494
|
+
return this._pagesBoundingRects || {}
|
|
495
|
+
},
|
|
496
|
+
getPageBoundsList() {
|
|
497
|
+
return this._pagesBoundingRectsList || []
|
|
498
|
+
},
|
|
499
|
+
getPageRect(docIndex, pageIndex) {
|
|
500
|
+
return this.getPageBoundsMap()[`${docIndex}-${pageIndex}`]?.rect || null
|
|
501
|
+
},
|
|
502
|
+
getPointerPosition(event) {
|
|
503
|
+
if (event?.type?.includes?.('touch')) {
|
|
504
|
+
return {
|
|
505
|
+
x: event.touches?.[0]?.clientX,
|
|
506
|
+
y: event.touches?.[0]?.clientY,
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return {
|
|
510
|
+
x: event?.clientX,
|
|
511
|
+
y: event?.clientY,
|
|
512
|
+
}
|
|
416
513
|
},
|
|
417
514
|
|
|
418
515
|
getDisplayedPageScale(docIndex, pageIndex) {
|
|
516
|
+
this.pageBoundsVersion
|
|
419
517
|
const doc = this.pdfDocuments[docIndex]
|
|
420
518
|
if (!doc) return 1
|
|
519
|
+
const baseWidth = doc.pageWidths?.[pageIndex] || 0
|
|
520
|
+
const pageBoundsMap = this.getPageBoundsMap()
|
|
521
|
+
if (!pageBoundsMap[`${docIndex}-${pageIndex}`]) {
|
|
522
|
+
this.cachePageBoundsForPage(docIndex, pageIndex)
|
|
523
|
+
}
|
|
524
|
+
const rectWidth = this.getPageBoundsMap()[`${docIndex}-${pageIndex}`]?.rect?.width || 0
|
|
525
|
+
if (rectWidth && baseWidth) {
|
|
526
|
+
return rectWidth / baseWidth
|
|
527
|
+
}
|
|
528
|
+
if (this.isAddingMode || this.isDraggingElement) {
|
|
529
|
+
const canvas = this.getPageCanvasElement(docIndex, pageIndex)
|
|
530
|
+
const fallbackRectWidth = canvas?.getBoundingClientRect?.().width || 0
|
|
531
|
+
if (fallbackRectWidth && baseWidth) {
|
|
532
|
+
return fallbackRectWidth / baseWidth
|
|
533
|
+
}
|
|
534
|
+
}
|
|
421
535
|
const base = doc.pagesScale[pageIndex] || 1
|
|
422
536
|
const factor = this.visualScale && this.scale ? (this.visualScale / this.scale) : 1
|
|
423
537
|
return base * factor
|
|
424
538
|
},
|
|
425
|
-
getRenderPageScale(docIndex, pageIndex) {
|
|
426
|
-
const doc = this.pdfDocuments[docIndex]
|
|
427
|
-
if (!doc) return 1
|
|
428
|
-
return doc.pagesScale[pageIndex] || 1
|
|
429
|
-
},
|
|
430
539
|
getPageComponent(docIndex, pageIndex) {
|
|
431
540
|
const pageRef = this.$refs[`page${docIndex}-${pageIndex}`]
|
|
432
541
|
return pageRef && Array.isArray(pageRef) && pageRef[0] ? pageRef[0] : null
|
|
@@ -439,8 +548,25 @@ export default {
|
|
|
439
548
|
onViewportScroll() {
|
|
440
549
|
if (this.viewportRafId) return
|
|
441
550
|
this.viewportRafId = window.requestAnimationFrame(() => {
|
|
551
|
+
const container = this.$el
|
|
552
|
+
const scrollTop = container?.scrollTop || 0
|
|
553
|
+
const clientWidth = container?.clientWidth || 0
|
|
554
|
+
const scrollChanged = scrollTop !== this.lastScrollTop
|
|
555
|
+
const widthChanged = clientWidth !== this.lastClientWidth
|
|
556
|
+
this.lastScrollTop = scrollTop
|
|
557
|
+
this.lastClientWidth = clientWidth
|
|
558
|
+
|
|
442
559
|
if (this.isAddingMode || this.isDraggingElement) {
|
|
443
|
-
|
|
560
|
+
if (scrollChanged || widthChanged) {
|
|
561
|
+
this.cachePageBounds()
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
if (this.autoFitZoom && !this.isAddingMode && !this.isDraggingElement) {
|
|
565
|
+
if (clientWidth && widthChanged) {
|
|
566
|
+
this.lastContainerWidth = clientWidth
|
|
567
|
+
this.autoFitApplied = false
|
|
568
|
+
this.scheduleAutoFitZoom()
|
|
569
|
+
}
|
|
444
570
|
}
|
|
445
571
|
this.viewportRafId = 0
|
|
446
572
|
})
|
|
@@ -448,49 +574,75 @@ export default {
|
|
|
448
574
|
|
|
449
575
|
handleMouseMove(event) {
|
|
450
576
|
if (!this.isAddingMode || !this.previewElement) return
|
|
577
|
+
const { x, y } = this.getPointerPosition(event)
|
|
578
|
+
if (x === undefined || y === undefined) return
|
|
579
|
+
this.pendingHoverClientPos = { x, y }
|
|
580
|
+
if (this.hoverRafId) return
|
|
581
|
+
this.hoverRafId = window.requestAnimationFrame(() => {
|
|
582
|
+
this.hoverRafId = 0
|
|
583
|
+
const pending = this.pendingHoverClientPos
|
|
584
|
+
if (!pending) return
|
|
585
|
+
|
|
586
|
+
const cursorX = pending.x
|
|
587
|
+
const cursorY = pending.y
|
|
588
|
+
let target = null
|
|
589
|
+
|
|
590
|
+
if (this.lastHoverRect &&
|
|
591
|
+
cursorX >= this.lastHoverRect.left && cursorX <= this.lastHoverRect.right &&
|
|
592
|
+
cursorY >= this.lastHoverRect.top && cursorY <= this.lastHoverRect.bottom) {
|
|
593
|
+
target = {
|
|
594
|
+
docIndex: this.previewPageDocIndex,
|
|
595
|
+
pageIndex: this.previewPageIndex,
|
|
596
|
+
rect: this.lastHoverRect,
|
|
597
|
+
}
|
|
598
|
+
} else {
|
|
599
|
+
const rects = this.getPageBoundsList().length
|
|
600
|
+
? this.getPageBoundsList()
|
|
601
|
+
: Object.values(this.getPageBoundsMap())
|
|
602
|
+
for (let i = 0; i < rects.length; i++) {
|
|
603
|
+
const entry = rects[i]
|
|
604
|
+
const rect = entry.rect
|
|
605
|
+
if (cursorX >= rect.left && cursorX <= rect.right &&
|
|
606
|
+
cursorY >= rect.top && cursorY <= rect.bottom) {
|
|
607
|
+
target = entry
|
|
608
|
+
break
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
451
612
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
const { docIndex, pageIndex, rect } = this.pagesBoundingRects[key]
|
|
458
|
-
if (clientX >= rect.left && clientX <= rect.right &&
|
|
459
|
-
clientY >= rect.top && clientY <= rect.bottom) {
|
|
460
|
-
this.previewPageDocIndex = docIndex
|
|
461
|
-
this.previewPageIndex = pageIndex
|
|
462
|
-
foundPage = true
|
|
463
|
-
|
|
464
|
-
const canvasEl = this.getPageCanvasElement(docIndex, pageIndex)
|
|
465
|
-
const pagesScale = this.pdfDocuments[docIndex]?.pagesScale?.[pageIndex] || 1
|
|
466
|
-
const layoutWidth = canvasEl?.offsetWidth || rect.width
|
|
467
|
-
const layoutHeight = canvasEl?.offsetHeight || rect.height
|
|
468
|
-
const layoutScaleX = layoutWidth ? rect.width / layoutWidth : 1
|
|
469
|
-
const layoutScaleY = layoutHeight ? rect.height / layoutHeight : 1
|
|
470
|
-
const relX = (clientX - rect.left) / layoutScaleX / pagesScale
|
|
471
|
-
const relY = (clientY - rect.top) / layoutScaleY / pagesScale
|
|
472
|
-
|
|
473
|
-
const pageWidth = layoutWidth / pagesScale
|
|
474
|
-
const pageHeight = layoutHeight / pagesScale
|
|
475
|
-
this.previewScale.x = pagesScale * layoutScaleX
|
|
476
|
-
this.previewScale.y = pagesScale * layoutScaleY
|
|
477
|
-
let x = relX - this.previewElement.width / 2
|
|
478
|
-
let y = relY - this.previewElement.height / 2
|
|
479
|
-
|
|
480
|
-
x = Math.max(0, Math.min(x, pageWidth - this.previewElement.width))
|
|
481
|
-
y = Math.max(0, Math.min(y, pageHeight - this.previewElement.height))
|
|
482
|
-
|
|
483
|
-
this.previewPosition.x = x
|
|
484
|
-
this.previewPosition.y = y
|
|
485
|
-
this.previewVisible = true
|
|
486
|
-
break
|
|
613
|
+
if (!target) {
|
|
614
|
+
this.previewVisible = false
|
|
615
|
+
this.previewScale = { x: 1, y: 1 }
|
|
616
|
+
this.lastHoverRect = null
|
|
617
|
+
return
|
|
487
618
|
}
|
|
488
|
-
}
|
|
489
619
|
|
|
490
|
-
|
|
491
|
-
this.
|
|
492
|
-
this.
|
|
493
|
-
|
|
620
|
+
this.previewPageDocIndex = target.docIndex
|
|
621
|
+
this.previewPageIndex = target.pageIndex
|
|
622
|
+
this.lastHoverRect = target.rect
|
|
623
|
+
const canvasEl = this.getPageCanvasElement(target.docIndex, target.pageIndex)
|
|
624
|
+
const pagesScale = this.pdfDocuments[target.docIndex]?.pagesScale?.[target.pageIndex] || 1
|
|
625
|
+
const renderWidth = canvasEl?.width || target.rect.width
|
|
626
|
+
const renderHeight = canvasEl?.height || target.rect.height
|
|
627
|
+
const layoutScaleX = renderWidth ? target.rect.width / renderWidth : 1
|
|
628
|
+
const layoutScaleY = renderHeight ? target.rect.height / renderHeight : 1
|
|
629
|
+
const relX = (cursorX - target.rect.left) / layoutScaleX / pagesScale
|
|
630
|
+
const relY = (cursorY - target.rect.top) / layoutScaleY / pagesScale
|
|
631
|
+
|
|
632
|
+
const pageWidth = renderWidth / pagesScale
|
|
633
|
+
const pageHeight = renderHeight / pagesScale
|
|
634
|
+
this.previewScale.x = pagesScale
|
|
635
|
+
this.previewScale.y = pagesScale
|
|
636
|
+
let x = relX - this.previewElement.width / 2
|
|
637
|
+
let y = relY - this.previewElement.height / 2
|
|
638
|
+
|
|
639
|
+
x = Math.max(0, Math.min(x, pageWidth - this.previewElement.width))
|
|
640
|
+
y = Math.max(0, Math.min(y, pageHeight - this.previewElement.height))
|
|
641
|
+
|
|
642
|
+
this.previewPosition.x = x
|
|
643
|
+
this.previewPosition.y = y
|
|
644
|
+
this.previewVisible = true
|
|
645
|
+
})
|
|
494
646
|
},
|
|
495
647
|
|
|
496
648
|
handleKeyDown(event) {
|
|
@@ -506,7 +658,11 @@ export default {
|
|
|
506
658
|
const factor = 1 - (event.deltaY * 0.002)
|
|
507
659
|
const nextVisual = Math.max(0.5, Math.min(3.0, this.visualScale * factor))
|
|
508
660
|
this.visualScale = nextVisual
|
|
509
|
-
this.
|
|
661
|
+
if (this.wheelZoomRafId) return
|
|
662
|
+
this.wheelZoomRafId = window.requestAnimationFrame(() => {
|
|
663
|
+
this.wheelZoomRafId = null
|
|
664
|
+
this.commitZoom()
|
|
665
|
+
})
|
|
510
666
|
},
|
|
511
667
|
|
|
512
668
|
commitZoom() {
|
|
@@ -514,10 +670,9 @@ export default {
|
|
|
514
670
|
|
|
515
671
|
this.scale = newScale
|
|
516
672
|
|
|
517
|
-
this.pdfDocuments.
|
|
518
|
-
doc.pagesScale = doc.pagesScale.map(() => this.scale)
|
|
519
|
-
})
|
|
673
|
+
applyScaleToDocs(this.pdfDocuments, this.scale)
|
|
520
674
|
|
|
675
|
+
this._pageMeasurementCache = {}
|
|
521
676
|
this.cachePageBounds()
|
|
522
677
|
},
|
|
523
678
|
|
|
@@ -527,7 +682,7 @@ export default {
|
|
|
527
682
|
|
|
528
683
|
const objectToAdd = {
|
|
529
684
|
...this.previewElement,
|
|
530
|
-
id:
|
|
685
|
+
id: this.generateObjectId(),
|
|
531
686
|
x: Math.round(this.previewPosition.x),
|
|
532
687
|
y: Math.round(this.previewPosition.y),
|
|
533
688
|
}
|
|
@@ -564,6 +719,30 @@ export default {
|
|
|
564
719
|
this.isAddingMode = false
|
|
565
720
|
this.previewElement = null
|
|
566
721
|
this.previewVisible = false
|
|
722
|
+
this.detachAddingListeners()
|
|
723
|
+
},
|
|
724
|
+
generateObjectId() {
|
|
725
|
+
const counter = this.nextObjectCounter++
|
|
726
|
+
const rand = Math.random().toString(36).slice(2, 8)
|
|
727
|
+
return `obj-${Date.now()}-${counter}-${rand}`
|
|
728
|
+
},
|
|
729
|
+
attachAddingListeners() {
|
|
730
|
+
if (this.addingListenersAttached) return
|
|
731
|
+
this.addingListenersAttached = true
|
|
732
|
+
document.addEventListener('mousemove', this.handleMouseMove)
|
|
733
|
+
document.addEventListener('touchmove', this.handleMouseMove, { passive: true })
|
|
734
|
+
document.addEventListener('mouseup', this.finishAdding)
|
|
735
|
+
document.addEventListener('touchend', this.finishAdding)
|
|
736
|
+
document.addEventListener('keydown', this.handleKeyDown)
|
|
737
|
+
},
|
|
738
|
+
detachAddingListeners() {
|
|
739
|
+
if (!this.addingListenersAttached) return
|
|
740
|
+
this.addingListenersAttached = false
|
|
741
|
+
document.removeEventListener('mousemove', this.handleMouseMove)
|
|
742
|
+
document.removeEventListener('touchmove', this.handleMouseMove, { passive: true })
|
|
743
|
+
document.removeEventListener('mouseup', this.finishAdding)
|
|
744
|
+
document.removeEventListener('touchend', this.finishAdding)
|
|
745
|
+
document.removeEventListener('keydown', this.handleKeyDown)
|
|
567
746
|
},
|
|
568
747
|
|
|
569
748
|
addObjectToPage(object, pageIndex = this.selectedPageIndex, docIndex = this.selectedDocIndex) {
|
|
@@ -574,45 +753,65 @@ export default {
|
|
|
574
753
|
const pageRef = this.getPageComponent(docIndex, pageIndex)
|
|
575
754
|
if (!pageRef) return false
|
|
576
755
|
|
|
756
|
+
let objectToAdd = object
|
|
757
|
+
if (!objectToAdd.id || this.objectIdExists(docIndex, objectToAdd.id)) {
|
|
758
|
+
objectToAdd = { ...objectToAdd, id: this.generateObjectId() }
|
|
759
|
+
}
|
|
760
|
+
|
|
577
761
|
const pageWidth = this.getPageWidth(docIndex, pageIndex)
|
|
578
762
|
const pageHeight = this.getPageHeight(docIndex, pageIndex)
|
|
579
763
|
|
|
580
|
-
if (
|
|
581
|
-
|
|
582
|
-
|
|
764
|
+
if (objectToAdd.x < 0 || objectToAdd.y < 0 ||
|
|
765
|
+
objectToAdd.x + objectToAdd.width > pageWidth ||
|
|
766
|
+
objectToAdd.y + objectToAdd.height > pageHeight) {
|
|
583
767
|
return false
|
|
584
768
|
}
|
|
585
769
|
|
|
586
|
-
doc.allObjects
|
|
587
|
-
|
|
588
|
-
)
|
|
770
|
+
doc.allObjects[pageIndex].push(objectToAdd)
|
|
771
|
+
this.objectIndexCache[`${docIndex}-${objectToAdd.id}`] = pageIndex
|
|
589
772
|
return true
|
|
590
773
|
},
|
|
774
|
+
objectIdExists(docIndex, objectId) {
|
|
775
|
+
if (!objectId) return false
|
|
776
|
+
const cacheKey = `${docIndex}-${objectId}`
|
|
777
|
+
if (this.objectIndexCache[cacheKey] !== undefined) return true
|
|
778
|
+
const doc = this.pdfDocuments[docIndex]
|
|
779
|
+
return objectIdExistsInDoc(doc, objectId)
|
|
780
|
+
},
|
|
781
|
+
updateObjectInPage(docIndex, pageIndex, objectId, payload) {
|
|
782
|
+
const doc = this.pdfDocuments[docIndex]
|
|
783
|
+
updateObjectInDoc(doc, pageIndex, objectId, payload)
|
|
784
|
+
},
|
|
785
|
+
removeObjectFromPage(docIndex, pageIndex, objectId) {
|
|
786
|
+
const doc = this.pdfDocuments[docIndex]
|
|
787
|
+
removeObjectFromDoc(doc, pageIndex, objectId)
|
|
788
|
+
},
|
|
591
789
|
|
|
592
790
|
getAllObjects(docIndex = this.selectedDocIndex) {
|
|
593
791
|
if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return []
|
|
594
792
|
|
|
595
793
|
const doc = this.pdfDocuments[docIndex]
|
|
596
|
-
const scale = this.scale || 1
|
|
597
794
|
const result = []
|
|
598
795
|
|
|
599
796
|
doc.allObjects.forEach((pageObjects, pageIndex) => {
|
|
600
797
|
const pageRef = this.getPageComponent(docIndex, pageIndex)
|
|
601
798
|
if (!pageRef) return
|
|
602
|
-
|
|
603
|
-
const
|
|
604
|
-
const
|
|
799
|
+
const measurement = this.getCachedMeasurement(docIndex, pageIndex, pageRef)
|
|
800
|
+
const normalizedCanvasHeight = measurement.height
|
|
801
|
+
const pagesScale = doc.pagesScale[pageIndex] || 1
|
|
605
802
|
|
|
606
803
|
pageObjects.forEach(object => {
|
|
607
804
|
result.push({
|
|
608
805
|
...object,
|
|
609
806
|
pageIndex,
|
|
610
807
|
pageNumber: pageIndex + 1,
|
|
611
|
-
scale,
|
|
808
|
+
scale: pagesScale,
|
|
612
809
|
normalizedCoordinates: {
|
|
613
810
|
llx: parseInt(object.x, 10),
|
|
614
811
|
lly: parseInt(normalizedCanvasHeight - object.y, 10),
|
|
615
812
|
ury: parseInt(normalizedCanvasHeight - object.y - object.height, 10),
|
|
813
|
+
width: parseInt(object.width, 10),
|
|
814
|
+
height: parseInt(object.height, 10),
|
|
616
815
|
},
|
|
617
816
|
})
|
|
618
817
|
})
|
|
@@ -629,12 +828,10 @@ export default {
|
|
|
629
828
|
let currentPageIndex = this.objectIndexCache[cacheKey]
|
|
630
829
|
|
|
631
830
|
if (currentPageIndex === undefined) {
|
|
632
|
-
doc
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
}
|
|
637
|
-
})
|
|
831
|
+
currentPageIndex = findObjectPageIndex(doc, objectId)
|
|
832
|
+
if (currentPageIndex !== undefined) {
|
|
833
|
+
this.objectIndexCache[cacheKey] = currentPageIndex
|
|
834
|
+
}
|
|
638
835
|
}
|
|
639
836
|
|
|
640
837
|
if (currentPageIndex === undefined) return
|
|
@@ -646,19 +843,18 @@ export default {
|
|
|
646
843
|
const mouseX = payload._mouseX
|
|
647
844
|
const mouseY = payload._mouseY
|
|
648
845
|
|
|
649
|
-
|
|
846
|
+
const pageBoundsMap = this.getPageBoundsMap()
|
|
847
|
+
if (!pageBoundsMap || Object.keys(pageBoundsMap).length === 0) {
|
|
650
848
|
this.cachePageBounds()
|
|
651
849
|
}
|
|
652
850
|
|
|
653
|
-
const currentPageRect = this.
|
|
851
|
+
const currentPageRect = this.getPageRect(docIndex, currentPageIndex)
|
|
654
852
|
if (currentPageRect) {
|
|
655
853
|
const pagesScale = this.getDisplayedPageScale(docIndex, currentPageIndex)
|
|
656
854
|
const relX = (mouseX - currentPageRect.left - this.draggingElementShift.x) / pagesScale - (this.draggingInitialMouseOffset.x / pagesScale)
|
|
657
855
|
const relY = (mouseY - currentPageRect.top - this.draggingElementShift.y) / pagesScale - (this.draggingInitialMouseOffset.y / pagesScale)
|
|
658
856
|
|
|
659
|
-
|
|
660
|
-
obj.id === objectId ? { ...obj, x: relX, y: relY } : obj
|
|
661
|
-
)
|
|
857
|
+
this.updateObjectInPage(docIndex, currentPageIndex, objectId, { x: relX, y: relY })
|
|
662
858
|
}
|
|
663
859
|
return
|
|
664
860
|
}
|
|
@@ -669,6 +865,14 @@ export default {
|
|
|
669
865
|
const objWidth = payload.width !== undefined ? payload.width : targetObject.width
|
|
670
866
|
const objHeight = payload.height !== undefined ? payload.height : targetObject.height
|
|
671
867
|
|
|
868
|
+
const { width: currentPageWidth, height: currentPageHeight } = this.getPageSize(docIndex, currentPageIndex)
|
|
869
|
+
if (newX >= 0 && newY >= 0 &&
|
|
870
|
+
newX + objWidth <= currentPageWidth &&
|
|
871
|
+
newY + objHeight <= currentPageHeight) {
|
|
872
|
+
this.updateObjectInPage(docIndex, currentPageIndex, objectId, payload)
|
|
873
|
+
return
|
|
874
|
+
}
|
|
875
|
+
|
|
672
876
|
let bestPageIndex = currentPageIndex
|
|
673
877
|
let maxVisibleArea = 0
|
|
674
878
|
|
|
@@ -676,30 +880,18 @@ export default {
|
|
|
676
880
|
const pageWidth = this.getPageWidth(docIndex, pIndex)
|
|
677
881
|
const pageHeight = this.getPageHeight(docIndex, pIndex)
|
|
678
882
|
|
|
679
|
-
const
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
if (visibleRight > visibleLeft && visibleBottom > visibleTop) {
|
|
685
|
-
const visibleArea = (visibleRight - visibleLeft) * (visibleBottom - visibleTop)
|
|
686
|
-
if (visibleArea > maxVisibleArea) {
|
|
687
|
-
maxVisibleArea = visibleArea
|
|
688
|
-
bestPageIndex = pIndex
|
|
689
|
-
}
|
|
883
|
+
const visibleArea = getVisibleArea(newX, newY, objWidth, objHeight, pageWidth, pageHeight)
|
|
884
|
+
if (visibleArea > maxVisibleArea) {
|
|
885
|
+
maxVisibleArea = visibleArea
|
|
886
|
+
bestPageIndex = pIndex
|
|
690
887
|
}
|
|
691
888
|
}
|
|
692
889
|
|
|
693
890
|
if (bestPageIndex !== currentPageIndex) {
|
|
694
|
-
const pageWidth = this.
|
|
695
|
-
const
|
|
891
|
+
const { width: pageWidth, height: pageHeight } = this.getPageSize(docIndex, bestPageIndex)
|
|
892
|
+
const { x: adjustedX, y: adjustedY } = clampPosition(newX, newY, objWidth, objHeight, pageWidth, pageHeight)
|
|
696
893
|
|
|
697
|
-
|
|
698
|
-
const adjustedY = Math.max(0, Math.min(newY, pageHeight - objHeight))
|
|
699
|
-
|
|
700
|
-
doc.allObjects[currentPageIndex] = doc.allObjects[currentPageIndex].filter(
|
|
701
|
-
obj => obj.id !== objectId
|
|
702
|
-
)
|
|
894
|
+
this.removeObjectFromPage(docIndex, currentPageIndex, objectId)
|
|
703
895
|
const updatedObject = {
|
|
704
896
|
...targetObject,
|
|
705
897
|
...payload,
|
|
@@ -711,8 +903,7 @@ export default {
|
|
|
711
903
|
return
|
|
712
904
|
}
|
|
713
905
|
|
|
714
|
-
const pageWidth = this.
|
|
715
|
-
const pageHeight = this.getPageHeight(docIndex, currentPageIndex)
|
|
906
|
+
const { width: pageWidth, height: pageHeight } = this.getPageSize(docIndex, currentPageIndex)
|
|
716
907
|
|
|
717
908
|
if (newX < 0 || newY < 0 ||
|
|
718
909
|
newX + objWidth > pageWidth ||
|
|
@@ -721,18 +912,33 @@ export default {
|
|
|
721
912
|
}
|
|
722
913
|
}
|
|
723
914
|
|
|
724
|
-
|
|
725
|
-
objects.map(object => (object.id === objectId ? { ...object, ...payload } : object)),
|
|
726
|
-
)
|
|
915
|
+
this.updateObjectInPage(docIndex, currentPageIndex, objectId, payload)
|
|
727
916
|
},
|
|
728
917
|
|
|
729
918
|
deleteObject(docIndex, objectId) {
|
|
730
919
|
if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return
|
|
731
920
|
const doc = this.pdfDocuments[docIndex]
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
921
|
+
let deletedObject = null
|
|
922
|
+
let deletedPageIndex = -1
|
|
923
|
+
|
|
924
|
+
doc.allObjects.some((objects, pageIndex) => {
|
|
925
|
+
const objectIndex = objects.findIndex(object => object.id === objectId)
|
|
926
|
+
if (objectIndex === -1) {
|
|
927
|
+
return false
|
|
928
|
+
}
|
|
929
|
+
deletedObject = objects[objectIndex]
|
|
930
|
+
deletedPageIndex = pageIndex
|
|
931
|
+
objects.splice(objectIndex, 1)
|
|
932
|
+
return true
|
|
933
|
+
})
|
|
735
934
|
delete this.objectIndexCache[`${docIndex}-${objectId}`]
|
|
935
|
+
if (deletedObject) {
|
|
936
|
+
this.$emit('pdf-elements:delete-object', {
|
|
937
|
+
object: deletedObject,
|
|
938
|
+
docIndex,
|
|
939
|
+
pageIndex: deletedPageIndex,
|
|
940
|
+
})
|
|
941
|
+
}
|
|
736
942
|
},
|
|
737
943
|
|
|
738
944
|
checkAndMoveObjectPage(docIndex, objectId, mouseX, mouseY) {
|
|
@@ -743,12 +949,10 @@ export default {
|
|
|
743
949
|
let currentPageIndex = this.objectIndexCache[cacheKey]
|
|
744
950
|
|
|
745
951
|
if (currentPageIndex === undefined) {
|
|
746
|
-
doc
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
}
|
|
751
|
-
})
|
|
952
|
+
currentPageIndex = findObjectPageIndex(doc, objectId)
|
|
953
|
+
if (currentPageIndex !== undefined) {
|
|
954
|
+
this.objectIndexCache[cacheKey] = currentPageIndex
|
|
955
|
+
}
|
|
752
956
|
}
|
|
753
957
|
|
|
754
958
|
if (currentPageIndex === undefined) return undefined
|
|
@@ -757,8 +961,9 @@ export default {
|
|
|
757
961
|
if (!targetObject) return currentPageIndex
|
|
758
962
|
|
|
759
963
|
let targetPageIndex = currentPageIndex
|
|
760
|
-
|
|
761
|
-
|
|
964
|
+
const pageBoundsMap = this.getPageBoundsMap()
|
|
965
|
+
for (const key in pageBoundsMap) {
|
|
966
|
+
const { docIndex: rectDocIndex, pageIndex, rect } = pageBoundsMap[key]
|
|
762
967
|
if (rectDocIndex === docIndex &&
|
|
763
968
|
mouseX >= rect.left && mouseX <= rect.right &&
|
|
764
969
|
mouseY >= rect.top && mouseY <= rect.bottom) {
|
|
@@ -767,23 +972,25 @@ export default {
|
|
|
767
972
|
}
|
|
768
973
|
}
|
|
769
974
|
|
|
770
|
-
const targetPageRect = this.
|
|
975
|
+
const targetPageRect = this.getPageRect(docIndex, targetPageIndex)
|
|
771
976
|
if (!targetPageRect) return currentPageIndex
|
|
772
977
|
|
|
773
978
|
const pagesScale = this.getDisplayedPageScale(docIndex, targetPageIndex)
|
|
774
979
|
const relX = (mouseX - targetPageRect.left - this.draggingElementShift.x) / pagesScale - (this.draggingInitialMouseOffset.x / pagesScale)
|
|
775
980
|
const relY = (mouseY - targetPageRect.top - this.draggingElementShift.y) / pagesScale - (this.draggingInitialMouseOffset.y / pagesScale)
|
|
776
981
|
|
|
777
|
-
const pageWidth = this.
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
982
|
+
const { width: pageWidth, height: pageHeight } = this.getPageSize(docIndex, targetPageIndex)
|
|
983
|
+
const { x: clampedX, y: clampedY } = clampPosition(
|
|
984
|
+
relX,
|
|
985
|
+
relY,
|
|
986
|
+
targetObject.width,
|
|
987
|
+
targetObject.height,
|
|
988
|
+
pageWidth,
|
|
989
|
+
pageHeight,
|
|
990
|
+
)
|
|
782
991
|
|
|
783
992
|
if (targetPageIndex !== currentPageIndex) {
|
|
784
|
-
|
|
785
|
-
obj => obj.id !== objectId
|
|
786
|
-
)
|
|
993
|
+
this.removeObjectFromPage(docIndex, currentPageIndex, objectId)
|
|
787
994
|
doc.allObjects[targetPageIndex].push({
|
|
788
995
|
...targetObject,
|
|
789
996
|
x: clampedX,
|
|
@@ -791,9 +998,7 @@ export default {
|
|
|
791
998
|
})
|
|
792
999
|
this.objectIndexCache[cacheKey] = targetPageIndex
|
|
793
1000
|
} else if (clampedX !== targetObject.x || clampedY !== targetObject.y) {
|
|
794
|
-
|
|
795
|
-
obj.id === objectId ? { ...obj, x: clampedX, y: clampedY } : obj
|
|
796
|
-
)
|
|
1001
|
+
this.updateObjectInPage(docIndex, currentPageIndex, objectId, { x: clampedX, y: clampedY })
|
|
797
1002
|
}
|
|
798
1003
|
|
|
799
1004
|
return targetPageIndex
|
|
@@ -801,8 +1006,9 @@ export default {
|
|
|
801
1006
|
|
|
802
1007
|
onMeasure(e, docIndex, pageIndex) {
|
|
803
1008
|
if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return
|
|
804
|
-
this.pdfDocuments[docIndex].pagesScale
|
|
805
|
-
this.
|
|
1009
|
+
this.pdfDocuments[docIndex].pagesScale.splice(pageIndex, 1, e.scale)
|
|
1010
|
+
this._pageMeasurementCache[`${docIndex}-${pageIndex}`] = null
|
|
1011
|
+
this.cachePageBoundsForPage(docIndex, pageIndex)
|
|
806
1012
|
if (this.autoFitZoom) {
|
|
807
1013
|
this.scheduleAutoFitZoom()
|
|
808
1014
|
}
|
|
@@ -816,16 +1022,26 @@ export default {
|
|
|
816
1022
|
getPageWidth(docIndex, pageIndex) {
|
|
817
1023
|
const pageRef = this.getPageComponent(docIndex, pageIndex)
|
|
818
1024
|
if (!pageRef) return 0
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
return pageRef.getCanvasMeasurement().canvasWidth / pagesScale
|
|
1025
|
+
const measurement = this.getCachedMeasurement(docIndex, pageIndex, pageRef)
|
|
1026
|
+
return measurement.width
|
|
822
1027
|
},
|
|
823
1028
|
getPageHeight(docIndex, pageIndex) {
|
|
824
1029
|
const pageRef = this.getPageComponent(docIndex, pageIndex)
|
|
825
1030
|
if (!pageRef) return 0
|
|
1031
|
+
const measurement = this.getCachedMeasurement(docIndex, pageIndex, pageRef)
|
|
1032
|
+
return measurement.height
|
|
1033
|
+
},
|
|
1034
|
+
getPageSize(docIndex, pageIndex) {
|
|
1035
|
+
return {
|
|
1036
|
+
width: this.getPageWidth(docIndex, pageIndex),
|
|
1037
|
+
height: this.getPageHeight(docIndex, pageIndex),
|
|
1038
|
+
}
|
|
1039
|
+
},
|
|
1040
|
+
getCachedMeasurement(docIndex, pageIndex, pageRef) {
|
|
1041
|
+
const cacheKey = `${docIndex}-${pageIndex}`
|
|
826
1042
|
const doc = this.pdfDocuments[docIndex]
|
|
827
1043
|
const pagesScale = doc.pagesScale[pageIndex] || 1
|
|
828
|
-
return
|
|
1044
|
+
return getCachedMeasurement(this._pageMeasurementCache, cacheKey, pageRef, pagesScale)
|
|
829
1045
|
},
|
|
830
1046
|
calculateOptimalScale(maxPageWidth) {
|
|
831
1047
|
const containerWidth = this.$el?.clientWidth || 0
|
|
@@ -869,9 +1085,8 @@ export default {
|
|
|
869
1085
|
if (Math.abs(optimalScale - this.scale) > 0.01) {
|
|
870
1086
|
this.scale = optimalScale
|
|
871
1087
|
this.visualScale = optimalScale
|
|
872
|
-
this.pdfDocuments.
|
|
873
|
-
|
|
874
|
-
})
|
|
1088
|
+
applyScaleToDocs(this.pdfDocuments, this.scale)
|
|
1089
|
+
this._pageMeasurementCache = {}
|
|
875
1090
|
this.cachePageBounds()
|
|
876
1091
|
}
|
|
877
1092
|
},
|
|
@@ -913,15 +1128,6 @@ export default {
|
|
|
913
1128
|
opacity: 0.7;
|
|
914
1129
|
pointer-events: none;
|
|
915
1130
|
}
|
|
916
|
-
.drag-ghost {
|
|
917
|
-
position: fixed;
|
|
918
|
-
opacity: 0.9;
|
|
919
|
-
pointer-events: none;
|
|
920
|
-
z-index: 10000;
|
|
921
|
-
transform-origin: top left;
|
|
922
|
-
transition: none;
|
|
923
|
-
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
|
924
|
-
}
|
|
925
1131
|
.overlay {
|
|
926
1132
|
position: absolute;
|
|
927
1133
|
top: 0;
|