当前位置: 首页 > 工具软件 > Dial-menu > 使用案例 >

reat-float-menu

锺离飞鸣
2023-12-01
import * as React from 'react';
import Box from '@mui/material/Box';
import Fab from '@mui/material/Fab';
import AddIcon from '@mui/icons-material/Add';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
// import { createTheme } from '@mui/material/styles'
import './floatBtn.css';

export default function FloatingActionButtonSize() {
  const [transform,setTranasform] = React.useState({ top: document.body.offsetHeight - 300, left: document.body.offsetWidth - 50 })
  const [anchorEl, setAnchorEl] = React.useState(null);
  const [moveFlags,setMoveFlags] = React.useState(false);
  let [lastMoveIndex,setLastMoveIndex] = React.useState(0);
  let [curMoveIndex,setCurMoveIndex] = React.useState(0);
  const open = Boolean(anchorEl);
  // const [open,setOpen] = React.useState(false);
  const floatBtn = React.useRef()
  const handleClick = (event) => {
    if(!moveFlags){
      console.log('first',lastMoveIndex,curMoveIndex)
      if(lastMoveIndex === curMoveIndex){
        setAnchorEl(event.currentTarget);
      }else{
        setCurMoveIndex(lastMoveIndex)
      }
    }
    // setOpen(true)
  };
  const handleClose = () => {
    setAnchorEl(null);
  };

  const moveStart = (e) => {
    console.log('moveStart')
    if (e.button === 2) return;
    //计算鼠标相对于元素的位置
    const { top, left } = transform
    const dx = e.clientX - left
    const dy = e.clientY - top

    setMoveFlags(true)
    document.onmousemove = (e) => {
    setLastMoveIndex(lastMoveIndex++)

      console.log('onmousemove')
      const bodyWidth = document.body.clientWidth
      const bodyHeight = document.body.clientHeight
      const moveMaxHeight = bodyHeight - floatBtn.current.offsetHeight +dy
      const moveMaxWidth = bodyWidth - floatBtn.current.offsetWidth + dx
      const nx = e.clientX
      const ny = e.clientY
     const xPum = (nx > moveMaxWidth ? moveMaxWidth : nx) - dx
     const yPum = (ny > moveMaxHeight ? moveMaxHeight : ny) - dy
      console.log('xpum', xPum, yPum)
      setTranasform({ top:yPum > 0 ? yPum : 0, left:xPum > 0 ? xPum : 0})
    }
    document.onmouseup = () => {
      // document.onmousemove = null
      // document.onmouseup = null
      setMoveFlags(false)
      // resetFloatBtnLocation()
      moveEnd()
    }
  }
  const resetFloatBtnLocation = () => { 
    console.log('reset')
    if(!floatBtn.current) return
    const bodyWidth = document.body.clientWidth
    const {top, left} = transform
    console.log('left: ' + left + ' top: ' + top)
    if(left <= bodyWidth / 2){
      console.log('1')
      setTranasform({ top:top, left:0})
    }else{
      console.log('2')
      setTranasform({ top:top, left:bodyWidth - 50})
    }

  }
  const moveEnd = () => {
    console.log('moveEnd')
    document.onmousemove = null
    document.onmouseup = null;
    resetFloatBtnLocation()
    // setMoveFlags(false)
  }

  return (
    <div className='warpBox'>
      <div
        className='floatBtn'
        ref={floatBtn}
        style={{ transition: !moveFlags ? 'all 300ms ease' : 'unset', transform: `translate(${transform.left}px,${transform.top}px)` }}
        onMouseDown={moveStart}
        onMouseUp={moveEnd}

      >
        <Box>
          <Fab size="medium" color="secondary" aria-label="add" onClick={handleClick}>
            <AddIcon />
          </Fab>
          <Menu
            id="demo-positioned-menu"
            aria-labelledby="demo-positioned-button"
            anchorEl={anchorEl}
            open={open}
            onClose={handleClose}
            anchorOrigin={{
              vertical: 'top',
              horizontal: 'left',
            }}
            transformOrigin={{ horizontal: 'right', vertical: 'top' }}
          >
            <MenuItem onClick={handleClose}>Profile</MenuItem>
            <MenuItem onClick={handleClose}>My account</MenuItem>
            <MenuItem onClick={handleClose}>Logout</MenuItem>
          </Menu>
        </Box>
      </div>
    </div>
  );
}

// import * as React from 'react';
// import Box from '@mui/material/Box';
// import SpeedDial from '@mui/material/SpeedDial';
// import SpeedDialIcon from '@mui/material/SpeedDialIcon';
// import SpeedDialAction from '@mui/material/SpeedDialAction';
// import FileCopyIcon from '@mui/icons-material/FileCopyOutlined';
// import SaveIcon from '@mui/icons-material/Save';
// import PrintIcon from '@mui/icons-material/Print';
// import ShareIcon from '@mui/icons-material/Share';

// const actions = [
//   { icon: <FileCopyIcon />, name: 'Copy' },
//   { icon: <SaveIcon />, name: 'Save' },
//   { icon: <PrintIcon />, name: 'Print' },
//   { icon: <ShareIcon />, name: 'Share' },
// ];

// export default function BasicSpeedDial() {
//   return (
//     <Box sx={{ height: 320, transform: 'translateZ(0px)', flexGrow: 1 }}>
//       <SpeedDial
//         ariaLabel="SpeedDial basic example"
//         sx={{ position: 'absolute', bottom: 16, right: 16 }}
//         icon={<SpeedDialIcon />}
//       >
//         {actions.map((action) => (
//           <SpeedDialAction
//             key={action.name}
//             icon={action.icon}
//             tooltipTitle={action.name}
//           />
//         ))}
//       </SpeedDial>
//     </Box>
//   );
// }
.warpBox {
    position: absolute;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    /* pointer-events: none; */
}
.floatBtn {
    position: absolute;
    z-index: 1000;
    cursor: pointer;
}
 类似资料: