highlights.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { PDFJS } from '@/features/pdf-preview/util/pdf-js'
  2. export function buildHighlightElement(highlight, viewer) {
  3. const { viewport, div } = viewer.getPageView(highlight.page - 1)
  4. // page coordinates from synctex
  5. const rectangle = {
  6. left: highlight.h,
  7. right: highlight.h + highlight.width,
  8. top: highlight.v,
  9. bottom: highlight.v + highlight.height,
  10. }
  11. // needed because PDF page origin is at the bottom left
  12. const viewBoxHeight = viewport.viewBox[3] + 10
  13. // account for scaling
  14. const viewportRectangle = viewport.convertToViewportRectangle([
  15. rectangle.left,
  16. viewBoxHeight - rectangle.bottom,
  17. rectangle.right,
  18. viewBoxHeight - rectangle.top,
  19. ])
  20. // flip top/bottom, left/right if needed
  21. const normalizedRectangle = PDFJS.Util.normalizeRect(viewportRectangle)
  22. const [left, top, right, bottom] = normalizedRectangle
  23. // restrict to within the page container
  24. const clampedRectangle = {
  25. left: Math.max(left, 0),
  26. right: Math.min(right, div.clientWidth),
  27. top: Math.max(top, 0),
  28. bottom: Math.min(bottom, div.clientHeight),
  29. }
  30. // convert to screen positions
  31. const positions = {
  32. left: div.offsetLeft + clampedRectangle.left,
  33. right: div.offsetLeft + clampedRectangle.right,
  34. top: div.offsetTop + clampedRectangle.top,
  35. bottom: div.offsetTop + clampedRectangle.bottom,
  36. }
  37. const element = document.createElement('div')
  38. element.style.position = 'absolute'
  39. element.style.left = Math.floor(positions.left) + 'px'
  40. element.style.top = Math.floor(positions.top) + 'px'
  41. element.style.width = Math.floor(positions.right - positions.left) + 'px'
  42. element.style.height = Math.floor(positions.bottom - positions.top) + 'px'
  43. element.style.backgroundColor = 'rgb(255,255,0)'
  44. element.style.display = 'inline-block'
  45. element.style.scrollMargin = '72px'
  46. element.style.pointerEvents = 'none'
  47. element.style.opacity = '0'
  48. element.style.transition = 'opacity 1s'
  49. viewer.viewer?.append(element)
  50. return element
  51. }