如何在 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
}
我想要一个始终具有例如 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
}
我的代码:
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
}