@niobrix/solidjs-skinview3d
Version:
A SolidJS wrapper for SkinView3D
244 lines (238 loc) • 7.45 kB
JavaScript
import { use, insert, memo, effect, className, template } from 'solid-js/web';
import { SkinViewer, WalkingAnimation } from 'skinview3d';
import { createSignal, onMount, createEffect, onCleanup } from 'solid-js';
// src/SolidSkinView3D.tsx
// src/SolidSkinView3D.module.css
var SolidSkinView3D_default = {};
// src/SolidSkinView3D.tsx
var _tmpl$ = /* @__PURE__ */ template(`<div><div><canvas>`);
var _tmpl$2 = /* @__PURE__ */ template(`<div><div>`);
var SolidSkinView3D = (props) => {
const [viewer, setViewer] = createSignal(null);
const [isLoading, setIsLoading] = createSignal(true);
let canvasRef;
let animationId = null;
let animation = null;
onMount(() => {
if (!canvasRef)
return;
const skinViewerOptions = {
canvas: canvasRef,
alpha: true,
width: props.width || 300,
height: props.height || 400,
fov: props.fov || 70
};
if (props.background) {
skinViewerOptions.background = props.background;
}
const skinViewer = new SkinViewer(skinViewerOptions);
setViewer(skinViewer);
const orbitControls = skinViewer.controls;
orbitControls.enableRotate = true;
orbitControls.enableZoom = true;
orbitControls.enablePan = false;
if (props.zoom !== void 0) {
skinViewer.camera.position.z = props.zoom;
}
if (props.autoRotate) {
const rotateSpeed = props.rotateSpeed || 5e-3;
const animate = () => {
skinViewer.playerObject.rotation.y += rotateSpeed;
animationId = requestAnimationFrame(animate);
};
animate();
}
const handleSkinLoaded = () => {
setIsLoading(false);
if (props.onSkinLoaded) {
props.onSkinLoaded();
}
};
const handleSkinError = (error) => {
setIsLoading(false);
if (props.onSkinError) {
props.onSkinError(error);
}
};
if (props.skinUrl) {
setIsLoading(true);
const skinOptions = {};
if (typeof props.ears === "boolean") {
skinOptions.ears = props.ears;
} else if (props.ears) {
skinOptions.ears = false;
}
skinViewer.loadSkin(props.skinUrl, skinOptions).then(() => {
if (props.ears && typeof props.ears !== "boolean") {
skinViewer.loadEars(props.ears.source, {
textureType: props.ears.textureType
});
}
handleSkinLoaded();
}).catch(handleSkinError);
} else {
setIsLoading(false);
}
if (props.capeUrl) {
skinViewer.loadCape(props.capeUrl, {
backEquipment: props.backEquipment || "cape"
});
}
animation = new WalkingAnimation();
skinViewer.animation = animation;
if (props.onReady) {
props.onReady(skinViewer);
}
const handleResize = () => {
if (props.autoResize) {
const parent = canvasRef.parentElement;
if (parent) {
skinViewer.setSize(parent.clientWidth, parent.clientHeight);
}
}
};
if (props.autoResize) {
window.addEventListener("resize", handleResize);
handleResize();
}
onCleanup(() => {
if (props.autoResize) {
window.removeEventListener("resize", handleResize);
}
if (animationId !== null) {
cancelAnimationFrame(animationId);
}
if (viewer()) {
viewer()?.dispose();
}
});
});
createEffect(() => {
const currentViewer = viewer();
if (currentViewer && props.skinUrl) {
setIsLoading(true);
const skinOptions = {};
if (typeof props.ears === "boolean") {
skinOptions.ears = props.ears;
} else if (props.ears) {
skinOptions.ears = false;
}
currentViewer.loadSkin(props.skinUrl, skinOptions).then(() => {
if (props.ears && typeof props.ears !== "boolean") {
currentViewer.loadEars(props.ears.source, {
textureType: props.ears.textureType
});
}
setIsLoading(false);
if (props.onSkinLoaded) {
props.onSkinLoaded();
}
}).catch((error) => {
setIsLoading(false);
if (props.onSkinError) {
props.onSkinError(error);
}
});
}
});
createEffect(() => {
const currentViewer = viewer();
if (currentViewer && props.capeUrl !== void 0) {
if (props.capeUrl) {
currentViewer.loadCape(props.capeUrl, {
backEquipment: props.backEquipment || "cape"
});
} else {
currentViewer.loadCape(null);
}
}
});
createEffect(() => {
const currentViewer = viewer();
if (currentViewer && props.backEquipment && props.capeUrl) {
currentViewer.loadCape(props.capeUrl, {
backEquipment: props.backEquipment
});
}
});
createEffect(() => {
const currentViewer = viewer();
if (currentViewer && (props.width || props.height)) {
currentViewer.setSize(props.width || currentViewer.width, props.height || currentViewer.height);
}
});
createEffect(() => {
const currentViewer = viewer();
if (currentViewer && props.background !== void 0) {
currentViewer.background = props.background;
}
});
createEffect(() => {
const currentViewer = viewer();
if (currentViewer && props.zoom !== void 0) {
currentViewer.camera.position.z = props.zoom;
}
});
createEffect(() => {
const currentViewer = viewer();
if (currentViewer && props.fov !== void 0) {
currentViewer.fov = props.fov;
}
});
createEffect(() => {
if (props.autoRotate) {
if (animationId === null && viewer()) {
const rotateSpeed = props.rotateSpeed || 5e-3;
const animate = () => {
const currentViewer = viewer();
if (currentViewer) {
currentViewer.playerObject.rotation.y += rotateSpeed;
}
animationId = requestAnimationFrame(animate);
};
animate();
}
} else if (animationId !== null) {
cancelAnimationFrame(animationId);
animationId = null;
}
});
return (() => {
var _el$ = _tmpl$(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
var _ref$ = canvasRef;
typeof _ref$ === "function" ? use(_ref$, _el$3) : canvasRef = _el$3;
insert(_el$2, (() => {
var _c$ = memo(() => !!(props.showLoader !== false && isLoading()));
return () => _c$() && (() => {
var _el$4 = _tmpl$2(), _el$5 = _el$4.firstChild;
effect((_p$) => {
var _v$4 = SolidSkinView3D_default.loader, _v$5 = SolidSkinView3D_default.spinner;
_v$4 !== _p$.e && className(_el$4, _p$.e = _v$4);
_v$5 !== _p$.t && className(_el$5, _p$.t = _v$5);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$4;
})();
})(), null);
effect((_p$) => {
var _v$ = SolidSkinView3D_default.container, _v$2 = SolidSkinView3D_default.wrapper, _v$3 = `${SolidSkinView3D_default.canvas} ${props.className || ""}`;
_v$ !== _p$.e && className(_el$, _p$.e = _v$);
_v$2 !== _p$.t && className(_el$2, _p$.t = _v$2);
_v$3 !== _p$.a && className(_el$3, _p$.a = _v$3);
return _p$;
}, {
e: void 0,
t: void 0,
a: void 0
});
return _el$;
})();
};
var SolidSkinView3D_default2 = SolidSkinView3D;
// src/index.tsx
var src_default = SolidSkinView3D_default2;
export { SolidSkinView3D_default2 as SolidSkinView3D, src_default as default };