drawings-to-human / frontend /src /lib /ResultCanvas.svelte
radames's picture
center and status message
fd7fe93
<script lang="ts">
let canvas: HTMLCanvasElement;
import { API } from '../data';
import { nanoid } from 'nanoid';
import type { Params } from '../types';
import {
selectedParams,
generateHuman,
currentCanvas,
resultImage,
saveResult
} from '$lib/store';
$: (async () => {
if ($generateHuman) {
const results = await predict($currentCanvas.toDataURL(), $selectedParams);
if (results) {
$resultImage = results.data[0];
}
$generateHuman = false;
}
})();
$: (async () => {
if ($saveResult) {
const results = await saveImage($resultImage);
$saveResult = false;
}
})();
let predictStatus: string = '';
async function saveImage(base64Image: string) {
return new Promise((resolve, reject) => {
try {
const a = document.createElement('a');
a.download = `sucess-${Date.now()}.png`;
a.target = '_self';
a.onclick = async (e) => {
if (a.href) {
URL.revokeObjectURL(a.href);
}
a.href = base64Image;
};
requestAnimationFrame(() => {
console.log('Downloading image.');
a.click();
resolve(null);
});
} catch (err) {
reject();
}
});
}
async function predict(base64Image: string, { texture, steps, seed }: Params) {
const session = nanoid(11);
let hash, queue_position;
let b = 0;
predictStatus = 'Generating';
const controller = new AbortController();
// invalidation.then(() => {
// controller.abort();
// });
await fetch(API + '/api/queue/push/', {
signal: controller.signal,
headers: { 'Content-Type': 'application/json' },
method: 'POST',
body: JSON.stringify({
fn_index: 2,
data: [base64Image, texture, steps, Number(seed)],
action: 'predict',
session_hash: session
})
})
.then(async (res) => {
const data = await res.json();
({ hash, queue_position } = data);
})
.catch((err) => {
console.log(err);
});
let timeout = 0;
let status, data;
while (status !== 'QUEUED' || status !== 'PENDING') {
try {
const resp = await fetch(API + '/api/queue/status/', {
signal: controller.signal,
headers: { 'Content-Type': 'application/json' },
method: 'POST',
body: JSON.stringify({ hash: hash })
});
if (resp.status != 200) {
break;
}
({ status, data } = await resp.json());
if (status === 'QUEUED') {
predictStatus = `Queue ${data}/${queue_position}`;
} else if (status === 'PENDING') {
predictStatus = 'Pending';
} else if (status === 'FAILED') {
predictStatus = 'Failed';
break;
} else if (status === 'COMPLETE') {
predictStatus = 'Complete';
break;
}
await new Promise((resolve) => setTimeout(resolve, 1000));
} catch (error) {
console.log(error);
break;
}
}
return data;
}
</script>
<div class="relative overflow-clip flex flex-col justify-center items-center w-full h-full">
{#if $resultImage}
<img
class="image {$generateHuman ? 'opacity-30' : ''}"
alt="Generative Human Result"
src={$resultImage}
width="256"
height="512"
/>
{/if}
{#if $generateHuman}
<div class="loading">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="animate-spin max-w-[3rem]"
>
<path
fill="currentColor"
d="M20 12a8 8 0 0 1-8 8v4a12 12 0 0 0 12-12h-4Zm-2-5.3a8 8 0 0 1 2 5.3h4c0-3-1.1-5.8-3-8l-3 2.7Z"
/>
</svg>
<span class="text-xs">{predictStatus}</span>
</div>
{/if}
</div>
<!-- {/if} -->
<style lang="postcss" scoped>
.image {
@apply box-border z-0 border dark:border-gray-300 border-gray-500 aspect-[256/512];
}
.loading {
@apply absolute top-0 left-0 right-0 bottom-0 flex flex-col justify-center items-center;
}
</style>