optimize fab

This commit is contained in:
Gabe Yuan
2023-08-09 22:45:43 +08:00
parent e588ea9f55
commit 7a84933107
2 changed files with 78 additions and 35 deletions

View File

@@ -1,17 +1,59 @@
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { limitNumber } from "../../libs/utils";
import { isMobile } from "../../libs/mobile";
export default function Draggable(props) {
const [origin, setOrigin] = useState(null);
const getSidePosition = (
windowWidth,
windowHeight,
width,
height,
left,
top
) => {
const right = Math.abs(windowWidth - left - width);
const bottom = Math.abs(windowHeight - top - height);
left = Math.abs(left);
top = Math.abs(top);
const min = Math.min(left, top, right, bottom);
switch (min) {
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 };
};
export default function Draggable({
windowSize,
width,
height,
left,
top,
show,
goside,
onStart,
onMove,
handler,
children,
}) {
const [origin, setOrigin] = useState(goside ? {} : null);
const [position, setPosition] = useState({
x: props.left,
y: props.top,
x: left,
y: top,
});
const handlePointerDown = (e) => {
!isMobile && e.target.setPointerCapture(e.pointerId);
props?.onStart();
onStart && onStart();
const { clientX, clientY } = isMobile ? e.targetTouches[0] : e;
setOrigin({
x: position.x,
@@ -22,37 +64,28 @@ export default function Draggable(props) {
};
const handlePointerMove = (e) => {
props?.onMove();
onMove && onMove();
const { clientX, clientY } = isMobile ? e.targetTouches[0] : e;
if (origin) {
const dx = clientX - origin.px;
const dy = clientY - origin.py;
let x = origin.x + dx;
let y = origin.y + dy;
const { w, h } = props.windowSize;
x = limitNumber(x, -props.width / 2, w - props.width / 2);
y = limitNumber(y, -props.height / 2, h - props.height / 2);
const { w, h } = windowSize;
x = limitNumber(x, -width / 2, w - width / 2);
y = limitNumber(y, -height / 2, h - height / 2);
setPosition({ x, y });
}
};
const handlePointerUp = (e) => {
setOrigin(null);
if (!props.goside) {
if (!goside) {
return;
}
const { w, h } = props.windowSize;
let { x: left, y: top } = position;
const right = w - left - props.width;
const bottom = h - top - props.height;
const min = Math.min(left, top, right, bottom);
left === min && (left = -props.width / 2);
top === min && (top = -props.height / 2);
right === min && (left = w - props.width / 2);
bottom === min && (top = h - props.height / 2);
setPosition({ x: left, y: top });
setPosition((pre) =>
getSidePosition(windowSize.w, windowSize.h, width, height, pre.x, pre.y)
);
};
const handleClick = (e) => {
@@ -72,23 +105,33 @@ export default function Draggable(props) {
};
useEffect(() => {
const { w, h } = props.windowSize;
setPosition(({ x, y }) => ({
x: limitNumber(x, -props.width / 2, w - props.width / 2),
y: limitNumber(y, -props.height / 2, h - props.height / 2),
}));
}, [props.windowSize, props.width, props.height]);
setOrigin(null);
if (!goside) {
return;
}
setPosition((pre) =>
getSidePosition(windowSize.w, windowSize.h, width, height, pre.x, pre.y)
);
}, [goside, windowSize.w, windowSize.h, width, height]);
const opacity = useMemo(() => {
if (goside) {
return origin ? 1 : 0.3;
}
return origin ? 0.7 : 1;
}, [origin, goside]);
return (
<div
style={{
opacity,
position: "fixed",
left: position.x,
top: position.y,
zIndex: 2147483647,
display: props.show ? "block" : "none",
display: show ? "block" : "none",
transitionProperty: origin ? "none" : "all",
transitionDuration: "1s",
transitionDuration: "0.5s",
transitionDelay: "0.5s",
}}
onClick={handleClick}
@@ -99,9 +142,9 @@ export default function Draggable(props) {
}}
{...touchProps}
>
{props.handler}
{handler}
</div>
<div>{props.children}</div>
<div>{children}</div>
</div>
);
}

View File

@@ -67,8 +67,8 @@ export default function Action({ translator }) {
windowSize,
width: fabWidth,
height: fabWidth,
left: window.innerWidth - fabWidth - fabWidth / 2,
top: window.innerHeight - fabWidth - fabWidth,
left: window.innerWidth - fabWidth,
top: window.innerHeight / 2,
};
return (