Archived
style/ui changes
This commit is contained in:
1 parent
a44056c590
commit
749652163b
14 files changed
+187
-26
No files matched your search
@@ -27,8 +27,10 @@
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="app">
|
||||
<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>
|
||||
<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-backend-webgl"></script>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,5 @@
|
||||
@media screen and (max-width: 768px) {
|
||||
.container {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
width: 100%;
|
||||
@@ -18,4 +18,6 @@
|
||||
padding: 10px;
|
||||
clip-path: inset(0 0 0 0);
|
||||
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) => {
|
||||
const container = document.createElement("div");
|
||||
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";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -1,39 +1,29 @@
|
||||
import { FC, useContext } from "react";
|
||||
import { spawnDialog } from "../../AlertDialog/spawnDialog";
|
||||
import { spawnDialog } from "../AlertDialog/spawnDialog";
|
||||
import { modelCtx } from "../../constants";
|
||||
import { getVideoFrame } from "../../utils/getVideoFrame";
|
||||
import { About } from "../About";
|
||||
import { Icon } from "../Icon";
|
||||
import { Results } from "../Results";
|
||||
import style from "./index.module.scss";
|
||||
|
||||
export const Overlay: FC = () => {
|
||||
const model = useContext(modelCtx);
|
||||
|
||||
return (
|
||||
<div className={style.container}>
|
||||
<button
|
||||
className={style.aboutBtn}
|
||||
onClick={() =>
|
||||
spawnDialog((close) => {
|
||||
return <></>;
|
||||
})
|
||||
}
|
||||
>
|
||||
<button className={style.aboutBtn} onClick={() => spawnDialog((c) => <About cfn={c} />)}>
|
||||
<Icon type="info-circle-fill" size={30} />
|
||||
</button>
|
||||
<button
|
||||
className={style.captureBtn}
|
||||
onClick={async () => {
|
||||
const can = getVideoFrame(document.querySelector("#video-feed") as HTMLVideoElement);
|
||||
const r = await model?.classify(can);
|
||||
console.log(r);
|
||||
spawnDialog((c) => {
|
||||
return (
|
||||
<>
|
||||
<img width={500} alt={r?.[0].className} src={can.toDataURL("image/png")} />
|
||||
<p>{r?.[0].className}</p>
|
||||
<p>{r?.[0].probability}</p>
|
||||
<button onClick={c}>close</button>
|
||||
</>
|
||||
<modelCtx.Provider value={model}>
|
||||
<Results />
|
||||
<button style={{ width: "100%" }} onClick={c} className="btn-inverse">
|
||||
Zamknij
|
||||
</button>
|
||||
</modelCtx.Provider>
|
||||
);
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
.loadingLbl {
|
||||
text-align: center;
|
||||
}
|
||||
.loadingCircle {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -40,6 +40,29 @@ button {
|
||||
&:hover {
|
||||
background-color: $text;
|
||||
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
@@ -7,7 +7,14 @@ import { modelCtx, videoStreamCtx } from "./constants";
|
||||
import { load as loadModel } from "@tensorflow-models/mobilenet";
|
||||
|
||||
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 =
|
||||
(await window.navigator.mediaDevices?.getUserMedia({ video: { facingMode: "environment" } }).catch((e) => {
|
||||
if (e instanceof DOMException) {
|
||||
@@ -15,7 +22,7 @@ const main = async () => {
|
||||
}
|
||||
return null;
|
||||
})) ?? null;
|
||||
console.log("Loading AI model...");
|
||||
infoLabel.innerHTML = "Wczytywanie aplikacji...";
|
||||
const model = await loadModel();
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
@@ -25,7 +32,7 @@ const main = async () => {
|
||||
</videoStreamCtx.Provider>
|
||||
</modelCtx.Provider>
|
||||
</React.StrictMode>,
|
||||
document.querySelector("#app")
|
||||
appContainer
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user