赞
踩
直接上代码,js代码片段如下
import React, { useRef, useState, useEffect } from 'react'; import { useHistory, withRouter } from 'react-router-dom'; import './index.css'; let firstTime = 0, lastTime = 0; const FloatingBall = (props) => { const history = useHistory(); const [position, setPosition] = useState({ x: 1362, y: 782 }); const [positionChildern, setPositionChildern] = useState({ x: 60, y: 60 }); const [isShow, setIsShow] = useState(false); const ballSize = 64; //悬浮球点击 const onClick = (event) => { if ((lastTime - firstTime) > 200) return setIsShow(!isShow) event.preventDefault(); } //菜单点击 const menuClick = (event, url) => { if (url.indexOf(getUrl()) > -1) { history.push(url.replace(getUrl(), '')) } else { window.location.href = url } event.preventDefault(); } const getUrl = () => { let baseUrl = '' switch (process.env.REACT_APP_ENV) { case 'test': baseUrl = 'http://...' break case 'prod': baseUrl = 'https://...' break default: baseUrl = 'https://...' } return baseUrl } useEffect(() => { if (isShow) { const screenWidth = document.documentElement.clientWidth; const screenHeight = document.documentElement.clientHeight; const baseWidth = 1920 / screenWidth; const baseHeight = 1080 / screenHeight; var height = document.getElementsByClassName("custom-menu-box")[0].offsetHeight; let childernX = position.x > (screenWidth / 2) * baseWidth ? -250 : 30 let childernY = position.y > (screenHeight / 2) * baseHeight ? -(height - 30) : 30 setPositionChildern({ x: childernX, y: childernY }) } }, [isShow]); useEffect(() => { //为true时会影响拖拽后的逻辑,只能为false进行设置 if (!props.isBallshow) { setIsShow(props.isBallshow) } }, [props.isBallshow]); const ballRef = useRef(null); const handleMouseDown = (e) => { firstTime = new Date().getTime(); const ball = ballRef.current; let newX, newY; const handleMouseMove = (e) => { lastTime = new Date().getTime(); if (isShow) { setIsShow(false) } //支持触控 const newLeft = e.touches ? e.touches[0].clientX : e.clientX; const newTop = e.touches ? e.touches[0].clientY : e.clientY; // 使用 document.documentElement.clientHeight 获取视口高度 const screenWidth = document.documentElement.clientWidth; const screenHeight = document.documentElement.clientHeight; const baseWidth = 1920 / screenWidth; const baseHeight = 1080 / screenHeight; // 边界检测,确保悬浮球不会超出视口---(ballSize/2)是球球一半值,处理鼠标在球球中心 if (newLeft >= (ballSize / 2) && newLeft - (ballSize / 2) <= screenWidth - ballSize) { newX = `${baseWidth * newLeft}`; } if (newTop >= (ballSize / 2) && newTop - (ballSize / 2) <= screenHeight - ballSize) { newY = `${baseHeight * newTop}`; } if ((lastTime - firstTime) < 200) return setPosition({ x: newX - (ballSize / 2), y: newY - (ballSize / 2) }); }; const handleMouseUp = (e) => { lastTime = new Date().getTime(); document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); document.removeEventListener('touchmove', handleMouseMove); document.removeEventListener('touchend', handleMouseUp); }; document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); document.addEventListener('touchmove', handleMouseMove); document.addEventListener('touchend', handleMouseUp); }; return ( <div ref={ballRef} className="floating-button" style={{ left: position.x + 'px', top: position.y + 'px' }} onMouseDown={handleMouseDown} onTouchStart={handleMouseDown} onClick={onClick} > <span></span> {(isShow) && <div className='custom-menu-box' style={{ left: positionChildern.x, top: positionChildern.y }}> {props.menuList && props.menuList.map((item, index) => ( <div onClick={e => { menuClick(e, item.url) }} className={index == props.menuList.length - 1 ? 'custom-last-div' : ''}>{item.resourceName}<i className='operate-L1Arr-open'></i></div> ))} </div>} </div> ); }; export default FloatingBall;
在公共页面引入此组件,需要传入两个参数(menuList,isBallshow),我这个写的支持悬浮球点击 打开菜单,菜单的列表可跳转,鼠标拖拽和移动端触控都可以使用
不论哪个框架,拖拽的事件都差不多,自行修改就可以
css代码
* { box-sizing: border-box; } .floating-button { position: fixed; width: 64px; height: 64px; cursor: pointer; z-index: 1000; top: 50%; left: 50%; /* background-color: red; */ } .floating-button span { width: 100%; height: 100%; position: absolute; top: 0; left: 0; background-image: url('../../assets/images/ball/button.gif'); background-size: cover; background-repeat: no-repeat; background-position: center; z-index: 222; } .floating-button .custom-menu-box { width: 280px; /* height: 300px; */ background-color: #0C2243; position: absolute; top: 60px; left: 60px; border-radius: 8px; border: 2px solid #379BE8; padding: 8px 24px 0 26px; color: #fff; font-size: 14px; letter-spacing: 1px; box-shadow: 0 4px 4px 0 rgba(255, 255, 255, 0.25) inset; } .floating-button .custom-menu-box>div { line-height: 42px; position: relative; cursor: pointer; } .floating-button .custom-menu-box>div::after { position: absolute; display: block; content: ''; width: 100%; height: 1px; background: linear-gradient(to right, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0)); top: 100%; left: 0; } .floating-button .custom-menu-box>.custom-last-div::after { background: transparent; } .floating-button .custom-menu-box .operate-L1Arr-open { width: 24px; height: 24px; position: absolute; right: 6px; top: 9px; background-image: url('../../assets/images/ball/gengduo1 2@2x.png'); /* 图标路径 */ background-size: cover; /* 图标适应尺寸 */ background-repeat: no-repeat; /* 禁止重复 */ }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。