如何在 React-Grid-Layout 中实现像 3x3 这样的静态大小的网格

How to implement static sized grid like 3x3 in 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 的前一个位置将为空。 是否可以让项目在水平拖动期间也只是交换位置,而不是创建新行?

所以我将 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,因为 ui 在布局之前更新数据.

我的代码:

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
}