Last active
November 23, 2019 17:46
-
-
Save suhaotian/72bd877fa7858921cf5ae354fb38d843 to your computer and use it in GitHub Desktop.
floating menu ball like iOS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useRef } from 'react'; | |
import { useSpring, animated } from 'react-spring'; | |
import { useDrag } from 'react-use-gesture'; | |
import { useWindowSize } from 'react-use'; | |
function calcMinDirection( | |
x: number, | |
y: number, | |
w: number, | |
h: number, | |
parentWidth: number, | |
parentHeight: number | |
): string { | |
const headerThreshold = 0.2; | |
//let min = x | |
let min_dir = 'left'; | |
if (parentWidth - x < x) { | |
//min = parentHeight - x | |
min_dir = 'right'; | |
} | |
if (y < headerThreshold) { | |
// y < headerThreshold | |
min_dir = 'top'; | |
} | |
if (parentHeight - y < h + headerThreshold) { | |
// height + headerThreshold | |
min_dir = 'bottom'; | |
} | |
return min_dir; | |
} | |
function snapback( | |
direction: string, | |
x: number, | |
y: number, | |
w: number, | |
h: number, | |
parentWidth: number, | |
parentHeight: number | |
): Array<number> { | |
if (direction == 'left') { | |
x -= x; | |
} | |
if (direction == 'right') { | |
x -= x + w - parentWidth; | |
} | |
if (direction == 'top') { | |
y -= y; | |
} | |
if (direction == 'bottom') { | |
y -= y + h - parentHeight; | |
} | |
return [x, y]; | |
} | |
export function DragBall(props: any) { | |
const { size, ...rest } = props; | |
const { width, height } = useWindowSize(); | |
const ref = useRef({ x: 0, y: 0 }); // 缓存最后一次位置 | |
const [style, set] = useSpring(() => ({ x: 0, y: 0, scale: 1 })); | |
const bind = useDrag(({ down, movement: [x, y] }) => { | |
const last = ref.current; | |
const xx = x + last.x, | |
yy = y + last.y; | |
if (down) { | |
set({ | |
x: xx, | |
y: yy, | |
scale: 1.2, | |
}); | |
} else { | |
const direction = calcMinDirection(xx, yy, size, size, width, height); | |
const [xxx, yyy] = snapback(direction, xx, yy, size, size, width, height); | |
last.x = xxx; | |
last.y = yyy; | |
set({ | |
x: xxx, | |
y: yyy, | |
scale: 1, | |
}); | |
} | |
}); | |
return <animated.div {...bind()} style={style} {...rest} />; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment