Skip to content

Commit

Permalink
Fix skinviewer reactivity (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
ptlthg authored Jan 8, 2025
1 parent ef78f51 commit 0bf75ea
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
73 changes: 43 additions & 30 deletions src/lib/components/Skin3D.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,69 @@
import { getProfileCtx } from "$ctx/profile.svelte";
import { cn } from "$lib/shared/utils";
import * as skinview3d from "skinview3d";
import { onMount } from "svelte";
import { onDestroy } from "svelte";
const ctx = getProfileCtx();
const profile = $derived(ctx.profile);
const uuid = $derived(ctx.profile.uuid);
let { class: className }: { class: string | undefined } = $props();
let viewer: skinview3d.SkinViewer;
let minecraftAvatar: HTMLCanvasElement;
let viewer = $state<skinview3d.SkinViewer>();
let minecraftAvatar = $state<HTMLCanvasElement>();
let canvasIsLoading = $state<boolean>(true);
let loadedUuid = "";
function onResize() {
const FIXED_WIDTH = 500;
const FIXED_HEIGHT = 1000;
function updateViewerSize() {
if (minecraftAvatar && minecraftAvatar.parentElement && viewer) {
viewer.setSize(minecraftAvatar.parentElement.clientWidth, window.innerHeight);
}
}
onMount(() => {
const createSkinviewer = async () => {
const minecraftAvatarContainerDimensions = minecraftAvatar.getBoundingClientRect();
const cape = await fetch(`https://crafatar.com/capes/${profile.uuid}`, {
method: "HEAD"
}).catch(() => ({ ok: false }));
const updateSkinViewer = async (uuid: string) => {
if (loadedUuid === uuid) return;
canvasIsLoading = true;
const cape = await fetch(`https://crafatar.com/capes/${uuid}`, {
method: "HEAD"
}).catch(() => ({ ok: false }));
if (!viewer) {
viewer = new skinview3d.SkinViewer({
canvas: minecraftAvatar,
width: minecraftAvatarContainerDimensions.width,
height: minecraftAvatarContainerDimensions.height,
skin: `https://crafatar.com/skins/${profile.uuid}`,
cape: cape.ok ? `https://crafatar.com/capes/${profile.uuid}` : undefined,
animation: new skinview3d.IdleAnimation()
width: FIXED_WIDTH,
height: FIXED_HEIGHT,
animation: new skinview3d.IdleAnimation(),
preserveDrawingBuffer: true
});
}
viewer.camera.position.set(-18, -3, 78);
viewer.controls.enableZoom = false;
viewer.controls.enablePan = true;
viewer.controls.enableRotate = true;
viewer.canvas.removeAttribute("tabindex");
await viewer.loadSkin(`https://crafatar.com/skins/${uuid}`);
if (cape.ok) {
await viewer.loadCape(`https://crafatar.com/capes/${uuid}`);
} else {
viewer.resetCape();
}
canvasIsLoading = false;
};
viewer.camera.position.set(-18, -3, 78);
viewer.controls.enableZoom = false;
viewer.controls.enablePan = true;
viewer.controls.enableRotate = true;
viewer.canvas.removeAttribute("tabindex");
createSkinviewer();
canvasIsLoading = false;
};
window.addEventListener("resize", onResize);
$effect(() => {
updateSkinViewer(uuid);
});
return () => {
canvasIsLoading = true;
viewer.dispose();
window.removeEventListener("resize", onResize);
};
onDestroy(() => {
viewer?.dispose();
});
</script>

<svelte:window onresize={updateViewerSize} />

<canvas bind:this={minecraftAvatar} class={cn("size-full transform-gpu overflow-hidden transition-opacity duration-[3s]", className)} class:opacity-100={!canvasIsLoading} class:opacity-0={canvasIsLoading}></canvas>
4 changes: 1 addition & 3 deletions src/lib/layouts/stats/Main.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
<div class="fixed left-0 top-1/2 z-10 hidden h-dvh w-[30vw] -translate-y-1/2 @container @[75rem]/parent:block">
{#if browser && window.innerWidth >= 1200}
{#await import('$lib/components/Skin3D.svelte') then { default: Skin3D }}
{#key profile}
<Skin3D class="h-full" />
{/key}
<Skin3D class="h-full" />
{/await}
{/if}
</div>
Expand Down

0 comments on commit 0bf75ea

Please sign in to comment.