collison.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { DragactLayoutItem } from "../dragact";
  2. import { GridItemEvent } from "../gridItem";
  3. export const collision = (a: DragactLayoutItem, b: DragactLayoutItem) => {
  4. if (a.GridX === b.GridX && a.GridY === b.GridY &&
  5. a.w === b.w && a.h === b.h) {
  6. return true
  7. }
  8. if (a.GridX + a.w <= b.GridX) return false
  9. if (a.GridX >= b.GridX + b.w) return false
  10. if (a.GridY + a.h <= b.GridY) return false
  11. if (a.GridY >= b.GridY + b.h) return false
  12. return true
  13. }
  14. /**获取layout中,item第一个碰撞到的物体 */
  15. export const getFirstCollison = (layout: DragactLayoutItem[], item: DragactLayoutItem) => {
  16. for (let i = 0, length = layout.length; i < length; i++) {
  17. if (collision(layout[i], item)) {
  18. return layout[i]
  19. }
  20. }
  21. return null
  22. }
  23. export const layoutCheck = (layout: DragactLayoutItem[], layoutItem: GridItemEvent,
  24. key: string | number, fristItemkey: string | number, moving: number) => {
  25. let i: any = [], movedItem: any = []/**收集所有移动过的物体 */
  26. let newlayout = layout.map((item, idx) => {
  27. if (item.key !== key) {
  28. if (item.static) {
  29. return item
  30. }
  31. if (collision(item, layoutItem)) {
  32. i.push(item.key)
  33. /**
  34. * 这里就是奇迹发生的地方,如果向上移动,那么必须注意的是
  35. * 一格一格的移动,而不是一次性移动
  36. */
  37. let offsetY = item.GridY + 1
  38. /**这一行也非常关键,当向上移动的时候,碰撞的元素必须固定 */
  39. // if (moving < 0 && layoutItem.GridY > 0) offsetY = item.GridY
  40. if (layoutItem.GridY > item.GridY && layoutItem.GridY < item.GridY + item.h) {
  41. /**
  42. * 元素向上移动时,元素的上面空间不足,则不移动这个元素
  43. * 当元素移动到GridY>所要向上交换的元素时,就不会进入这里,直接交换元素
  44. */
  45. offsetY = item.GridY
  46. }
  47. /**
  48. * 物体向下移动的时候
  49. */
  50. if (moving > 0) {
  51. if (layoutItem.GridY + layoutItem.h < item.GridY) {
  52. let collision;
  53. let copy = { ...item }
  54. while (true) {
  55. let newLayout = layout.filter((item) => {
  56. if (item.key !== key && (item.key !== copy.key)) {
  57. return item
  58. }
  59. })
  60. collision = getFirstCollison(newLayout, copy)
  61. if (collision) {
  62. offsetY = collision.GridY + collision.h
  63. break
  64. } else {
  65. copy.GridY--
  66. }
  67. if (copy.GridY < 0) {
  68. offsetY = 0
  69. break
  70. }
  71. }
  72. }
  73. }
  74. movedItem.push({ ...item, GridY: offsetY, isUserMove: false })
  75. return { ...item, GridY: offsetY, isUserMove: false }
  76. }
  77. } else if (fristItemkey === key) {
  78. /**永远保持用户移动的块是 isUserMove === true */
  79. return { ...item, GridX: layoutItem.GridX, GridY: layoutItem.GridY, isUserMove: true }
  80. }
  81. return item
  82. })
  83. /** 递归调用,将layout中的所有重叠元素全部移动 */
  84. const length = movedItem.length;
  85. for (let c = 0; c < length; c++) {
  86. newlayout = layoutCheck(newlayout, movedItem[c], i[c], fristItemkey, 0)
  87. }
  88. return newlayout
  89. }