瀏覽代碼

Attach PDF highlights to the viewer element (#7728)

GitOrigin-RevId: 918dfd8c43dfea4e64fbb5a1437ea8532cbac7ec
Alf Eaton 4 年之前
父節點
當前提交
37218bce59

+ 41 - 6
services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js

@@ -178,29 +178,64 @@ function PdfJsViewer({ url }) {
 
   // when highlights are created, build the highlight elements
   useEffect(() => {
+    const timers = []
+    let intersectionObserver
+
     if (pdfJsWrapper && highlights?.length) {
+      // watch for the highlight elements to scroll into view
+      intersectionObserver = new IntersectionObserver(
+        entries => {
+          for (const entry of entries) {
+            if (entry.isIntersecting) {
+              intersectionObserver.unobserve(entry.target)
+
+              // fade the element in and out
+              entry.target.style.opacity = '0.5'
+
+              timers.push(
+                window.setTimeout(() => {
+                  entry.target.style.opacity = '0'
+                }, 1000)
+              )
+            }
+          }
+        },
+        {
+          threshold: 1.0, // the whole element must be visible
+        }
+      )
+
       const elements = []
 
       for (const highlight of highlights) {
         try {
           const element = buildHighlightElement(highlight, pdfJsWrapper)
           elements.push(element)
+          intersectionObserver.observe(element)
         } catch (error) {
           // ignore invalid highlights
         }
       }
 
-      // scroll to the first highlighted element
-      elements[0]?.scrollIntoView({
-        block: 'nearest',
-        inline: 'start',
-        behavior: 'smooth',
-      })
+      const [firstElement] = elements
+
+      if (firstElement) {
+        // scroll to the first highlighted element
+        firstElement.scrollIntoView({
+          block: 'center',
+          inline: 'start',
+          behavior: 'smooth',
+        })
+      }
 
       return () => {
+        for (const timer of timers) {
+          window.clearTimeout(timer)
+        }
         for (const element of elements) {
           element.remove()
         }
+        intersectionObserver?.disconnect()
       }
     }
   }, [highlights, pdfJsWrapper])

+ 4 - 11
services/web/frontend/js/features/pdf-preview/util/highlights.js

@@ -15,8 +15,8 @@ export function buildHighlightElement(highlight, wrapper) {
   const [left, top, right, bottom] = wrapper.PDFJS.Util.normalizeRect(rect)
 
   const element = document.createElement('div')
-  element.style.left = Math.floor(left) + 'px'
-  element.style.top = Math.floor(top) + 'px'
+  element.style.left = Math.floor(pageView.div.offsetLeft + left) + 'px'
+  element.style.top = Math.floor(pageView.div.offsetTop + top + 10) + 'px'
   element.style.width = Math.ceil(right - left) + 'px'
   element.style.height = Math.ceil(bottom - top) + 'px'
   element.style.backgroundColor = 'rgba(255,255,0)'
@@ -25,16 +25,9 @@ export function buildHighlightElement(highlight, wrapper) {
   element.style.scrollMargin = '72px'
   element.style.pointerEvents = 'none'
   element.style.opacity = '0'
-  element.style.transition = 'opacity 0.5s'
-  pageView.div.appendChild(element)
+  element.style.transition = 'opacity 1s'
 
-  window.setTimeout(() => {
-    element.style.opacity = '0.3'
-
-    window.setTimeout(() => {
-      element.style.opacity = '0'
-    }, 1000)
-  }, 0)
+  wrapper.viewer.viewer.append(element)
 
   return element
 }