React+Kanva实现座位环绕中心圆桌布局技术求助
实现React+Kanva圆桌座位环绕布局方案
核心思路
圆桌布局本质是极坐标转笛卡尔坐标:以圆桌中心为原点,按总座位数均分圆周角度,计算每个座位的坐标后偏移到圆桌中心位置,同时预留座位与圆桌的间距。
具体实现调整
1. 替换定位函数
删除原有分栏定位逻辑,改用极坐标计算座位位置:
// 可根据容器动态调整的基础配置 const TABLE_CENTER_X = 400; // 示例值,建议改为容器宽的一半 const TABLE_CENTER_Y = 300; // 示例值,建议改为容器高的一半 const TABLE_RADIUS = 120; // 圆桌半径 const SEAT_OFFSET = 30; // 座位与圆桌边缘的间距 // 计算单个座位的坐标 const calculateSeatPosition = (seatIndex, totalSeats) => { // 均分圆周角度(2π弧度对应360度) const angle = (2 * Math.PI * seatIndex) / totalSeats; // 极坐标转笛卡尔坐标 const x = TABLE_CENTER_X + (TABLE_RADIUS + SEAT_OFFSET) * Math.cos(angle); const y = TABLE_CENTER_Y + (TABLE_RADIUS + SEAT_OFFSET) * Math.sin(angle); return { x, y }; };
2. 动态生成座位时应用新坐标
修改座位生成逻辑,传入索引和总数量调用新计算函数:
// 假设你的座位数据是 seatsList 数组 const seats = seatsList.map((seat, index) => { const { x, y } = calculateSeatPosition(index, seatsList.length); return ( <Seat key={seat.id} x={x} y={y} seatNumber={seat.seatNumber} // 其他所需props /> ); });
3. 响应式适配处理
如果需要适配不同屏幕尺寸,动态计算圆桌中心和半径:
const containerRef = useRef(null); const [tableConfig, setTableConfig] = useState({ centerX: 400, centerY: 300, tableRadius: 120 }); useEffect(() => { const updateTableConfig = () => { if (!containerRef.current) return; const { width, height } = containerRef.current.getBoundingClientRect(); const centerX = width / 2; const centerY = height / 2; // 取容器较小边的1/3作为圆桌半径,避免溢出 const tableRadius = Math.min(width, height) / 3; setTableConfig({ centerX, centerY, tableRadius }); }; updateTableConfig(); window.addEventListener('resize', updateTableConfig); return () => window.removeEventListener('resize', updateTableConfig); }, []); // 同步修改calculateSeatPosition函数,使用tableConfig中的值 const calculateSeatPosition = (seatIndex, totalSeats) => { const angle = (2 * Math.PI * seatIndex) / totalSeats; const x = tableConfig.centerX + (tableConfig.tableRadius + SEAT_OFFSET) * Math.cos(angle); const y = tableConfig.centerY + (tableConfig.tableRadius + SEAT_OFFSET) * Math.sin(angle); return { x, y }; };
4. 修正Seat组件锚点
Kanva元素默认以左上角为锚点,需将座位锚点设为中心避免偏移:
// Seat组件内部的Circle配置 <Circle x={props.x} y={props.y} radius={15} fill="#fff" stroke="#333" strokeWidth={2} // 设置锚点为中心(偏移值等于半径的负值) offsetX={-15} offsetY={-15} />
5. 兼容座位状态样式
基于JSON数据中的座位状态调整样式,不影响布局逻辑:
<Circle fill={ seat.status === 'occupied' ? '#ff4444' : seat.status === 'reserved' ? '#ffdd44' : '#fff' } // 其他属性 />
调试建议
- 先固定总座位数(如4个)测试,验证座位是否均匀分布在上下左右
- 调整
SEAT_OFFSET控制座位与圆桌的距离,避免重叠 - 响应式场景下,监听容器尺寸变化后重新计算所有座位坐标
内容的提问来源于stack exchange,提问作者Tsuki
相关产品推荐
相关产品推荐

