index.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import React, { useState, useEffect } from 'react';
  2. import OuterRect from '../OuterRect';
  3. import {
  4. svgPath,
  5. bezierCommand,
  6. controlPoint,
  7. line,
  8. } from '../../helpers/svgBezierCurve';
  9. import { pointCalc, rectCalcWithPoint, calcViewBox } from '../../helpers/brush';
  10. import { AnnotationContainer } from '../../global/otherStyled';
  11. import { SVG } from './styled';
  12. const Ink: React.FC<AnnotationElementPropsType> = ({
  13. obj_attr: { position, bdcolor, bdwidth = 0, transparency },
  14. isCollapse,
  15. onUpdate,
  16. viewport,
  17. scale,
  18. id,
  19. }: AnnotationElementPropsType) => {
  20. let points: PointType[][] = [];
  21. let tempRect: HTMLCoordinateType = { top: 0, left: 0, width: 0, height: 0 };
  22. const borderWidth = bdwidth * scale;
  23. points = pointCalc(position as PointType[][], viewport.height, scale);
  24. tempRect = rectCalcWithPoint(points, borderWidth);
  25. const [rect, setRect] = useState({ top: 0, left: 0, width: 0, height: 0 });
  26. const handleScaleOrMove = ({
  27. top,
  28. left,
  29. width = 0,
  30. height = 0,
  31. }: CoordType): void => {
  32. const xScaleRate = width / tempRect.width;
  33. const yScaleRate = height / tempRect.height;
  34. const xDistance = left - tempRect.left;
  35. const yDistance = tempRect.top - top;
  36. const newPosition = (position as PointType[][])[0].map((ele) => ({
  37. x: (ele.x + xDistance) * (xScaleRate || 1),
  38. y: (ele.y + yDistance) * (yScaleRate || 1),
  39. }));
  40. setRect({
  41. top,
  42. left,
  43. width,
  44. height,
  45. });
  46. onUpdate({
  47. position: [newPosition],
  48. });
  49. };
  50. useEffect(() => {
  51. const newPoints = pointCalc(
  52. position as PointType[][],
  53. viewport.height,
  54. scale,
  55. );
  56. const newRect = rectCalcWithPoint(newPoints, borderWidth);
  57. setRect(newRect);
  58. }, [viewport, scale]);
  59. return (
  60. <>
  61. <AnnotationContainer
  62. id={id}
  63. top={`${rect.top}px`}
  64. left={`${rect.left}px`}
  65. width={`${rect.width}px`}
  66. height={`${rect.height}px`}
  67. >
  68. <SVG viewBox={calcViewBox(tempRect, borderWidth)}>
  69. {points.map((ele: PointType[], index: number) => {
  70. const key = `${id}_path_${index}`;
  71. return (
  72. <path
  73. key={key}
  74. d={svgPath(
  75. ele as PointType[],
  76. bezierCommand(controlPoint(line, 0.2)),
  77. )}
  78. fill="none"
  79. stroke={bdcolor}
  80. strokeWidth={borderWidth}
  81. strokeOpacity={transparency}
  82. />
  83. );
  84. })}
  85. </SVG>
  86. </AnnotationContainer>
  87. {!isCollapse ? (
  88. <OuterRect
  89. top={rect.top}
  90. left={rect.left}
  91. width={rect.width}
  92. height={rect.height}
  93. onMove={handleScaleOrMove}
  94. onScale={handleScaleOrMove}
  95. />
  96. ) : (
  97. ''
  98. )}
  99. </>
  100. );
  101. };
  102. export default Ink;