Как реализовать сетку статического размера, такую ​​как 3x3, в React-Grid-Layout

Я хочу иметь сетку, которая всегда будет иметь, например, 3 строки и 3 столбца. Теперь предположим, что это мои элементы сетки

      <div className="myClass" key="1">1</div>
      <div className="myClass" key="2">2</div>
      <div className="myClass" key="3">3</div>
      <div className="myClass" key="4">4</div>
      <div className="myClass" key="5">5</div>
      <div className="myClass" key="6">6</div>
      <div className="myClass" key="7">7</div>
      <div className="myClass" key="8">8</div>
      <div className="myClass" key="9">9</div>

Предположим, что все элементы имеют одинаковую ширину и высоту и не могут быть изменены.

Если я перетащу 9 к 6, то есть по вертикали, предметы просто поменяются местами. Однако, если я перетащу 9 к 8, то есть по горизонтали, элемент 8 опустится в новую строку, и 9 будет на месте 8, тогда как предыдущее место на 9 будет пустым. Можно ли сделать так, чтобы элементы просто менялись местами при горизонтальном перетаскивании, вместо создания новой строки?

2 ответа

Решение

Поэтому я добавил onLayoutChange к ReactGridLayout

Прочитайте комментарии к коду для более подробной информации.

private onLayoutChange = (layout: any) => {
    const fixedLayout = this.fixLayout(layout)
    this.setState({
      layout: fixedLayout
    })
  }

  /**
   * The `react-grid-layout` lib is not swapping items during horizontal dragover
   * Rather it moves the items into a new row
   * Since we need a static 3x3 row, let's fix that
   */
  private fixLayout = (layout: any) => {
    // `y` is calculated by `h` in the layout object, since `h` is 20
    // first row will be 0, second 20, third 40
    const maxY = 40

    // when an item goes to a new row, there is an empty column in the maxY row
    // so here we find which columns exist
    // tslint:disable-next-line:max-line-length
    const maxRowXs = layout.map((item: any) => item.y === maxY ? item.x : null).filter((value: any) => value !== null)

    // xs or cols, we only have 3 cols
    const xs = [0,1,2]

    // find the missing col
    // tslint:disable-next-line:max-line-length
    const missingX = xs.find((value: any) => maxRowXs.every((maxRowX: number) => maxRowX !== value))

    // bring the item from the new row into maxY row
    // and place it in the missing column
    const fixedLayout = layout.map((item: any) => {
      if (item.y > maxY) {
        return {
          ...item,
          y: maxY,
          x: missingX
        }
      }
      return item
    })
    return fixedLayout
  }

Ответ Айка Сафаряна был отличным и исправил именно эту проблему, однако я обнаружил, что добавление "maxRows={3}" исправляет ошибку в ответе, когда вы могли сложить 4, потому что пользовательский интерфейс обновлялся до данных макета.

Мой код:

      import { useState } from "react";
import GridLayout from "react-grid-layout";

const Drag = () => {
  // layout is an array of objects, see the demo for more complete usage
  const [layout,setLayout] = useState([
    { i: "a", x: 0, y: 0, w: 1, h: 1, isResizable: false, },
    { i: "b", x: 1, y: 0, w: 1, h: 1, isResizable: false, },
    { i: "c", x: 2, y: 0, w: 1, h: 1, isResizable: false, },
    { i: "d", x: 0, y: 1, w: 1, h: 1, isResizable: false, },
    { i: "e", x: 1, y: 1, w: 1, h: 1, isResizable: false, },
    { i: "f", x: 2, y: 1, w: 1, h: 1, isResizable: false, },
    { i: "g", x: 0, y: 2, w: 1, h: 1, isResizable: false, },
    { i: "h", x: 1, y: 2, w: 1, h: 1, isResizable: false, },
    { i: "i", x: 2, y: 2, w: 1, h: 1, isResizable: false, },
  ]);

  
  return (
    <GridLayout
      className="layout"
      layout={layout}
      cols={3}
      rowHeight={100}
      width={1500}
      onLayoutChange={e=>setLayout(fixLayout(e))}
      maxRows={3}
    >
      <div key="a" style={{ background: "grey" }}>
        a
      </div>
      <div key="b" style={{ background: "grey" }}>
        b
      </div>
      <div key="c" style={{ background: "grey" }}>
        c
      </div>
      <div key="d" style={{ background: "grey" }}>
        d
      </div>
      <div key="e" style={{ background: "grey" }}>
        e
      </div>
      <div key="f" style={{ background: "grey" }}>
        f
      </div>
      <div key="g" style={{ background: "grey" }}>
        g
      </div>
      <div key="h" style={{ background: "grey" }}>
        h
      </div>
      <div key="i" style={{ background: "grey" }}>
        i
      </div>
    </GridLayout>
  );
};

export default Drag;


/**
 * The `react-grid-layout` lib is not swapping items during horizontal dragover
 * Rather it moves the items into a new row
 * Since we need a static 3x3 row, let's fix that
 */
const fixLayout = (layout) => {
  // `y` is calculated by `h` in the layout object, since `h` is 20
  // first row will be 0, second 20, third 40
  const maxY = 2

  // when an item goes to a new row, there is an empty column in the maxY row
  // so here we find which columns exist
  // tslint:disable-next-line:max-line-length
  const maxRowXs = layout.map((item) => item.y === maxY ? item.x : null).filter((value) => value !== null)

  // xs or cols, we only have 3 cols
  const xs = [0,1,2]

  // find the missing col
  // tslint:disable-next-line:max-line-length
  const missingX = xs.find((value) => maxRowXs.every((maxRowX) => maxRowX !== value))

  // bring the item from the new row into maxY row
  // and place it in the missing column
  const fixedLayout = layout.map((item) => {
    if (item.y > maxY) {
      const fixedItem = {
        ...item,
        y: maxY,
        x: missingX
      }
      return fixedItem
    }
    return item
  })
  return fixedLayout
}
Другие вопросы по тегам