WIP reordering tiles

This commit is contained in:
Robert Long 2021-08-13 16:27:19 -07:00
commit d763b4a83c

View file

@ -1,10 +1,25 @@
import React, { useCallback, useEffect, useRef, useState } from "react"; import React, { useCallback, useEffect, useRef, useState } from "react";
import classNames from "classnames";
import { useDrag } from "react-use-gesture"; import { useDrag } from "react-use-gesture";
import { useSprings, useTransition, animated } from "@react-spring/web"; import { useSprings, animated } from "@react-spring/web";
import styles from "./GridDemo.module.css"; import styles from "./GridDemo.module.css";
import useMeasure from "react-use-measure"; import useMeasure from "react-use-measure";
function isInside([x, y], dragTile, targetTile) {
const cursorX = dragTile.x + x;
const cursorY = dragTile.y + y;
const left = targetTile.x;
const top = targetTile.y;
const bottom = targetTile.y + targetTile.height;
const right = targetTile.x + targetTile.width;
if (cursorX < left || cursorX > right || cursorY < top || cursorY > bottom) {
return false;
}
return true;
}
export function GridDemo() { export function GridDemo() {
const tileKey = useRef(0); const tileKey = useRef(0);
const [stream, setStream] = useState(); const [stream, setStream] = useState();
@ -14,6 +29,10 @@ export function GridDemo() {
}); });
const draggingTileRef = useRef(null); const draggingTileRef = useRef(null);
// Contains tile indices
// Tiles are displayed in the order that they appear
const tileOrderRef = useRef([]);
const [gridRef, gridBounds] = useMeasure(); const [gridRef, gridBounds] = useMeasure();
const getTilePositions = useCallback((tiles, gridBounds) => { const getTilePositions = useCallback((tiles, gridBounds) => {
@ -111,6 +130,7 @@ export function GridDemo() {
const startWebcam = useCallback(async () => { const startWebcam = useCallback(async () => {
const stream = await navigator.mediaDevices.getUserMedia({ video: true }); const stream = await navigator.mediaDevices.getUserMedia({ video: true });
setStream(stream); setStream(stream);
tileOrderRef.current.push(tileOrderRef.current.length);
setTileState(() => { setTileState(() => {
const tiles = [{ stream, key: tileKey.current++ }]; const tiles = [{ stream, key: tileKey.current++ }];
const tilePositions = getTilePositions(tiles, gridBounds); const tilePositions = getTilePositions(tiles, gridBounds);
@ -121,6 +141,8 @@ export function GridDemo() {
const addTile = useCallback(() => { const addTile = useCallback(() => {
const newStream = stream.clone(); const newStream = stream.clone();
tileOrderRef.current.push(tileOrderRef.current.length);
setTileState(({ tiles }) => { setTileState(({ tiles }) => {
const newTiles = [ const newTiles = [
...tiles, ...tiles,
@ -132,6 +154,7 @@ export function GridDemo() {
}, [stream, gridBounds]); }, [stream, gridBounds]);
const removeTile = useCallback(() => { const removeTile = useCallback(() => {
tileOrderRef.current.pop();
setTileState(({ tiles }) => { setTileState(({ tiles }) => {
const newTiles = [...tiles]; const newTiles = [...tiles];
newTiles.pop(); newTiles.pop();
@ -148,11 +171,12 @@ export function GridDemo() {
}, [gridBounds]); }, [gridBounds]);
const animate = useCallback( const animate = useCallback(
(index) => { (order) => (index) => {
const tilePosition = tilePositions[index]; const tileIndex = order[index];
const tilePosition = tilePositions[tileIndex];
const draggingTile = draggingTileRef.current; const draggingTile = draggingTileRef.current;
const dragging = const dragging =
draggingTileRef.current && index === draggingTileRef.current.index; draggingTileRef.current && tileIndex === draggingTileRef.current.index;
if (dragging) { if (dragging) {
return { return {
@ -178,32 +202,65 @@ export function GridDemo() {
[tilePositions] [tilePositions]
); );
const [springs, api] = useSprings(tiles.length, animate, [tilePositions]); const [springs, api] = useSprings(
tiles.length,
animate(tileOrderRef.current),
[tilePositions]
);
const bind = useDrag(({ args: [index], active, movement }) => {
let order = tileOrderRef.current;
let dragIndex = index;
// const tileIndex = tileOrderRef.current[index];
// const tilePosition = tilePositions[tileIndex];
// for (let i = 0; i < tileOrderRef.current.length; i++) {
// if (i === index) {
// continue;
// }
// const hoverTileIndex = tileOrderRef.current[i];
// const hoverTilePosition = tilePositions[hoverTileIndex];
// if (isInside(movement, tilePosition, hoverTilePosition)) {
// order = [...tileOrderRef.current];
// const [toBeMoved] = order.splice(i, 1);
// order.splice(index, 0, toBeMoved);
// dragIndex = i;
// break;
// }
// }
const bind = useDrag(({ args: [index], active, movement: [x, y] }) => {
if (active) { if (active) {
draggingTileRef.current = { draggingTileRef.current = {
index, index: dragIndex,
x, x: movement[0],
y, y: movement[1],
}; };
} else { } else {
draggingTileRef.current = null; draggingTileRef.current = null;
//tileOrderRef.current = order;
} }
api.start(animate); api.start(animate(order));
}); });
return ( return (
<div className={styles.gridDemo}> <div className={styles.gridDemo}>
<div className={styles.buttons}> <div className={styles.buttons}>
{!stream && <button onClick={startWebcam}>Start Webcam</button>} {!stream && <button onClick={startWebcam}>Start Webcam</button>}
{stream && <button onClick={addTile}>Add Tile</button>} {stream && tiles.length < 12 && (
{stream && <button onClick={removeTile}>Remove Tile</button>} <button onClick={addTile}>Add Tile</button>
)}
{stream && tiles.length > 0 && (
<button onClick={removeTile}>Remove Tile</button>
)}
</div> </div>
<div className={styles.grid} ref={gridRef}> <div className={styles.grid} ref={gridRef}>
{springs.map(({ shadow, ...style }, i) => { {springs.map(({ shadow, ...style }, i) => {
const tile = tiles[i]; const tileIndex = tileOrderRef.current[i];
const tile = tiles[tileIndex];
return ( return (
<ParticipantTile <ParticipantTile