Skip to content

Commit 4ced717

Browse files
committed
Fixed annotations not displayed in two-page spread for PDFs
1 parent 2bf0cec commit 4ced717

1 file changed

Lines changed: 37 additions & 1 deletion

File tree

fixed-layout.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,14 @@ export class FixedLayout extends HTMLElement {
235235
if (!iframe) return
236236
if (onZoom) {
237237
const p = onZoom({ doc: frame.iframe.contentDocument, scale, pageColors: this.#pageColors })
238-
if (p?.then) renderPromises.push(p)
238+
if (p?.then) {
239+
// onZoom (e.g. pdf.js) may rebuild the text layer DOM,
240+
// invalidating Range objects stored in the overlayer. After
241+
// the rebuild, re-emit create-overlayer so listeners can
242+
// re-anchor annotations against the fresh DOM.
243+
const refreshed = p.then(() => this.#refreshOverlayerForFrame(frame))
244+
renderPromises.push(refreshed)
245+
}
239246
}
240247
const iframeScale = onZoom ? scale : 1
241248
const zoomedOut = this.#scaleFactor < 1.0
@@ -1028,6 +1035,35 @@ export class FixedLayout extends HTMLElement {
10281035
? parseInt(frame.iframe.dataset.sectionIndex) : undefined
10291036
if (idx != null) this.#overlayers.delete(idx)
10301037
}
1038+
// Drop a frame's overlayer and re-emit create-overlayer so listeners can
1039+
// re-add annotations. Called after a text layer rebuild (e.g. pdf.js
1040+
// onZoom) which invalidates Range objects stored in the overlayer.
1041+
#refreshOverlayerForFrame(frame) {
1042+
if (!frame?.iframe) return
1043+
const index = frame.iframe.dataset.sectionIndex != null
1044+
? parseInt(frame.iframe.dataset.sectionIndex) : undefined
1045+
if (index == null) return
1046+
const stale = this.#overlayers.get(index)
1047+
if (!stale) return
1048+
// Only refresh for frames currently visible; hidden frames keep their
1049+
// overlayer untouched until they are shown again.
1050+
const isVisible = frame.element?.parentNode
1051+
&& frame.element.style.visibility !== 'hidden'
1052+
if (!isVisible) return
1053+
stale.element?.remove()
1054+
this.#overlayers.delete(index)
1055+
const doc = frame.iframe.contentDocument
1056+
if (!doc) return
1057+
this.dispatchEvent(new CustomEvent('create-overlayer', {
1058+
detail: {
1059+
doc, index,
1060+
attach: overlayer => {
1061+
this.#overlayers.set(index, overlayer)
1062+
frame.element.append(overlayer.element)
1063+
},
1064+
},
1065+
}))
1066+
}
10311067
async select(target) {
10321068
await this.goTo(target)
10331069
// TODO

0 commit comments

Comments
 (0)