position.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import _ from 'lodash';
  2. export const rectCalc = (
  3. position: PositionType,
  4. viewHeight: number,
  5. scale: number,
  6. ): HTMLCoordinateType => ({
  7. top: viewHeight - position.top * scale,
  8. left: position.left * scale,
  9. width: (position.right - position.left) * scale,
  10. height: (position.top - position.bottom) * scale,
  11. });
  12. export const getPosition = (
  13. type: string,
  14. element: HTMLElement,
  15. ): AnnotationPositionType => {
  16. const attributes = element.attributes as ElementAttributeType;
  17. switch (type) {
  18. case 'Ink': {
  19. const gestures: PointType[][] = [];
  20. const nodes: NodeListOf<ChildNode> = element.childNodes[1].childNodes;
  21. const nodeList = Array.prototype.slice.call(nodes);
  22. nodeList.forEach((ele: HTMLElement) => {
  23. if (ele.tagName === 'gesture') {
  24. const points: PointType[] = [];
  25. const gestureArray = (ele.innerHTML || ele.textContent || '').split(
  26. ';',
  27. );
  28. gestureArray.forEach((ele1: string) => {
  29. const pointArr = ele1.split(',');
  30. const point = {
  31. x: parseInt(pointArr[0], 10),
  32. y: parseInt(pointArr[1], 10),
  33. };
  34. points.push(point);
  35. });
  36. gestures.push(points);
  37. }
  38. });
  39. return gestures;
  40. }
  41. case 'Line': {
  42. const start = attributes.start.value.split(',');
  43. const end = attributes.end.value.split(',');
  44. return {
  45. start: {
  46. x: parseInt(start[0], 10),
  47. y: parseInt(start[1], 10),
  48. },
  49. end: {
  50. x: parseInt(end[0], 10),
  51. y: parseInt(end[1], 10),
  52. },
  53. };
  54. }
  55. case 'Square':
  56. case 'Circle': {
  57. const width = parseInt(attributes.width.value, 10);
  58. const rect = attributes.rect.value.split(',');
  59. return {
  60. left: parseInt(rect[0], 10) + width,
  61. bottom: parseInt(rect[1], 10) + width,
  62. right: parseInt(rect[2], 10) - width,
  63. top: parseInt(rect[3], 10) - width,
  64. };
  65. }
  66. case 'Text':
  67. case 'FreeText':
  68. case 'textfield':
  69. case 'checkbox': {
  70. const rect = attributes.rect.value.split(',');
  71. return {
  72. left: parseInt(rect[0], 10),
  73. bottom: parseInt(rect[1], 10),
  74. right: parseInt(rect[2], 10),
  75. top: parseInt(rect[3], 10),
  76. };
  77. }
  78. case 'Highlight':
  79. case 'Underline':
  80. case 'Squiggly':
  81. case 'StrikeOut': {
  82. let tempArray: string[][] = [];
  83. if (attributes.coords) {
  84. const coords = attributes.coords.value.split(',');
  85. tempArray = _.chunk(coords, 8);
  86. }
  87. const position = tempArray.map((ele: string[]) => ({
  88. left: parseInt(ele[0], 10),
  89. bottom: parseInt(ele[1], 10),
  90. right: parseInt(ele[2], 10),
  91. top: parseInt(ele[5], 10),
  92. }));
  93. return position;
  94. }
  95. default:
  96. return {
  97. left: 0,
  98. bottom: 0,
  99. right: 0,
  100. top: 0,
  101. };
  102. }
  103. };
  104. export const parsePositionForBackend = (
  105. type: string,
  106. position: AnnotationPositionType,
  107. pageHeight: number,
  108. scale: number,
  109. ): AnnotationPositionType => {
  110. switch (type) {
  111. case 'Highlight':
  112. case 'Underline':
  113. case 'Squiggly':
  114. case 'StrikeOut': {
  115. const positionArray = position as PositionType[];
  116. return positionArray.map((ele: PositionType) => ({
  117. left: ele.left / scale,
  118. bottom: (pageHeight - ele.bottom) / scale,
  119. right: ele.right / scale,
  120. top: (pageHeight - ele.top) / scale,
  121. }));
  122. }
  123. case 'Square':
  124. case 'Circle':
  125. case 'FreeText':
  126. case 'Text':
  127. case 'Image':
  128. case 'textfield':
  129. case 'checkbox': {
  130. const normalPosition = position as PositionType;
  131. return {
  132. left: normalPosition.left / scale,
  133. bottom: (pageHeight - normalPosition.bottom) / scale,
  134. right: normalPosition.right / scale,
  135. top: (pageHeight - normalPosition.top) / scale,
  136. };
  137. }
  138. case 'Line': {
  139. const { start, end } = position as LinePositionType;
  140. return {
  141. start: {
  142. x: start.x / scale,
  143. y: (pageHeight - start.y) / scale,
  144. },
  145. end: {
  146. x: end.x / scale,
  147. y: (pageHeight - end.y) / scale,
  148. },
  149. };
  150. }
  151. case 'Ink': {
  152. if (Array.isArray(position)) {
  153. const points = position as PointType[][];
  154. return [
  155. points[0].map((point) => ({
  156. x: point.x / scale,
  157. y: (pageHeight - point.y) / scale,
  158. })),
  159. ];
  160. }
  161. const point = position as PointType;
  162. return {
  163. x: point.x / scale,
  164. y: (pageHeight - point.y) / scale,
  165. };
  166. }
  167. default:
  168. return {
  169. left: 0,
  170. bottom: 0,
  171. right: 0,
  172. top: 0,
  173. };
  174. }
  175. };
  176. type GetAbsoluteCoordinateType = (
  177. parentElement: HTMLElement | SVGSVGElement | SVGCircleElement | null,
  178. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  179. clickEvent: any,
  180. ) => { x: number; y: number };
  181. export const getAbsoluteCoordinate: GetAbsoluteCoordinateType = (
  182. parentElement,
  183. clickEvent,
  184. ) => {
  185. if (!parentElement) return { x: 0, y: 0 };
  186. let pageX = 0;
  187. let pageY = 0;
  188. if (clickEvent.touches) {
  189. const touch = clickEvent.touches[0];
  190. ({ pageX, pageY } = touch);
  191. } else {
  192. ({ pageX, pageY } = clickEvent);
  193. }
  194. const rect = parentElement.getBoundingClientRect();
  195. const offsetX = window.pageXOffset || window.scrollX || 0;
  196. const offsetY = window.pageYOffset || window.scrollY || 0;
  197. const coordinate = {
  198. x: pageX - rect.left - offsetX,
  199. y: pageY - rect.top - offsetY,
  200. };
  201. return coordinate;
  202. };
  203. export default rectCalc;