fix(web): ensure mask editing works in firefox

This commit is contained in:
Paul Armstrong 2021-01-16 09:33:15 -08:00 committed by Blake Blackshear
parent d84b75168c
commit 7f8ae2ce5c

View File

@ -96,18 +96,14 @@ export default function Camera({ camera, url }) {
); );
} }
function EditableMask({ onChange, points: initialPoints, scale, width, height }) { function EditableMask({ onChange, points, scale, width, height }) {
const [points, setPoints] = useState(initialPoints); const boundingRef = useRef(null);
useEffect(() => {
setPoints(initialPoints);
}, [setPoints, initialPoints]);
function boundedSize(value, maxValue) { function boundedSize(value, maxValue) {
return Math.min(Math.max(0, Math.round(value)), maxValue); return Math.min(Math.max(0, Math.round(value)), maxValue);
} }
const handleDragEnd = useCallback( const handleMovePoint = useCallback(
(index, newX, newY) => { (index, newX, newY) => {
if (newX < 0 && newY < 0) { if (newX < 0 && newY < 0) {
return; return;
@ -116,10 +112,9 @@ function EditableMask({ onChange, points: initialPoints, scale, width, height })
const y = boundedSize(newY / scale, height); const y = boundedSize(newY / scale, height);
const newPoints = [...points]; const newPoints = [...points];
newPoints[index] = [x, y]; newPoints[index] = [x, y];
setPoints(newPoints);
onChange(newPoints); onChange(newPoints);
}, },
[scale, points, setPoints] [scale, points]
); );
// Add a new point between the closest two other points // Add a new point between the closest two other points
@ -138,20 +133,18 @@ function EditableMask({ onChange, points: initialPoints, scale, width, height })
const index = points.indexOf(closest); const index = points.indexOf(closest);
const newPoints = [...points]; const newPoints = [...points];
newPoints.splice(index, 0, newPoint); newPoints.splice(index, 0, newPoint);
setPoints(newPoints);
onChange(newPoints); onChange(newPoints);
}, },
[scale, points, setPoints, onChange] [scale, points, onChange]
); );
const handleRemovePoint = useCallback( const handleRemovePoint = useCallback(
(index) => { (index) => {
const newPoints = [...points]; const newPoints = [...points];
newPoints.splice(index, 1); newPoints.splice(index, 1);
setPoints(newPoints);
onChange(newPoints); onChange(newPoints);
}, },
[points, setPoints, onChange] [points, onChange]
); );
const scaledPoints = useMemo(() => scalePolylinePoints(points, scale), [points, scale]); const scaledPoints = useMemo(() => scalePolylinePoints(points, scale), [points, scale]);
@ -161,9 +154,22 @@ function EditableMask({ onChange, points: initialPoints, scale, width, height })
{!scaledPoints {!scaledPoints
? null ? null
: scaledPoints.map(([x, y], i) => ( : scaledPoints.map(([x, y], i) => (
<PolyPoint index={i} onDragend={handleDragEnd} onRemove={handleRemovePoint} x={x} y={y} /> <PolyPoint
boundingRef={boundingRef}
index={i}
onMove={handleMovePoint}
onRemove={handleRemovePoint}
x={x}
y={y}
/>
))} ))}
<svg width="100%" height="100%" className="absolute" style="top: 0; left: 0; right: 0; bottom: 0;"> <svg
ref={boundingRef}
width="100%"
height="100%"
className="absolute"
style="top: 0; left: 0; right: 0; bottom: 0;"
>
{!scaledPoints ? null : ( {!scaledPoints ? null : (
<g> <g>
<polyline points={polylinePointsToPolyline(scaledPoints)} fill="rgba(244,0,0,0.5)" /> <polyline points={polylinePointsToPolyline(scaledPoints)} fill="rgba(244,0,0,0.5)" />
@ -235,21 +241,28 @@ function polylinePointsToPolyline(polylinePoints) {
} }
const PolyPointRadius = 10; const PolyPointRadius = 10;
function PolyPoint({ index, x, y, onDragend, onRemove }) { function PolyPoint({ boundingRef, index, x, y, onMove, onRemove }) {
const [hidden, setHidden] = useState(false); const [hidden, setHidden] = useState(false);
const handleDragStart = useCallback(() => {
setHidden(true); const handleDragOver = useCallback(
}, [setHidden]);
const handleDrag = useCallback(
(event) => { (event) => {
const { offsetX, offsetY } = event; if (event.target !== boundingRef.current && !boundingRef.current.contains(event.target)) {
onDragend(index, event.offsetX + x - PolyPointRadius, event.offsetY + y - PolyPointRadius); return;
}
onMove(index, event.layerX, event.layerY - PolyPointRadius);
}, },
[onDragend, index] [onMove, index, boundingRef.current]
); );
const handleDragStart = useCallback(() => {
boundingRef.current && boundingRef.current.addEventListener('dragover', handleDragOver, false);
setHidden(true);
}, [setHidden, boundingRef.current, handleDragOver]);
const handleDragEnd = useCallback(() => { const handleDragEnd = useCallback(() => {
boundingRef.current && boundingRef.current.removeEventListener('dragover', handleDragOver);
setHidden(false); setHidden(false);
}, [setHidden]); }, [setHidden, boundingRef.current, handleDragOver]);
const handleRightClick = useCallback( const handleRightClick = useCallback(
(event) => { (event) => {
@ -272,7 +285,6 @@ function PolyPoint({ index, x, y, onDragend, onRemove }) {
onclick={handleClick} onclick={handleClick}
oncontextmenu={handleRightClick} oncontextmenu={handleRightClick}
ondragstart={handleDragStart} ondragstart={handleDragStart}
ondrag={handleDrag}
ondragend={handleDragEnd} ondragend={handleDragEnd}
/> />
); );