import React, { useState, useRef } from "react"; import { FloatingBubble, Image } from "antd-mobile"; import { AddOutline, MessageOutline, UserOutline, SetOutline, HeartOutline, CheckOutline, } from "antd-mobile-icons"; import { createPortal } from "react-dom"; import "./index.less"; import { MoreTwo } from "@icon-park/react"; export interface FloatMenuItemConfig { icon: React.ReactNode; type?: string; } const FloatingFanMenu: React.FC<{ menuItems: FloatMenuItemConfig[]; value?: FloatMenuItemConfig; onChange?: (item: FloatMenuItemConfig) => void; }> = (props) => { const { menuItems = [] } = props; const [visible, setVisible] = useState(false); const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 }); const bubbleRef = useRef(null); // 点击时获取FloatingBubble的位置 const handleMainClick = () => { if (!visible) { // 显示菜单时,获取当前FloatingBubble的位置 if (bubbleRef.current) { const bubble = bubbleRef.current.querySelector( ".adm-floating-bubble-button" ); if (bubble) { const rect = bubble.getBoundingClientRect(); setMenuPosition({ x: rect.left + rect.width / 2, y: rect.top + rect.height / 2, }); } } } setVisible(!visible); }; const handleItemClick = (item: FloatMenuItemConfig) => { props.onChange?.(item); setVisible(false); }; // 计算菜单项位置 const getMenuItemPosition = (index: number) => { const positions = [ { x: 0, y: -80 }, // 上方 { x: -60, y: -60 }, // 左上 { x: -80, y: 0 }, // 左方 { x: -60, y: 60 }, // 左下 ]; const pos = positions[index] || { x: 0, y: 0 }; let x = menuPosition.x + pos.x; let y = menuPosition.y + pos.y; // // 边界检测 // const itemSize = 48; // const margin = 20; // 边界检测 const itemSize = 48; // const margin = 0; // x = Math.max( // // margin + itemSize / 2, // Math.min(window.innerWidth - margin - itemSize / 2, x) // ); // y = Math.max( // // margin + itemSize / 2, // Math.min(window.innerHeight - margin - itemSize / 2, y) // ); return { left: x - itemSize / 2, top: y - itemSize / 2, }; }; // 菜单组件 const MenuComponent = () => ( <> {/* 背景遮罩 */}
setVisible(false)} /> {/* 菜单项 */} {menuItems.map((item, index) => { const position = getMenuItemPosition(index); return (
handleItemClick(item)} // title={item.label} > {item.icon}
); })} ); return ( <> {/* 主按钮 */}
{props.value?.icon}
{/* {!visible && } */} 切换语言
{/* 菜单 - 只在有位置信息时渲染 */} {visible && menuPosition.x > 0 && menuPosition.y > 0 && createPortal(, document.body)} ); }; export default FloatingFanMenu;