style/ui changes

This commit is contained in:
mmacierzanka committed 2021-12-10 18:12:32 +01:00
1 parent a44056c590
commit 749652163b
14 files changed
+188 -27

No files matched your search

+3 -1
View File
@@ -27,7 +27,9 @@
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<div id="app"> <div id="app">
<img src="%PUBLIC_URL%/logo192.png" alt="Trash Recognizer logo" /> <div id="loading-cont" style="text-align: center; display: flex; flex-direction: column; column-gap: 10px; justify-content: center; align-items: center">
<img src="%PUBLIC_URL%/logo192.png" alt="Trash Recognizer logo" />
</div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core"></script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter"></script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter"></script>
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+5
View File
@@ -0,0 +1,5 @@
@media screen and (max-width: 768px) {
.container {
flex-direction: column !important;
}
}
+20
View File
@@ -0,0 +1,20 @@
import { FC } from "react";
import { Box } from "../Box";
import { CreditTile } from "../CreditTile";
import style from "./index.module.scss";
export const About: FC<{ cfn: (d: any) => void }> = (props) => {
return (
<Box direction="column" gap={10} horizontalAlignment="center" verticalAlignment="center">
<h1>Trash helper</h1>
<Box className={style.container} direction="row" gap={5} horizontalAlignment={"center"} verticalAlignment="center">
<CreditTile title="GRZ4NA" imageUrl="https://avatars.githubusercontent.com/u/74425958?v=4" gh="grz4na" delay={0} />
<CreditTile title="makoteq" imageUrl="https://avatars.githubusercontent.com/u/42750440?v=4" gh="makoteq" delay={100} />
<CreditTile title="drgoodcat" imageUrl="https://avatars.githubusercontent.com/u/60068941?v=4" gh="drgoodcat" delay={200} />
</Box>
<button style={{ width: "100%" }} onClick={props.cfn} className="btn-inverse">
Zamknij
</button>
</Box>
);
};
@@ -1,4 +1,4 @@
@import "../index.scss"; @import "../../index.scss";
.container { .container {
width: 100%; width: 100%;
@@ -18,4 +18,6 @@
padding: 10px; padding: 10px;
clip-path: inset(0 0 0 0); clip-path: inset(0 0 0 0);
position: relative; position: relative;
border: 1.5px solid lighten($background, 10%);
box-shadow: 0 0 0.5px black;
} }
File renamed without changes.
@@ -5,7 +5,7 @@ import { AlertDialog } from "./index";
export const spawnDialog = async (elements: (close: (data: any) => void) => ReactNode, windowStyles?: CSSProperties) => { export const spawnDialog = async (elements: (close: (data: any) => void) => ReactNode, windowStyles?: CSSProperties) => {
const container = document.createElement("div"); const container = document.createElement("div");
const backgroundColor = "rgba(0,0,0,0.75)"; const backgroundColor = "rgba(0,0,0,0.75)";
const animationDuration = 300; const animationDuration = 250;
(container.style as any) = "display: block; overflow: hidden; width: 100vw; height: 100vh; z-index: 20; position: fixed; top: 0; left: 0"; (container.style as any) = "display: block; overflow: hidden; width: 100vw; height: 100vh; z-index: 20; position: fixed; top: 0; left: 0";
@@ -0,0 +1,45 @@
@import "../../index.scss";
.container {
text-decoration: none;
animation: in-anim 0.3s ease-out both;
transform: translateY(15px);
opacity: 0;
transition: all 0.3s ease;
background-color: transparent;
border-radius: 15px;
padding: 10px;
border: solid 1px transparent;
display: block;
&:hover {
background-color: rgba(200, 200, 200, 0.2);
border: solid 1px lighten(rgba(200, 200, 200, 0.2), 10%);
}
}
.img {
border-radius: 50%;
padding: 10px;
transition: transform 0.2s ease-out;
width: 10vh;
height: 10vh;
.container:hover & {
transform: scale(1.1);
}
}
.title {
font-size: 20px;
color: $text;
}
@keyframes in-anim {
from {
transform: translateY(15px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
+20
View File
@@ -0,0 +1,20 @@
import { FC } from "react";
import { Box } from "../Box";
import style from "./index.module.scss";
export const CreditTile: FC<{ title: string; imageUrl?: string; gh?: string; delay?: number }> = (props) => {
return (
<a
target={"_blank"}
style={{ animationDelay: `${props.delay ? props.delay + 300 : 300}ms` }}
className={style.container}
rel="noreferrer"
href={`https://github.com/${props.gh}`}
>
<Box gap={5} direction="column" verticalAlignment="center" horizontalAlignment="center">
<img className={style.img} src={props.imageUrl} alt={props.title} />
<div className={style.title}>{props.title}</div>
</Box>
</a>
);
};
+10 -20
View File
@@ -1,39 +1,29 @@
import { FC, useContext } from "react"; import { FC, useContext } from "react";
import { spawnDialog } from "../../AlertDialog/spawnDialog"; import { spawnDialog } from "../AlertDialog/spawnDialog";
import { modelCtx } from "../../constants"; import { modelCtx } from "../../constants";
import { getVideoFrame } from "../../utils/getVideoFrame"; import { About } from "../About";
import { Icon } from "../Icon"; import { Icon } from "../Icon";
import { Results } from "../Results";
import style from "./index.module.scss"; import style from "./index.module.scss";
export const Overlay: FC = () => { export const Overlay: FC = () => {
const model = useContext(modelCtx); const model = useContext(modelCtx);
return ( return (
<div className={style.container}> <div className={style.container}>
<button <button className={style.aboutBtn} onClick={() => spawnDialog((c) => <About cfn={c} />)}>
className={style.aboutBtn}
onClick={() =>
spawnDialog((close) => {
return <></>;
})
}
>
<Icon type="info-circle-fill" size={30} /> <Icon type="info-circle-fill" size={30} />
</button> </button>
<button <button
className={style.captureBtn} className={style.captureBtn}
onClick={async () => { onClick={async () => {
const can = getVideoFrame(document.querySelector("#video-feed") as HTMLVideoElement);
const r = await model?.classify(can);
console.log(r);
spawnDialog((c) => { spawnDialog((c) => {
return ( return (
<> <modelCtx.Provider value={model}>
<img width={500} alt={r?.[0].className} src={can.toDataURL("image/png")} /> <Results />
<p>{r?.[0].className}</p> <button style={{ width: "100%" }} onClick={c} className="btn-inverse">
<p>{r?.[0].probability}</p> Zamknij
<button onClick={c}>close</button> </button>
</> </modelCtx.Provider>
); );
}); });
}} }}
+15
View File
@@ -0,0 +1,15 @@
.loadingLbl {
text-align: center;
}
.loadingCircle {
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
+32
View File
@@ -0,0 +1,32 @@
import { FC, useContext, useEffect, useState } from "react";
import { modelCtx } from "../../constants";
import { getVideoFrame } from "../../utils/getVideoFrame";
import style from "./index.module.scss";
import loadingCircle from "../../assets/loadingCircle.png";
import { Box } from "../Box";
export const Results: FC<{}> = (_) => {
const [el, uel] = useState(
<Box direction="column" gap={10} verticalAlignment="center" horizontalAlignment="center">
<img className={style.loadingCircle} src={loadingCircle} width={100} height={100} />
<h1 className={style.loadingLbl}>Trwa analizowanie zdjęcia...</h1>
</Box>
);
const model = useContext(modelCtx);
useEffect(() => {
const can = getVideoFrame(document.querySelector("#video-feed") as HTMLVideoElement);
model?.classify(can).then((r) => {
console.log(r);
uel(
<>
<img height={500} alt={r?.[0].className} src={can.toDataURL("image/png")} />
<p>{r?.[0].className}</p>
<p>{r?.[0].probability}</p>
</>
);
});
}, [model]);
return el;
};
+24 -1
View File
@@ -40,6 +40,29 @@ button {
&:hover { &:hover {
background-color: $text; background-color: $text;
color: black; color: black;
border-color: darken($text, 10%); border-color: darken($text, 30%);
} }
} }
.btn-inverse {
border: none;
padding: 10px;
box-shadow: none;
border-radius: $borderRadius;
background-color: $text;
color: black;
transition: all $transitionDuration ease;
border: 1.5px solid darken($text, 30%);
box-shadow: 0 0 0.5px black;
cursor: pointer;
&:hover {
background-color: $background;
color: $text;
border-color: lighten($background, 10%);
}
}
::selection {
background-color: darken($text, 20%);
color: black;
}
+10 -3
View File
@@ -7,7 +7,14 @@ import { modelCtx, videoStreamCtx } from "./constants";
import { load as loadModel } from "@tensorflow-models/mobilenet"; import { load as loadModel } from "@tensorflow-models/mobilenet";
const main = async () => { const main = async () => {
console.log("Requesting camera access..."); const appContainer = document.querySelector("#app");
const infoLabel = document.createElement("p");
infoLabel.style.color = "white";
infoLabel.style.fontSize = "25px";
infoLabel.style.fontFamily = "Arial, sans-serif";
infoLabel.style.fontWeight = "100";
infoLabel.innerHTML = "Oczekiwanie na uprawnienia dostępu do kamery...";
appContainer?.children[0].appendChild(infoLabel);
const videoStream = const videoStream =
(await window.navigator.mediaDevices?.getUserMedia({ video: { facingMode: "environment" } }).catch((e) => { (await window.navigator.mediaDevices?.getUserMedia({ video: { facingMode: "environment" } }).catch((e) => {
if (e instanceof DOMException) { if (e instanceof DOMException) {
@@ -15,7 +22,7 @@ const main = async () => {
} }
return null; return null;
})) ?? null; })) ?? null;
console.log("Loading AI model..."); infoLabel.innerHTML = "Wczytywanie aplikacji...";
const model = await loadModel(); const model = await loadModel();
ReactDOM.render( ReactDOM.render(
<React.StrictMode> <React.StrictMode>
@@ -25,7 +32,7 @@ const main = async () => {
</videoStreamCtx.Provider> </videoStreamCtx.Provider>
</modelCtx.Provider> </modelCtx.Provider>
</React.StrictMode>, </React.StrictMode>,
document.querySelector("#app") appContainer
); );
}; };