diff --git a/services/web/frontend/js/features/pdf-preview/util/highlights.js b/services/web/frontend/js/features/pdf-preview/util/highlights.js index a2da6b2621..2fb204ac11 100644 --- a/services/web/frontend/js/features/pdf-preview/util/highlights.js +++ b/services/web/frontend/js/features/pdf-preview/util/highlights.js @@ -1,28 +1,55 @@ import { PDFJS } from '@/features/pdf-preview/util/pdf-js' export function buildHighlightElement(highlight, viewer) { - const pageView = viewer.getPageView(highlight.page - 1) + const { viewport, div } = viewer.getPageView(highlight.page - 1) - const viewport = pageView.viewport + // page coordinates from synctex + const rectangle = { + left: highlight.h, + right: highlight.h + highlight.width, + top: highlight.v, + bottom: highlight.v + highlight.height, + } - const height = viewport.viewBox[3] + // needed because PDF page origin is at the bottom left + const viewBoxHeight = viewport.viewBox[3] + 10 - const rect = viewport.convertToViewportRectangle([ - highlight.h, // xMin - height - (highlight.v + highlight.height) + 10, // yMin - highlight.h + highlight.width, // xMax - height - highlight.v + 10, // yMax + // account for scaling + const viewportRectangle = viewport.convertToViewportRectangle([ + rectangle.left, + viewBoxHeight - rectangle.bottom, + rectangle.right, + viewBoxHeight - rectangle.top, ]) - const [left, top, right, bottom] = PDFJS.Util.normalizeRect(rect) + // flip top/bottom, left/right if needed + const normalizedRectangle = PDFJS.Util.normalizeRect(viewportRectangle) + + const [left, top, right, bottom] = normalizedRectangle + + // restrict to within the page container + const clampedRectangle = { + left: Math.max(left, 0), + right: Math.min(right, div.clientWidth), + top: Math.max(top, 0), + bottom: Math.min(bottom, div.clientHeight), + } + + // convert to screen positions + const positions = { + left: div.offsetLeft + clampedRectangle.left, + right: div.offsetLeft + clampedRectangle.right, + top: div.offsetTop + clampedRectangle.top, + bottom: div.offsetTop + clampedRectangle.bottom, + } const element = document.createElement('div') - element.style.left = Math.floor(pageView.div.offsetLeft + left) + 'px' - element.style.top = Math.floor(pageView.div.offsetTop + top) + 'px' - element.style.width = Math.ceil(right - left) + 'px' - element.style.height = Math.ceil(bottom - top) + 'px' - element.style.backgroundColor = 'rgba(255,255,0)' element.style.position = 'absolute' + element.style.left = Math.floor(positions.left) + 'px' + element.style.top = Math.floor(positions.top) + 'px' + element.style.width = Math.floor(positions.right - positions.left) + 'px' + element.style.height = Math.floor(positions.bottom - positions.top) + 'px' + element.style.backgroundColor = 'rgb(255,255,0)' element.style.display = 'inline-block' element.style.scrollMargin = '72px' element.style.pointerEvents = 'none'