Skip to content

Commit ac59ede

Browse files
committed
fea: better VRM component
1 parent 081928b commit ac59ede

File tree

2 files changed

+31
-34
lines changed

2 files changed

+31
-34
lines changed

src/app/[locale]/template.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,6 @@ export default function PagesLayout({ children }: { children: ReactNode }) {
126126
name: t("jp-payments"),
127127
href: "https://docs.mikn.dev/legal/jp-payments",
128128
},
129-
{
130-
name: t("gdpr"),
131-
href: "https://docs.mikn.dev/legal/dpa",
132-
},
133129
],
134130
},
135131
];

src/components/vrm.tsx

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,19 @@ import {
1111
} from "@pixiv/three-vrm-animation";
1212
import { AnimationMixer, LoopOnce, LoopRepeat } from "three";
1313

14+
const animations = [
15+
{ url: "https://cdn.mikn.dev/vroid/shikanoko.vrma", loop: true, percentage: 30 },
16+
{ url: "https://cdn.mikn.dev/vroid/hi.vrma", loop: false, percentage: 70 },
17+
];
18+
1419
export const VRMModel: React.FC<{
1520
vrm: import("@pixiv/three-vrm").VRM | null;
1621
mixer: AnimationMixer | null;
1722
}> = ({ vrm, mixer }) => {
1823
useFrame(({ clock }, delta) => {
1924
if (vrm) {
20-
vrm.scene.position.set(0, -4, 0);
21-
vrm.scene.scale.set(5, 5, 5);
25+
vrm.scene.position.set(0, -4.2, 0);
26+
vrm.scene.scale.set(6.5, 5, 5);
2227
vrm.scene.rotation.y = Math.PI;
2328
vrm.expressionManager?.setValue("neutral", 1);
2429

@@ -46,7 +51,7 @@ export function VRM() {
4651
return new Promise<import("@pixiv/three-vrm").VRM>(
4752
(resolve, reject) => {
4853
loader.load(
49-
"https://cdn.mikn.dev/vroid/mikan.dev(web).vrm",
54+
"https://cdn.mikn.dev/vroid/mikan.dev(kyonyu).vrm",
5055
(gltf: GLTF) => {
5156
const loadedVrm = gltf.userData.vrm;
5257
setVrm(loadedVrm);
@@ -65,14 +70,22 @@ export function VRM() {
6570
);
6671
};
6772

73+
function pickAnimation() {
74+
const total = animations.reduce((sum, anim) => sum + anim.percentage, 0);
75+
const rand = Math.random() * total;
76+
let acc = 0;
77+
for (const anim of animations) {
78+
acc += anim.percentage;
79+
if (rand < acc) return anim;
80+
}
81+
return animations[0]; // fallback
82+
}
83+
6884
const loadAnimation = (loadedVrm: import("@pixiv/three-vrm").VRM) => {
69-
const animationUrl =
70-
Math.random() < 0.3
71-
? "https://cdn.mikn.dev/vroid/shikanoko.vrma"
72-
: "https://cdn.mikn.dev/vroid/hi.vrma";
85+
const { url, loop } = pickAnimation();
7386

7487
loader.load(
75-
animationUrl,
88+
url,
7689
(gltf: GLTF) => {
7790
const vrmAnimations = gltf.userData.vrmAnimations;
7891
if (vrmAnimations && vrmAnimations.length > 0) {
@@ -81,37 +94,26 @@ export function VRM() {
8194
vrmAnimations[0],
8295
loadedVrm,
8396
);
84-
const animationMixer = new AnimationMixer(
85-
loadedVrm.scene,
86-
);
87-
const action =
88-
animationMixer.clipAction(animationClip);
97+
const animationMixer = new AnimationMixer(loadedVrm.scene);
98+
const action = animationMixer.clipAction(animationClip);
8999

90-
if (
91-
animationUrl ===
92-
"https://cdn.mikn.dev/vroid/hi.vrma"
93-
) {
100+
if (loop) {
101+
action.setLoop(LoopRepeat, Infinity);
102+
} else {
94103
action.setLoop(LoopOnce, 1);
95104
action.clampWhenFinished = true;
96-
} else {
97-
action.setLoop(LoopRepeat, Infinity);
98105
}
99106

100107
action.play();
101108
setMixer(animationMixer);
102109
} else {
103-
console.error(
104-
"VRM model or humanoid is not loaded correctly.",
105-
);
110+
console.error("VRM model or humanoid is not loaded correctly.");
106111
}
107112
}
108113
},
109114
undefined,
110115
(error: Error) => {
111-
console.error(
112-
"An error occurred while loading the animation:",
113-
error,
114-
);
116+
console.error("An error occurred while loading the animation:", error);
115117
},
116118
);
117119
};
@@ -130,14 +132,13 @@ export function VRM() {
130132
<div className="flex justify-center items-center w-96 h-96">
131133
{!isLoaded ? (
132134
<div className="flex items-center justify-center p-4">
133-
<AiOutlineLoading3Quarters
134-
className="animate-spin text-primary"
135-
size={80}
135+
<span
136+
className="loading loading-xl loading-spinner text-primary"
136137
/>
137138
</div>
138139
) : (
139140
<Canvas camera={{ position: [0, 0, 3] }}>
140-
<ambientLight intensity={2.1} />
141+
<ambientLight intensity={1.5} />
141142
<VRMModel vrm={vrm} mixer={mixer} />
142143
</Canvas>
143144
)}

0 commit comments

Comments
 (0)