index.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import React from 'react';
  2. import {
  3. AnnotationElementPropsType,
  4. PointType,
  5. HTMLCoordinateType,
  6. CoordType,
  7. UpdateData,
  8. } from '../../constants/type';
  9. import OuterRect from '../OuterRect';
  10. import {
  11. svgPath,
  12. bezierCommand,
  13. controlPoint,
  14. line,
  15. } from '../../helpers/svgBezierCurve';
  16. import { AnnotationContainer } from '../../global/otherStyled';
  17. import { SVG } from './styled';
  18. const Ink: React.SFC<AnnotationElementPropsType> = ({
  19. obj_attr: { position, bdcolor, bdwidth = 0, transparency },
  20. isCollapse,
  21. onUpdate,
  22. viewport,
  23. scale,
  24. id,
  25. }: AnnotationElementPropsType) => {
  26. const pointCalc = (
  27. _points: PointType[][],
  28. h: number,
  29. s: number
  30. ): PointType[][] => {
  31. const reducer = _points.reduce(
  32. (acc: PointType[][], cur: PointType[]): PointType[][] => {
  33. const p = cur.map((point: PointType) => ({
  34. x: point.x * s,
  35. y: h - point.y * s,
  36. }));
  37. acc.push(p);
  38. return acc;
  39. },
  40. []
  41. );
  42. return reducer;
  43. };
  44. const rectCalcWithPoint = (
  45. pointsGroup: PointType[][],
  46. borderWidth: number
  47. ): HTMLCoordinateType => {
  48. const xArray: number[] = [];
  49. const yArray: number[] = [];
  50. pointsGroup[0].forEach((point: PointType) => {
  51. xArray.push(point.x);
  52. yArray.push(point.y);
  53. });
  54. const top = Math.min(...yArray);
  55. const left = Math.min(...xArray);
  56. const bottom = Math.max(...yArray);
  57. const right = Math.max(...xArray);
  58. return {
  59. top,
  60. left,
  61. width: right - left + borderWidth,
  62. height: bottom - top + borderWidth,
  63. };
  64. };
  65. const borderWidth = bdwidth * scale;
  66. const annotPoints = pointCalc(
  67. position as PointType[][],
  68. viewport.height,
  69. scale
  70. );
  71. const annotRect = rectCalcWithPoint(annotPoints, borderWidth);
  72. const scaleOrMoveCalc = (
  73. rect: HTMLCoordinateType,
  74. updatePoints: (data: UpdateData) => void
  75. ) => ({ top, left, width = 0, height = 0 }: CoordType): void => {
  76. const xScaleRate = width / rect.width;
  77. const yScaleRate = height / rect.height;
  78. const xDistance = left - rect.left;
  79. const yDistance = rect.top - top;
  80. const newPosition = (position as PointType[][])[0].map(ele => ({
  81. x: (ele.x + xDistance) * (xScaleRate || 1),
  82. y: (ele.y + yDistance) * (yScaleRate || 1),
  83. }));
  84. updatePoints({
  85. position: [newPosition],
  86. });
  87. };
  88. const handleScaleOrMove = scaleOrMoveCalc(annotRect, onUpdate);
  89. const calcViewBox = (
  90. { top, left, width, height }: HTMLCoordinateType,
  91. _borderWidth: number
  92. ): string => `
  93. ${left - _borderWidth / 2} ${top - _borderWidth / 2} ${width} ${height}
  94. `;
  95. return (
  96. <>
  97. <AnnotationContainer
  98. top={`${annotRect.top}px`}
  99. left={`${annotRect.left}px`}
  100. width={`${annotRect.width}px`}
  101. height={`${annotRect.height}px`}
  102. >
  103. <SVG viewBox={calcViewBox(annotRect, bdwidth * scale)}>
  104. {annotPoints.map((ele: PointType[], index: number) => {
  105. const key = `${id}_path_${index}`;
  106. return (
  107. <path
  108. key={key}
  109. d={svgPath(
  110. ele as PointType[],
  111. bezierCommand(controlPoint(line, 0.2))
  112. )}
  113. fill="none"
  114. stroke={bdcolor}
  115. strokeWidth={bdwidth * scale}
  116. strokeOpacity={transparency}
  117. />
  118. );
  119. })}
  120. </SVG>
  121. </AnnotationContainer>
  122. {!isCollapse ? (
  123. <OuterRect
  124. top={annotRect.top}
  125. left={annotRect.left}
  126. width={annotRect.width}
  127. height={annotRect.height}
  128. onMove={handleScaleOrMove}
  129. onScale={handleScaleOrMove}
  130. />
  131. ) : (
  132. ''
  133. )}
  134. </>
  135. );
  136. };
  137. export default Ink;