Finished grid demo

This commit is contained in:
Robert Long 2021-08-16 16:18:45 -07:00
parent e68c9bee4a
commit f303cb345f
4 changed files with 88 additions and 30 deletions

27
package-lock.json generated
View file

@ -11,6 +11,7 @@
"classnames": "^2.3.1",
"color-hash": "^2.0.1",
"events": "^3.3.0",
"lodash-move": "^1.1.1",
"matrix-js-sdk": "^12.0.1",
"react": "^17.0.0",
"react-dom": "^17.0.0",
@ -1099,6 +1100,19 @@
"verror": "1.10.0"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash-move": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/lodash-move/-/lodash-move-1.1.1.tgz",
"integrity": "sha1-WfduDxrFfm2Gg/UxvsB8W26k40g=",
"dependencies": {
"lodash": "^4.6.1"
}
},
"node_modules/loglevel": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
@ -2530,6 +2544,19 @@
"verror": "1.10.0"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash-move": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/lodash-move/-/lodash-move-1.1.1.tgz",
"integrity": "sha1-WfduDxrFfm2Gg/UxvsB8W26k40g=",
"requires": {
"lodash": "^4.6.1"
}
},
"loglevel": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",

View file

@ -10,6 +10,7 @@
"classnames": "^2.3.1",
"color-hash": "^2.0.1",
"events": "^3.3.0",
"lodash-move": "^1.1.1",
"matrix-js-sdk": "^12.0.1",
"react": "^17.0.0",
"react-dom": "^17.0.0",

View file

@ -1,8 +1,9 @@
import React, { useCallback, useEffect, useRef, useState } from "react";
import { useDrag } from "react-use-gesture";
import { useSprings, animated, useSpring } from "@react-spring/web";
import { useSprings, animated } from "@react-spring/web";
import styles from "./GridDemo.module.css";
import useMeasure from "react-use-measure";
import moveArrItem from "lodash-move";
function isInside([x, y], targetTile) {
const left = targetTile.x;
@ -128,7 +129,9 @@ export function GridDemo() {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
setStream(stream);
tileOrderRef.current.push(tileOrderRef.current.length);
setTileState(() => {
console.log("startWebcam");
const tiles = [{ stream, key: tileKey.current++, remove: false }];
const tilePositions = getTilePositions(tiles, gridBounds);
return { tiles, tilePositions };
@ -141,6 +144,7 @@ export function GridDemo() {
tileOrderRef.current.push(tileOrderRef.current.length);
setTileState(({ tiles }) => {
console.log("addTile");
const newTiles = [
...tiles,
{ stream: newStream, key: tileKey.current++, remove: false },
@ -193,10 +197,11 @@ export function GridDemo() {
}, [gridBounds]);
const animate = useCallback(
(order) => (index) => {
const tileIndex = order[index];
(tileIndex) => {
const tileOrder = tileOrderRef.current;
const order = tileOrder.indexOf(tileIndex);
const tile = tiles[tileIndex];
const tilePosition = tilePositions[tileIndex];
const tilePosition = tilePositions[order];
const draggingTile = draggingTileRef.current;
const dragging = draggingTile && tile.key === draggingTile.key;
const remove = tile.remove;
@ -205,8 +210,8 @@ export function GridDemo() {
return {
width: tilePosition.width,
height: tilePosition.height,
x: tilePosition.x + draggingTile.x,
y: tilePosition.y + draggingTile.y,
x: draggingTile.offsetX + draggingTile.x,
y: draggingTile.offsetY + draggingTile.y,
scale: 1.1,
opacity: 1,
zIndex: 1,
@ -237,47 +242,62 @@ export function GridDemo() {
[tiles, tilePositions]
);
const [springs, api] = useSprings(
tiles.length,
animate(tileOrderRef.current),
[tilePositions, tiles]
);
const [springs, api] = useSprings(tiles.length, animate, [
tilePositions,
tiles,
]);
const bind = useDrag(({ args: [index], active, xy, movement }) => {
let order = tileOrderRef.current;
const bind = useDrag(({ args: [key], active, xy, movement }) => {
const tileOrder = tileOrderRef.current;
const tileIndex = tileOrderRef.current[index];
const tile = tiles[tileIndex];
const dragTileIndex = tiles.findIndex((tile) => tile.key === key);
const dragTile = tiles[dragTileIndex];
const dragTileOrder = tileOrder.indexOf(dragTileIndex);
const cursorPosition = [xy[0] - gridBounds.left, xy[1] - gridBounds.top];
for (let i = 0; i < tileOrderRef.current.length; i++) {
if (i === index) {
for (
let hoverTileIndex = 0;
hoverTileIndex < tiles.length;
hoverTileIndex++
) {
const hoverTile = tiles[hoverTileIndex];
const hoverTileOrder = tileOrder.indexOf(hoverTileIndex);
const hoverTilePosition = tilePositions[hoverTileOrder];
if (hoverTile.key === key) {
continue;
}
const hoverTileIndex = tileOrderRef.current[i];
const hoverTilePosition = tilePositions[hoverTileIndex];
if (isInside(cursorPosition, hoverTilePosition)) {
// TODO: Figure out swapping
// order[i] = tileIndex;
// order[index] = i;
tileOrderRef.current = moveArrItem(
tileOrder,
dragTileOrder,
hoverTileOrder
);
break;
}
}
if (active) {
draggingTileRef.current = {
key: tile.key,
x: movement[0],
y: movement[1],
};
if (!draggingTileRef.current) {
const tilePosition = tilePositions[dragTileOrder];
draggingTileRef.current = {
key: dragTile.key,
offsetX: tilePosition.x,
offsetY: tilePosition.y,
};
}
draggingTileRef.current.x = movement[0];
draggingTileRef.current.y = movement[1];
} else {
draggingTileRef.current = null;
}
api.start(animate(order));
api.start(animate);
});
return (
@ -300,7 +320,7 @@ export function GridDemo() {
return (
<ParticipantTile
{...bind(i)}
{...bind(tile.key)}
key={tile.key}
style={{
boxShadow: shadow.to(
@ -308,6 +328,7 @@ export function GridDemo() {
),
...style,
}}
tileKey={tile.key}
{...tile}
/>
);
@ -331,6 +352,7 @@ function ParticipantTile({ style, stream, remove, tileKey, ...rest }) {
return (
<animated.div className={styles.participantTile} style={style} {...rest}>
<div className={styles.participantName}>{tileKey}</div>
<video ref={videoRef} playsInline />
</animated.div>
);

View file

@ -26,4 +26,12 @@
width: 100%;
height: 100%;
object-fit: cover;
}
.participantName {
position: absolute;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.2);
padding: 8px 24px;
}