collison.js 3.6 KB

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