change fab ui

This commit is contained in:
Gabe Yuan
2023-09-12 15:44:30 +08:00
parent f4e4c84712
commit 5e8743dbb7
2 changed files with 58 additions and 99 deletions

View File

@@ -1,62 +1,36 @@
import { useCallback, useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { limitNumber } from "../../libs/utils"; import { limitNumber } from "../../libs/utils";
import { isMobile } from "../../libs/mobile"; import { isMobile } from "../../libs/mobile";
import { setFab } from "../../libs/storage"; import { setFab } from "../../libs/storage";
import { debounce } from "../../libs/utils";
import Paper from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
const getEdgePosition = ( const getEdgePosition = ({
{ x: left, y: top, edge }, x: left,
y: top,
width,
height,
windowWidth, windowWidth,
windowHeight, windowHeight,
width, hover,
height }) => {
) => {
const right = windowWidth - left - width; const right = windowWidth - left - width;
const bottom = windowHeight - top - height; const bottom = windowHeight - top - height;
const min = Math.min(left, top, right, bottom); const min = Math.min(left, top, right, bottom);
switch (min) { switch (min) {
case right: case right:
edge = "right"; left = hover ? windowWidth - width : windowWidth - width / 2;
left = windowWidth - width;
break; break;
case left: case left:
edge = "left"; left = hover ? 0 : -width / 2;
left = 0;
break; break;
case bottom: case bottom:
edge = "bottom"; top = hover ? windowHeight - height : windowHeight - height / 2;
top = windowHeight - height;
break; break;
default: default:
edge = "top"; top = hover ? 0 : -height / 2;
top = 0;
} }
left = limitNumber(left, 0, windowWidth - width); return { x: left, y: top };
top = limitNumber(top, 0, windowHeight - height);
return { x: left, y: top, edge, hide: false };
};
const getHidePosition = (
{ x: left, y: top, edge },
windowWidth,
windowHeight,
width,
height
) => {
switch (edge) {
case "right":
left = windowWidth - width / 2;
break;
case "left":
left = -width / 2;
break;
case "bottom":
top = windowHeight - height / 2;
break;
default:
top = -height / 2;
}
return { x: left, y: top, edge, hide: true };
}; };
function DraggableWrapper({ children, usePaper, ...props }) { function DraggableWrapper({ children, usePaper, ...props }) {
@@ -71,7 +45,7 @@ function DraggableWrapper({ children, usePaper, ...props }) {
} }
export default function Draggable({ export default function Draggable({
windowSize, windowSize: { w: windowWidth, h: windowHeight },
width, width,
height, height,
left, left,
@@ -84,65 +58,36 @@ export default function Draggable({
children, children,
usePaper, usePaper,
}) { }) {
const [origin, setOrigin] = useState({ const [hover, setHover] = useState(false);
x: left, const [origin, setOrigin] = useState(null);
y: top, const [position, setPosition] = useState({ x: left, y: top });
px: left, const setFabPosition = useMemo(() => debounce(setFab, 500), []);
py: top,
});
const [position, setPosition] = useState({
x: left,
y: top,
edge: null,
hide: false,
});
const [edgeTimer, setEdgeTimer] = useState(null);
const goEdge = useCallback((w, h, width, height) => {
setPosition((pre) => getEdgePosition(pre, w, h, width, height));
setEdgeTimer(
setTimeout(() => {
setPosition((pre) => getHidePosition(pre, w, h, width, height));
}, 1500)
);
}, []);
const handlePointerDown = (e) => { const handlePointerDown = (e) => {
!isMobile && e.target.setPointerCapture(e.pointerId); !isMobile && e.target.setPointerCapture(e.pointerId);
onStart && onStart(); onStart && onStart();
edgeTimer && clearTimeout(edgeTimer); const { x, y } = position;
const { clientX, clientY } = isMobile ? e.targetTouches[0] : e; const { clientX, clientY } = isMobile ? e.targetTouches[0] : e;
setOrigin({ setOrigin({ x, y, clientX, clientY });
x: position.x,
y: position.y,
px: clientX,
py: clientY,
});
}; };
const handlePointerMove = (e) => { const handlePointerMove = (e) => {
onMove && onMove(); onMove && onMove();
const { clientX, clientY } = isMobile ? e.targetTouches[0] : e; const { clientX, clientY } = isMobile ? e.targetTouches[0] : e;
if (origin) { if (origin) {
const dx = clientX - origin.px; const dx = clientX - origin.clientX;
const dy = clientY - origin.py; const dy = clientY - origin.clientY;
let x = origin.x + dx; let x = origin.x + dx;
let y = origin.y + dy; let y = origin.y + dy;
const { w, h } = windowSize; x = limitNumber(x, -width / 2, windowWidth - width / 2);
x = limitNumber(x, 0, w - width); y = limitNumber(y, 0, windowHeight - height / 2);
y = limitNumber(y, 0, h - height); setPosition({ x, y });
setPosition({ x, y, edge: null, hide: false });
} }
}; };
const handlePointerUp = (e) => { const handlePointerUp = (e) => {
e.stopPropagation(); e.stopPropagation();
setOrigin(null); setOrigin(null);
if (!snapEdge) {
return;
}
goEdge(windowSize.w, windowSize.h, width, height);
}; };
const handleClick = (e) => { const handleClick = (e) => {
@@ -151,35 +96,48 @@ export default function Draggable({
const handleMouseEnter = (e) => { const handleMouseEnter = (e) => {
e.stopPropagation(); e.stopPropagation();
if (snapEdge && position.hide) { setHover(true);
edgeTimer && clearTimeout(edgeTimer); };
goEdge(windowSize.w, windowSize.h, width, height);
} const handleMouseLeave = (e) => {
e.stopPropagation();
setHover(false);
}; };
useEffect(() => { useEffect(() => {
setOrigin(null); if (!snapEdge || !!origin) {
if (!snapEdge) {
return; return;
} }
goEdge(windowSize.w, windowSize.h, width, height);
}, [snapEdge, goEdge, windowSize.w, windowSize.h, width, height]);
useEffect(() => { setPosition((pre) => {
if (position.hide) { const edgePosition = getEdgePosition({
setFab({ ...pre,
x: position.x, width,
y: position.y, height,
windowWidth,
windowHeight,
hover,
}); });
} setFabPosition(edgePosition);
}, [position.x, position.y, position.hide]); return edgePosition;
});
}, [
origin,
hover,
width,
height,
windowWidth,
windowHeight,
snapEdge,
setFabPosition,
]);
const opacity = useMemo(() => { const opacity = useMemo(() => {
if (snapEdge) { if (snapEdge) {
return position.hide ? 0.2 : 1; return hover || origin ? 1 : 0.2;
} }
return origin ? 0.8 : 1; return origin ? 0.8 : 1;
}, [origin, snapEdge, position.hide]); }, [origin, snapEdge, hover]);
const touchProps = isMobile const touchProps = isMobile
? { ? {
@@ -205,6 +163,7 @@ export default function Draggable({
display: show ? "block" : "none", display: show ? "block" : "none",
}} }}
onMouseEnter={handleMouseEnter} onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onClick={handleClick} onClick={handleClick}
> >
<div <div

View File

@@ -166,7 +166,7 @@ export default function Action({ translator, fab }) {
windowSize, windowSize,
width: fabWidth, width: fabWidth,
height: fabWidth, height: fabWidth,
left: fab.x ?? 0, left: fab.x ?? -fabWidth,
top: fab.y ?? windowSize.h / 2, top: fab.y ?? windowSize.h / 2,
}; };