collison.js 3.8 KB

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