position.ts 5.3 KB

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