sys-line.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import { nextTick } from 'vue'
  2. import type { IDoneJson, IDoneJsonBinfo } from '../store/types'
  3. import { getRectCenterCoordinate, getRectCoordinate, rotatePoint } from '../utils'
  4. import { normalizeLineGeometry } from '../utils/line-interaction'
  5. /**
  6. * 更新系统连线实际宽高
  7. * @param sys_lines
  8. * @param scale
  9. */
  10. export const useUpdateSysLineRect = (
  11. sys_lines: IDoneJson[],
  12. canvasDom: HTMLElement,
  13. scale: number
  14. ) => {
  15. sys_lines.forEach((f) => {
  16. const itemRect = document.querySelector(`#${f.id} g .real`)!.getBoundingClientRect()
  17. const canvas_area_bounding_info = canvasDom!.getBoundingClientRect()
  18. const new_left = (itemRect?.left - canvas_area_bounding_info?.left) / scale
  19. const new_top = (itemRect?.top - canvas_area_bounding_info?.top) / scale
  20. const move_x = new_left - f.binfo.left
  21. const move_y = new_top - f.binfo.top
  22. const normalized_geometry = normalizeLineGeometry(
  23. {
  24. left: new_left,
  25. top: new_top,
  26. width: itemRect.width / scale,
  27. height: itemRect.height / scale
  28. },
  29. f.props.point_position.val.map((m: { x: number; y: number }) => ({
  30. x: m.x - move_x,
  31. y: m.y - move_y
  32. }))
  33. )
  34. Object.assign(f.binfo, normalized_geometry.binfo)
  35. f.props.point_position = {
  36. ...f.props.point_position,
  37. val: normalized_geometry.points
  38. }
  39. })
  40. }
  41. /**
  42. * 更新系统连线
  43. * @param sys_lines 要更新的连线列表
  44. * @param done_json 所有组件信息
  45. * @param canvasDom 画布dom
  46. * @param scale 画布缩放
  47. */
  48. export const useUpdateSysLine = (
  49. sys_lines: IDoneJson[],
  50. done_json: IDoneJson[],
  51. canvasDom: HTMLElement,
  52. scale: number,
  53. move_binfo?: IDoneJsonBinfo & { id: string }
  54. ) => {
  55. const temp_done_json = [...done_json]
  56. sys_lines.forEach((f) => {
  57. if (!f.props.bind_anchors.val.start && !f.props.bind_anchors.val.end) {
  58. return
  59. }
  60. const itemRect = document.querySelector(`#${f.id} g .real`)!.getBoundingClientRect()
  61. const canvas_area_bounding_info = canvasDom!.getBoundingClientRect()
  62. const new_left = (itemRect?.left - canvas_area_bounding_info?.left) / scale
  63. const new_top = (itemRect?.top - canvas_area_bounding_info?.top) / scale
  64. // 处理起点绑定
  65. if (f.props.bind_anchors.val.start) {
  66. // 根据id和类型找到锚点坐标
  67. const find_item = temp_done_json.find((m) => m.id === f.props.bind_anchors.val.start.id)
  68. if (find_item) {
  69. const b_info = find_item.id === move_binfo?.id ? move_binfo : find_item.binfo
  70. // 四个角原始坐标
  71. const { topLeft, topRight, bottomLeft, bottomRight } = getRectCoordinate(b_info)
  72. // 四条边中点坐标
  73. const { topCenter, bottomCenter, leftCenter, rightCenter } = getRectCenterCoordinate(
  74. topLeft,
  75. topRight,
  76. bottomLeft,
  77. bottomRight
  78. )
  79. // 旋转中心
  80. const centerX = topCenter.x
  81. const centerY = leftCenter.y
  82. // 旋转角度(弧度)
  83. const angleRad = (Math.PI / 180) * find_item.binfo.angle
  84. if (f.props.bind_anchors.val.start.type === 'tc') {
  85. const new_tc = rotatePoint(topCenter.x, topCenter.y, centerX, centerY, angleRad)
  86. f.props.point_position.val[0] = {
  87. x: new_tc.x - f.binfo.left,
  88. y: new_tc.y - f.binfo.top
  89. }
  90. } else if (f.props.bind_anchors.val.start.type === 'bc') {
  91. const new_bc = rotatePoint(bottomCenter.x, bottomCenter.y, centerX, centerY, angleRad)
  92. f.props.point_position.val[0] = {
  93. x: new_bc.x - f.binfo.left,
  94. y: new_bc.y - f.binfo.top
  95. }
  96. } else if (f.props.bind_anchors.val.start.type === 'lc') {
  97. const new_lc = rotatePoint(leftCenter.x, leftCenter.y, centerX, centerY, angleRad)
  98. f.props.point_position.val[0] = {
  99. x: new_lc.x - f.binfo.left,
  100. y: new_lc.y - f.binfo.top
  101. }
  102. } else if (f.props.bind_anchors.val.start.type === 'rc') {
  103. const new_rc = rotatePoint(rightCenter.x, rightCenter.y, centerX, centerY, angleRad)
  104. f.props.point_position.val[0] = {
  105. x: new_rc.x - f.binfo.left,
  106. y: new_rc.y - f.binfo.top
  107. }
  108. }
  109. const move_x = new_left - f.binfo.left
  110. const move_y = new_top - f.binfo.top
  111. const normalized_geometry = normalizeLineGeometry(
  112. {
  113. left: new_left,
  114. top: new_top,
  115. width: itemRect.width / scale,
  116. height: itemRect.height / scale
  117. },
  118. f.props.point_position.val.map((m: { x: number; y: number }) => ({
  119. x: m.x - move_x,
  120. y: m.y - move_y
  121. }))
  122. )
  123. f.binfo = { ...f.binfo, ...normalized_geometry.binfo }
  124. f.props.point_position = {
  125. ...f.props.point_position,
  126. val: normalized_geometry.points
  127. }
  128. } else {
  129. f.props.bind_anchors.val.start = null
  130. }
  131. }
  132. // 处理终点绑定
  133. if (f.props.bind_anchors.val.end) {
  134. // 根据id和类型找到锚点坐标
  135. const find_item = temp_done_json.find((m) => m.id === f.props.bind_anchors.val.end.id)
  136. if (find_item) {
  137. const b_info = find_item.id === move_binfo?.id ? move_binfo : find_item.binfo
  138. // 四个角原始坐标
  139. const { topLeft, topRight, bottomLeft, bottomRight } = getRectCoordinate(b_info)
  140. // 四条边中点坐标
  141. const { topCenter, bottomCenter, leftCenter, rightCenter } = getRectCenterCoordinate(
  142. topLeft,
  143. topRight,
  144. bottomLeft,
  145. bottomRight
  146. )
  147. // 旋转中心
  148. const centerX = topCenter.x
  149. const centerY = leftCenter.y
  150. // 旋转角度(弧度)
  151. const angleRad = (Math.PI / 180) * find_item.binfo.angle
  152. if (f.props.bind_anchors.val.end.type === 'tc') {
  153. const new_tc = rotatePoint(topCenter.x, topCenter.y, centerX, centerY, angleRad)
  154. f.props.point_position.val[f.props.point_position.val.length - 1] = {
  155. x: new_tc.x - f.binfo.left,
  156. y: new_tc.y - f.binfo.top
  157. }
  158. } else if (f.props.bind_anchors.val.end.type === 'bc') {
  159. const new_bc = rotatePoint(bottomCenter.x, bottomCenter.y, centerX, centerY, angleRad)
  160. f.props.point_position.val[f.props.point_position.val.length - 1] = {
  161. x: new_bc.x - f.binfo.left,
  162. y: new_bc.y - f.binfo.top
  163. }
  164. } else if (f.props.bind_anchors.val.end.type === 'lc') {
  165. const new_lc = rotatePoint(leftCenter.x, leftCenter.y, centerX, centerY, angleRad)
  166. f.props.point_position.val[f.props.point_position.val.length - 1] = {
  167. x: new_lc.x - f.binfo.left,
  168. y: new_lc.y - f.binfo.top
  169. }
  170. } else if (f.props.bind_anchors.val.end.type === 'rc') {
  171. const new_rc = rotatePoint(rightCenter.x, rightCenter.y, centerX, centerY, angleRad)
  172. f.props.point_position.val[f.props.point_position.val.length - 1] = {
  173. x: new_rc.x - f.binfo.left,
  174. y: new_rc.y - f.binfo.top
  175. }
  176. }
  177. const move_x = new_left - f.binfo.left
  178. const move_y = new_top - f.binfo.top
  179. const normalized_geometry = normalizeLineGeometry(
  180. {
  181. left: new_left,
  182. top: new_top,
  183. width: itemRect.width / scale,
  184. height: itemRect.height / scale
  185. },
  186. f.props.point_position.val.map((m: { x: number; y: number }) => ({
  187. x: m.x - move_x,
  188. y: m.y - move_y
  189. }))
  190. )
  191. f.binfo = { ...f.binfo, ...normalized_geometry.binfo }
  192. f.props.point_position = {
  193. ...f.props.point_position,
  194. val: normalized_geometry.points
  195. }
  196. } else {
  197. f.props.bind_anchors.val.end = null
  198. }
  199. }
  200. })
  201. // 直接写在这里会损失一部分性能 也可以注释掉下面的 然后根据需求在useUpdateSysLine之后手动调用useUpdateSysLineRect
  202. nextTick(() => {
  203. useUpdateSysLineRect(sys_lines, canvasDom, scale)
  204. })
  205. }