import React, { useEffect, useState, FC } from 'react'
import { useGesture } from '@use-gesture/react'
import { useSpring, animated } from '@react-spring/web'
interface IProps {
scrolling: boolean
}
const FloatingBall: FC<IProps> = props => {
const [show, setShow] = useState<boolean>(false)
const [positionType, setPositionType] = useState<string>('right')
const { scrolling = false } = props
const [style, setSpringStyle] = useSpring(() => ({ x: 0, y: 0 }))
const clientWidth: number = document.documentElement.clientWidth || document.body.clientWidth
const clientHeight: number = document.documentElement.clientHeight || document.body.clientHeight
// 悬浮球常量
const STOW_OFFSET: number = 60
const FLOATING_BALL_WIDTH: number = 65
const FLOATING_BALL_HEIGHT: number = 65
const FLOATING_BALL_MARGIN: number = 10
// 悬浮球停靠位置范围
const maxX: number = 0
const maxY: number = 0
const minX: number = -clientWidth + FLOATING_BALL_WIDTH + FLOATING_BALL_MARGIN * 2
const minY: number = -clientHeight + FLOATING_BALL_HEIGHT + FLOATING_BALL_MARGIN * 2
useEffect(() => {
let _x: number | null = null
const isPositionLeft: boolean = positionType === 'left'
if (scrolling) {
_x = isPositionLeft ? minX - STOW_OFFSET : maxX + STOW_OFFSET
} else {
_x = isPositionLeft ? minX : maxX
}
setSpringStyle({ x: _x })
}, [scrolling])
// 拖动悬浮球
const bind = useGesture({
onDrag: ({ offset: [x, y] }) => {
setSpringStyle({ x, y })
},
onDragEnd: ({ offset, offset: [x, y] }) => {
// 判断悬浮球停靠左侧还是右侧
const _positionType: string = x < -(clientWidth - FLOATING_BALL_WIDTH - FLOATING_BALL_MARGIN * 2) / 2 ? 'left' : 'right'
// 计算悬浮球停靠位置
const _x: number = _positionType === 'left' ? minX : maxX
const _y: number = y > maxY ? maxY : y < minY ? minY : y
// 保存悬浮球新的停靠位置,下次拖动以此位置为基础
offset[0] = _x
offset[1] = _y
setPositionType(_positionType)
setSpringStyle({ x: _x, y: _y })
},
})
return (
<animated.div {...bind()} style={style} className="floating-ball-box">
<img
className="floating-ball-icon"
src={require('@/images/seeDoctor/floating-ball-icon.png')}
/>
</animated.div>
)
}
export default FloatingBall
// 悬浮球相关样式
.floating-ball-box {
z-index: 30
width: 65px
height: 65px
cursor: pointer
touch-action: none
position: fixed
right: 10px
bottom: 10px
.floating-ball-icon {
width: 100%
height: 100%
}
}