Finished grid demo
This commit is contained in:
parent
e68c9bee4a
commit
f303cb345f
4 changed files with 88 additions and 30 deletions
27
package-lock.json
generated
27
package-lock.json
generated
|
@ -11,6 +11,7 @@
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"color-hash": "^2.0.1",
|
"color-hash": "^2.0.1",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
|
"lodash-move": "^1.1.1",
|
||||||
"matrix-js-sdk": "^12.0.1",
|
"matrix-js-sdk": "^12.0.1",
|
||||||
"react": "^17.0.0",
|
"react": "^17.0.0",
|
||||||
"react-dom": "^17.0.0",
|
"react-dom": "^17.0.0",
|
||||||
|
@ -1099,6 +1100,19 @@
|
||||||
"verror": "1.10.0"
|
"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": {
|
"node_modules/loglevel": {
|
||||||
"version": "1.7.1",
|
"version": "1.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
|
||||||
|
@ -2530,6 +2544,19 @@
|
||||||
"verror": "1.10.0"
|
"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": {
|
"loglevel": {
|
||||||
"version": "1.7.1",
|
"version": "1.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"color-hash": "^2.0.1",
|
"color-hash": "^2.0.1",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
|
"lodash-move": "^1.1.1",
|
||||||
"matrix-js-sdk": "^12.0.1",
|
"matrix-js-sdk": "^12.0.1",
|
||||||
"react": "^17.0.0",
|
"react": "^17.0.0",
|
||||||
"react-dom": "^17.0.0",
|
"react-dom": "^17.0.0",
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { useDrag } from "react-use-gesture";
|
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 styles from "./GridDemo.module.css";
|
||||||
import useMeasure from "react-use-measure";
|
import useMeasure from "react-use-measure";
|
||||||
|
import moveArrItem from "lodash-move";
|
||||||
|
|
||||||
function isInside([x, y], targetTile) {
|
function isInside([x, y], targetTile) {
|
||||||
const left = targetTile.x;
|
const left = targetTile.x;
|
||||||
|
@ -128,7 +129,9 @@ export function GridDemo() {
|
||||||
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);
|
tileOrderRef.current.push(tileOrderRef.current.length);
|
||||||
|
|
||||||
setTileState(() => {
|
setTileState(() => {
|
||||||
|
console.log("startWebcam");
|
||||||
const tiles = [{ stream, key: tileKey.current++, remove: false }];
|
const tiles = [{ stream, key: tileKey.current++, remove: false }];
|
||||||
const tilePositions = getTilePositions(tiles, gridBounds);
|
const tilePositions = getTilePositions(tiles, gridBounds);
|
||||||
return { tiles, tilePositions };
|
return { tiles, tilePositions };
|
||||||
|
@ -141,6 +144,7 @@ export function GridDemo() {
|
||||||
tileOrderRef.current.push(tileOrderRef.current.length);
|
tileOrderRef.current.push(tileOrderRef.current.length);
|
||||||
|
|
||||||
setTileState(({ tiles }) => {
|
setTileState(({ tiles }) => {
|
||||||
|
console.log("addTile");
|
||||||
const newTiles = [
|
const newTiles = [
|
||||||
...tiles,
|
...tiles,
|
||||||
{ stream: newStream, key: tileKey.current++, remove: false },
|
{ stream: newStream, key: tileKey.current++, remove: false },
|
||||||
|
@ -193,10 +197,11 @@ export function GridDemo() {
|
||||||
}, [gridBounds]);
|
}, [gridBounds]);
|
||||||
|
|
||||||
const animate = useCallback(
|
const animate = useCallback(
|
||||||
(order) => (index) => {
|
(tileIndex) => {
|
||||||
const tileIndex = order[index];
|
const tileOrder = tileOrderRef.current;
|
||||||
|
const order = tileOrder.indexOf(tileIndex);
|
||||||
const tile = tiles[tileIndex];
|
const tile = tiles[tileIndex];
|
||||||
const tilePosition = tilePositions[tileIndex];
|
const tilePosition = tilePositions[order];
|
||||||
const draggingTile = draggingTileRef.current;
|
const draggingTile = draggingTileRef.current;
|
||||||
const dragging = draggingTile && tile.key === draggingTile.key;
|
const dragging = draggingTile && tile.key === draggingTile.key;
|
||||||
const remove = tile.remove;
|
const remove = tile.remove;
|
||||||
|
@ -205,8 +210,8 @@ export function GridDemo() {
|
||||||
return {
|
return {
|
||||||
width: tilePosition.width,
|
width: tilePosition.width,
|
||||||
height: tilePosition.height,
|
height: tilePosition.height,
|
||||||
x: tilePosition.x + draggingTile.x,
|
x: draggingTile.offsetX + draggingTile.x,
|
||||||
y: tilePosition.y + draggingTile.y,
|
y: draggingTile.offsetY + draggingTile.y,
|
||||||
scale: 1.1,
|
scale: 1.1,
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
|
@ -237,47 +242,62 @@ export function GridDemo() {
|
||||||
[tiles, tilePositions]
|
[tiles, tilePositions]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [springs, api] = useSprings(
|
const [springs, api] = useSprings(tiles.length, animate, [
|
||||||
tiles.length,
|
tilePositions,
|
||||||
animate(tileOrderRef.current),
|
tiles,
|
||||||
[tilePositions, tiles]
|
]);
|
||||||
);
|
|
||||||
|
|
||||||
const bind = useDrag(({ args: [index], active, xy, movement }) => {
|
const bind = useDrag(({ args: [key], active, xy, movement }) => {
|
||||||
let order = tileOrderRef.current;
|
const tileOrder = tileOrderRef.current;
|
||||||
|
|
||||||
const tileIndex = tileOrderRef.current[index];
|
const dragTileIndex = tiles.findIndex((tile) => tile.key === key);
|
||||||
const tile = tiles[tileIndex];
|
const dragTile = tiles[dragTileIndex];
|
||||||
|
|
||||||
|
const dragTileOrder = tileOrder.indexOf(dragTileIndex);
|
||||||
|
|
||||||
const cursorPosition = [xy[0] - gridBounds.left, xy[1] - gridBounds.top];
|
const cursorPosition = [xy[0] - gridBounds.left, xy[1] - gridBounds.top];
|
||||||
|
|
||||||
for (let i = 0; i < tileOrderRef.current.length; i++) {
|
for (
|
||||||
if (i === index) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hoverTileIndex = tileOrderRef.current[i];
|
|
||||||
const hoverTilePosition = tilePositions[hoverTileIndex];
|
|
||||||
|
|
||||||
if (isInside(cursorPosition, hoverTilePosition)) {
|
if (isInside(cursorPosition, hoverTilePosition)) {
|
||||||
// TODO: Figure out swapping
|
tileOrderRef.current = moveArrItem(
|
||||||
// order[i] = tileIndex;
|
tileOrder,
|
||||||
// order[index] = i;
|
dragTileOrder,
|
||||||
|
hoverTileOrder
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
draggingTileRef.current = {
|
if (!draggingTileRef.current) {
|
||||||
key: tile.key,
|
const tilePosition = tilePositions[dragTileOrder];
|
||||||
x: movement[0],
|
|
||||||
y: movement[1],
|
draggingTileRef.current = {
|
||||||
};
|
key: dragTile.key,
|
||||||
|
offsetX: tilePosition.x,
|
||||||
|
offsetY: tilePosition.y,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
draggingTileRef.current.x = movement[0];
|
||||||
|
draggingTileRef.current.y = movement[1];
|
||||||
} else {
|
} else {
|
||||||
draggingTileRef.current = null;
|
draggingTileRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
api.start(animate(order));
|
api.start(animate);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -300,7 +320,7 @@ export function GridDemo() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ParticipantTile
|
<ParticipantTile
|
||||||
{...bind(i)}
|
{...bind(tile.key)}
|
||||||
key={tile.key}
|
key={tile.key}
|
||||||
style={{
|
style={{
|
||||||
boxShadow: shadow.to(
|
boxShadow: shadow.to(
|
||||||
|
@ -308,6 +328,7 @@ export function GridDemo() {
|
||||||
),
|
),
|
||||||
...style,
|
...style,
|
||||||
}}
|
}}
|
||||||
|
tileKey={tile.key}
|
||||||
{...tile}
|
{...tile}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -331,6 +352,7 @@ function ParticipantTile({ style, stream, remove, tileKey, ...rest }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<animated.div className={styles.participantTile} style={style} {...rest}>
|
<animated.div className={styles.participantTile} style={style} {...rest}>
|
||||||
|
<div className={styles.participantName}>{tileKey}</div>
|
||||||
<video ref={videoRef} playsInline />
|
<video ref={videoRef} playsInline />
|
||||||
</animated.div>
|
</animated.div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,3 +27,11 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.participantName {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
padding: 8px 24px;
|
||||||
|
}
|
Loading…
Reference in a new issue