index.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import React from 'react';
  2. import { v4 as uuidv4 } from 'uuid';
  3. import Outer from '../OuterRectForLine';
  4. import {
  5. AnnotationElementPropsType,
  6. LinePositionType,
  7. HTMLCoordinateType,
  8. } from '../../constants/type';
  9. import { parsePositionForBackend } from '../../helpers/position';
  10. import { AnnotationContainer } from '../../global/otherStyled';
  11. const Note: React.SFC<AnnotationElementPropsType> = ({
  12. obj_type,
  13. obj_attr,
  14. scale,
  15. viewport,
  16. isCollapse,
  17. onUpdate,
  18. }: AnnotationElementPropsType) => {
  19. const {
  20. bdcolor = '',
  21. bdwidth = 0,
  22. transparency = 0,
  23. position,
  24. is_arrow,
  25. } = obj_attr;
  26. const uuid = uuidv4();
  27. const getActualPoint = (
  28. { start, end }: LinePositionType,
  29. h: number,
  30. s: number
  31. ): LinePositionType => {
  32. const x1 = start.x * scale;
  33. const y1 = h - start.y * s;
  34. const x2 = end.x * scale;
  35. const y2 = h - end.y * s;
  36. return {
  37. start: {
  38. x: x1,
  39. y: y1,
  40. },
  41. end: {
  42. x: x2,
  43. y: y2,
  44. },
  45. };
  46. };
  47. const pointCalc = (
  48. { start, end }: LinePositionType,
  49. borderWidth: number
  50. ): LinePositionType => ({
  51. start: {
  52. x: start.x + borderWidth,
  53. y: start.y + borderWidth,
  54. },
  55. end: {
  56. x: end.x + borderWidth,
  57. y: end.y + borderWidth,
  58. },
  59. });
  60. const rectCalc = (
  61. { start, end }: LinePositionType,
  62. h: number,
  63. s: number
  64. ): HTMLCoordinateType => {
  65. const startY = h - start.y * s;
  66. const endY = h - end.y * s;
  67. return {
  68. top: startY > endY ? endY : startY,
  69. left: start.x > end.x ? end.x * s : start.x * s,
  70. width: Math.abs((end.x - start.x) * s),
  71. height: Math.abs(endY - startY),
  72. };
  73. };
  74. const actualbdwidth = bdwidth * scale;
  75. const annotRect = rectCalc(
  76. position as LinePositionType,
  77. viewport.height,
  78. scale
  79. );
  80. const { start, end } = getActualPoint(
  81. position as LinePositionType,
  82. viewport.height,
  83. scale
  84. );
  85. const { start: completeStart, end: completeEnd } = pointCalc(
  86. { start, end } as LinePositionType,
  87. actualbdwidth
  88. );
  89. const actualWidth = annotRect.width + actualbdwidth + 15;
  90. const actualHeight = annotRect.height + actualbdwidth + 15;
  91. const handleMove = ({
  92. start: moveStart,
  93. end: moveEnd,
  94. }: LinePositionType): void => {
  95. const newPosition = {
  96. start: {
  97. x: moveStart.x,
  98. y: moveStart.y,
  99. },
  100. end: {
  101. x: moveEnd.x,
  102. y: moveEnd.y,
  103. },
  104. };
  105. onUpdate({
  106. position: parsePositionForBackend(
  107. obj_type,
  108. newPosition,
  109. viewport.height,
  110. scale
  111. ),
  112. });
  113. };
  114. return (
  115. <>
  116. <AnnotationContainer
  117. top={`${annotRect.top}px`}
  118. left={`${annotRect.left}px`}
  119. width={`${actualWidth}px`}
  120. height={`${actualHeight}px`}
  121. >
  122. <svg
  123. width={`${actualWidth}px`}
  124. height={`${actualHeight}px`}
  125. viewBox={`${annotRect.left} ${annotRect.top} ${actualWidth} ${actualHeight}`}
  126. >
  127. {is_arrow ? (
  128. <defs>
  129. <marker
  130. id={uuid}
  131. markerWidth={actualbdwidth * 2}
  132. markerHeight={actualbdwidth * 3}
  133. refX={3}
  134. refY={2}
  135. orient="auto"
  136. markerUnits="strokeWidth"
  137. >
  138. <polyline
  139. points="0.25,0.5 3.25,2 0.25,3.5 3.25,2 -0.25,2"
  140. stroke={bdcolor}
  141. strokeWidth={1}
  142. fill="none"
  143. strokeDasharray={100}
  144. />
  145. </marker>
  146. </defs>
  147. ) : null}
  148. <line
  149. x1={completeStart.x}
  150. y1={completeStart.y}
  151. x2={completeEnd.x}
  152. y2={completeEnd.y}
  153. stroke={bdcolor}
  154. strokeWidth={actualbdwidth}
  155. strokeOpacity={transparency}
  156. markerEnd={is_arrow ? `url(#${uuid})` : ''}
  157. />
  158. </svg>
  159. </AnnotationContainer>
  160. {!isCollapse ? (
  161. <Outer
  162. top={annotRect.top}
  163. left={annotRect.left}
  164. width={actualWidth}
  165. height={actualHeight}
  166. start={start}
  167. end={end}
  168. completeStart={completeStart}
  169. completeEnd={completeEnd}
  170. onMove={handleMove}
  171. />
  172. ) : (
  173. ''
  174. )}
  175. </>
  176. );
  177. };
  178. export default Note;