1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| import { useRef } from "react"; import clamp from "lodash-es/clamp"; import swap from "lodash-move"; import { useSprings, animated, config } from "@react-spring/web"; import { useDrag } from "@use-gesture/react"; import { MAX_COL, SX, SY } from "@/constants/combFile"; import "./index.css";
const OperatePic = ({ items }) => { const height = (Math.floor(items.length / MAX_COL) + 1) * SY; const width = (Math.floor(items.length / MAX_COL) >= 1 ? MAX_COL : items.length) * SX;
const fn = ( order, active = false, originalIndex = 0, curIndex = 0, x = 0, y = 0 ) => (index) => active && index === originalIndex ? { x: (curIndex % MAX_COL) * SX + x, y: Math.floor(curIndex / MAX_COL) * SY + y, scale: 1.1, zIndex: 1, shadow: 15, immediate: (key) => key === "zIndex", config: (key) => key === "y" ? config.stiff : config.default, } : { x: (order.indexOf(index) % MAX_COL) * SX, y: Math.floor(order.indexOf(index) / MAX_COL) * SY, scale: 1, zIndex: 0, shadow: 1, immediate: false, };
const order = useRef(items.map((_, index) => index)); const [springs, api] = useSprings(items.length, fn(order.current)); const bind = useDrag( ({ args: [originalIndex], active, movement: [x, y] }) => { const curIndex = order.current.indexOf(originalIndex); const curRow = clamp( Math.round((Math.floor(curIndex / MAX_COL) * SY + y) / SY), 0, Math.floor(items.length / MAX_COL) ); const curCol = clamp( Math.round(((curIndex % MAX_COL) * SX + x) / SX), 0, Math.max(items.length - 1, MAX_COL) ); console.log(curRow, curCol, curIndex, originalIndex, x, y); const newOrder = swap( order.current, curIndex, curRow * MAX_COL + curCol ); api.start(fn(newOrder, active, originalIndex, curIndex, x, y)); if (!active) order.current = newOrder; } );
return ( <div className="content" style={{ height: height, width: width, }} > {springs.map(({ zIndex, shadow, x, y, scale }, i) => ( <animated.div {...bind(i)} // 绑定拖动事件 key={i} // 绑定key style={{ width: SX - 20, height: SY - 20, // 与fn的返回值对应 zIndex, boxShadow: shadow.to( (s) => `rgba(0, 0, 0, 0.15) 0px ${s}px ${2 * s}px 0px` ), x, y, scale, }} children={items[i]} // 显示内容 /> ))} </div> ); };
export default OperatePic;
|