瀏覽代碼

fix(annotation tools): optimization event. brush position. add svg attributs

RoyLiu 4 年之前
父節點
當前提交
4394d9f9d1

+ 5 - 1
components/Ink/index.tsx

@@ -107,7 +107,11 @@ const Ink: React.FC<AnnotationElementPropsType> = ({
         width={`${rect.width}px`}
         height={`${rect.height}px`}
       >
-        <SVG viewBox={calcViewBox(rect, borderWidth)}>
+        <SVG
+          width={rect.width + borderWidth}
+          height={rect.height + borderWidth}
+          viewBox={calcViewBox(rect, borderWidth)}
+        >
           {points.map((ele: PointType[], index: number) => {
             const key = `${id}_path_${index}`;
             return (

+ 3 - 0
components/Ink/styled.ts

@@ -4,6 +4,9 @@ export const SVG = styled.svg`
   pointer-events: none;
   user-select: none;
   touch-action: none;
+  position: absolute;
+  left: 0;
+  top: 0;
 `;
 
 export const PolyLine = styled('polyline')<{ isCovered: boolean }>`

+ 5 - 1
components/Line/index.tsx

@@ -148,7 +148,11 @@ const Line: React.FC<AnnotationElementPropsType> = ({
         width={`${rect.width}px`}
         height={`${rect.height}px`}
       >
-        <SVG viewBox={`${rect.left} ${rect.top} ${rect.width} ${rect.height}`}>
+        <SVG
+          width={rect.width}
+          height={rect.height}
+          viewBox={`${rect.left} ${rect.top} ${rect.width} ${rect.height}`}
+        >
           {is_arrow ? (
             <defs>
               <marker

+ 5 - 10
components/Page/index.tsx

@@ -120,22 +120,17 @@ const PageView: React.FC<Props> = ({
           ) : (
             ''
           )}
+          <Canvas
+            className="canvas"
+            viewBox={`0 0 ${viewport.width} ${viewport.height}`}
+          />
           <TextLayer
             data-id="text-layer"
-            style={{
-              display:
-                toolState === 'freehand' || toolState === 'shape'
-                  ? 'none'
-                  : 'block',
-            }}
+            disabledSelect={toolState === 'freehand' || toolState === 'shape'}
           />
           <AnnotationLayer data-id="annotation-layer">
             {annotations}
           </AnnotationLayer>
-          <Canvas
-            className="canvas"
-            viewBox={`0 0 ${viewport.width} ${viewport.height}`}
-          />
         </>
       )}
     </PageWrapper>

+ 5 - 2
components/Page/styled.ts

@@ -27,9 +27,10 @@ export const PdfCanvas = styled.canvas`
   display: block;
   width: 100%;
   height: 100%;
+  pointer-events: none;
 `;
 
-export const TextLayer = styled.div`
+export const TextLayer = styled.div<{ disabledSelect: boolean }>`
   position: absolute;
   left: 0;
   top: 0;
@@ -39,6 +40,7 @@ export const TextLayer = styled.div`
   overflow: hidden;
   opacity: 0.3;
   line-height: 1;
+  pointer-events: ${(props) => (props.disabledSelect ? 'none' : 'auto')};
 
   & > span {
     color: transparent;
@@ -73,6 +75,7 @@ export const WatermarkLayer = styled.div`
   display: flex;
   justify-content: center;
   align-items: center;
+  pointer-events: none;
 `;
 
 export const Inner = styled.div`
@@ -84,7 +87,7 @@ export const Inner = styled.div`
 `;
 
 export const Canvas = styled.svg`
-  display: none;
+  display: block;
   position: absolute;
   top: 0;
   left: 0;

+ 1 - 1
components/SvgShapeElement/index.tsx

@@ -21,7 +21,7 @@ const SvgShapeElement: React.FC<Props> = ({
   fcolor,
   ftransparency,
 }: Props) => (
-  <svg viewBox={`0 0 ${width} ${height}`}>
+  <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}>
     {shape === 'Circle' ? (
       <ellipse
         cx={width / 2}

+ 9 - 3
containers/FreeTextTool.tsx

@@ -99,9 +99,15 @@ const HighlightTool: React.FC<Props> = ({
 
   useEffect(() => {
     const pdfViewer = document.getElementById('pdf_viewer') as HTMLDivElement;
-    if (isActive && pdfViewer) {
-      pdfViewer.addEventListener('mousedown', handleMouseDown);
-      pdfViewer.addEventListener('touchstart', handleMouseDown);
+
+    if (pdfViewer) {
+      if (isActive) {
+        pdfViewer.addEventListener('mousedown', handleMouseDown);
+        pdfViewer.addEventListener('touchstart', handleMouseDown);
+      } else {
+        pdfViewer.removeEventListener('mousedown', handleMouseDown);
+        pdfViewer.removeEventListener('touchstart', handleMouseDown);
+      }
     }
 
     return (): void => {

+ 7 - 8
containers/FreehandTool.tsx

@@ -14,7 +14,6 @@ import {
   line,
 } from '../helpers/svgBezierCurve';
 
-import { getAbsoluteCoordinate } from '../helpers/position';
 import {
   parseAnnotationObject,
   appendUserIdAndDate,
@@ -61,12 +60,11 @@ const FreehandTool: React.FC<Props> = ({ title, isActive, onClick }: Props) => {
     if (pageEle.hasAttribute('data-page-num')) {
       setRef(pageEle);
       const pageNum = pageEle.getAttribute('data-page-num') || '0';
-      const coordinate = getAbsoluteCoordinate(pageEle, event);
+
       setData((current) => ({
         ...current,
         page: parseInt(pageNum, 10),
       }));
-      setPath([coordinate]);
     }
   };
 
@@ -124,8 +122,6 @@ const FreehandTool: React.FC<Props> = ({ title, isActive, onClick }: Props) => {
 
     if (path.length) {
       if (pageEle && canvas) {
-        canvas.style.display = 'block';
-
         if (pathEle) {
           const d = svgPath(path, bezierCommand(controlPoint(line, 0.2)));
           pathEle.setAttribute('d', d);
@@ -142,7 +138,6 @@ const FreehandTool: React.FC<Props> = ({ title, isActive, onClick }: Props) => {
         }
       }
     } else if (canvas && pathEle) {
-      canvas.style.display = 'none';
       canvas.removeChild(pathEle);
       pathEle = null;
     }
@@ -169,8 +164,12 @@ const FreehandTool: React.FC<Props> = ({ title, isActive, onClick }: Props) => {
   useEffect(() => {
     const pdfViewer = document.getElementById('pdf_viewer') as HTMLDivElement;
 
-    if (isActive && pdfViewer) {
-      subscribeEvent();
+    if (pdfViewer) {
+      if (isActive) {
+        subscribeEvent();
+      } else {
+        unsubscribeEvent();
+      }
     }
 
     return (): void => {

+ 26 - 24
containers/HighlightTools.tsx

@@ -67,8 +67,6 @@ const HighlightTools: React.FC<Props> = ({
             ) as HTMLElement;
           }
           if (textLayer) {
-            textLayer.style.zIndex = '10';
-
             const newMarkup = getMarkupWithSelection({
               ...data,
               scale,
@@ -83,10 +81,6 @@ const HighlightTools: React.FC<Props> = ({
         }
       }
       if (selection?.isCollapsed) {
-        if (textLayer) {
-          textLayer.style.zIndex = '0';
-        }
-
         setCurrentId('');
       }
     },
@@ -124,29 +118,37 @@ const HighlightTools: React.FC<Props> = ({
     }
   }, [annotations, data, scale, currentId]);
 
+  const subscribeEvent = () => {
+    document.addEventListener('mousedown', handleDown);
+    document.addEventListener('mousemove', handleMove);
+    document.addEventListener('mouseup', handleUp);
+    document.addEventListener('selectstart', handleSelectStart);
+    document.addEventListener('touchstart', handleDown);
+    document.addEventListener('touchmove', handleMove);
+    document.addEventListener('touchend', handleUp);
+    document.addEventListener('selectionchange', handleSelectChange);
+  };
+
+  const unsubscribeEvent = () => {
+    document.removeEventListener('mousedown', handleDown);
+    document.removeEventListener('mousemove', handleMove);
+    document.removeEventListener('mouseup', handleUp);
+    document.removeEventListener('selectstart', handleSelectStart);
+    document.removeEventListener('touchstart', handleDown);
+    document.removeEventListener('touchmove', handleMove);
+    document.removeEventListener('touchend', handleUp);
+    document.removeEventListener('selectionchange', handleSelectChange);
+  };
+
   useEffect(() => {
     if (isActive) {
-      document.addEventListener('mousedown', handleDown);
-      document.addEventListener('mousemove', handleMove);
-      document.addEventListener('mouseup', handleUp);
-      document.addEventListener('selectstart', handleSelectStart);
-      document.addEventListener('touchstart', handleDown);
-      document.addEventListener('touchmove', handleMove);
-      document.addEventListener('touchend', handleUp);
-      document.addEventListener('selectionchange', handleSelectChange);
-    } else if (textLayer) {
-      textLayer.style.zIndex = '0';
+      subscribeEvent();
+    } else {
+      unsubscribeEvent();
     }
 
     return (): void => {
-      document.removeEventListener('mousedown', handleDown);
-      document.removeEventListener('mousemove', handleMove);
-      document.removeEventListener('mouseup', handleUp);
-      document.removeEventListener('selectstart', handleSelectStart);
-      document.removeEventListener('touchstart', handleDown);
-      document.removeEventListener('touchmove', handleMove);
-      document.removeEventListener('touchend', handleUp);
-      document.removeEventListener('selectionchange', handleSelectChange);
+      unsubscribeEvent();
     };
   }, [isActive, handleUp, handleSelectChange]);
 

+ 6 - 5
containers/ShapeTool.tsx

@@ -155,8 +155,12 @@ const Shape: React.FC<Props> = ({ title, isActive, onClick }: Props) => {
   useEffect(() => {
     const pdfViewer = document.getElementById('pdf_viewer') as HTMLDivElement;
 
-    if (isActive && pdfViewer) {
-      subscribeEvent();
+    if (pdfViewer) {
+      if (isActive) {
+        subscribeEvent();
+      } else {
+        unsubscribeEvent();
+      }
     }
 
     return (): void => {
@@ -188,8 +192,6 @@ const Shape: React.FC<Props> = ({ title, isActive, onClick }: Props) => {
     const canvas = pageEle?.getElementsByClassName('canvas')[0] as HTMLElement;
 
     if (endPoint.x && endPoint.y) {
-      canvas.style.display = 'block';
-
       if (shapeEle) {
         const { top, left, right, bottom } = convertPosition(
           ANNOTATION_TYPE[data.shape],
@@ -240,7 +242,6 @@ const Shape: React.FC<Props> = ({ title, isActive, onClick }: Props) => {
         canvas.appendChild(shapeEle);
       }
     } else if (canvas && shapeEle) {
-      canvas.style.display = 'none';
       canvas.removeChild(shapeEle);
       shapeEle = null;
     }

+ 8 - 3
containers/StickyNoteTool.tsx

@@ -68,9 +68,14 @@ const StickyNoteTool: React.FC<Props> = ({
   useEffect(() => {
     const pdfViewer = document.getElementById('pdf_viewer') as HTMLDivElement;
 
-    if (isActive && pdfViewer) {
-      window.addEventListener('touchstart', handleMouseDown);
-      window.addEventListener('mousedown', handleMouseDown);
+    if (pdfViewer) {
+      if (isActive) {
+        window.addEventListener('mousedown', handleMouseDown);
+        window.addEventListener('touchstart', handleMouseDown);
+      } else {
+        window.removeEventListener('mousedown', handleMouseDown);
+        window.removeEventListener('touchstart', handleMouseDown);
+      }
     }
 
     return (): void => {

+ 5 - 6
helpers/brush.ts

@@ -78,10 +78,10 @@ export const rectCalcWithPoint = (
   const bottom = Math.max(...yArray);
   const right = Math.max(...xArray);
   return {
-    top,
-    left,
-    width: right - left + borderWidth,
-    height: bottom - top + borderWidth,
+    top: top - borderWidth,
+    left: left - borderWidth,
+    width: right - left + borderWidth * 2,
+    height: bottom - top + borderWidth * 2,
   };
 };
 
@@ -89,8 +89,7 @@ export const calcViewBox = (
   { top, left, width, height }: HTMLCoordinateType,
   borderWidth: number,
 ): string => {
-  const distance = borderWidth / 2;
   return `
-  ${left - distance} ${top - distance} ${width + distance} ${height + distance}
+  ${left} ${top} ${width + borderWidth} ${height + borderWidth}
 `;
 };