我已经编写了一些代码来使用 Qwik 和 Three.js 显示 3D 模型。不幸的是,我遇到了一个错误,指示“意外的标识符‘$’”。我怀疑这个问题可能与范围有关,特别是考虑到涉及网络工作人员。不过,我并不完全确定。任何帮助或见解将不胜感激。谢谢!
import { component$, useOnDocument, $ } from '@builder.io/qwik';
import * as THREE from 'three';
import type { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js';
export const Robot = component$(() => {
useOnDocument('qinit', $(() => {
... (other code)
async function loadModel() {
const threeJS = await fetchScript('https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js');
const gltfLoaderJS = await fetchScript('https://cdn.jsdelivr.net/gh/mrdoob/three.js@r128/examples/jsm/loaders/GLTFLoader.js');
const workerCode = `
const threeJS = \`${threeJS}\`;
const gltfLoaderJS = \`${gltfLoaderJS}\`;
eval(threeJS);
eval(gltfLoaderJS);
const loader = new THREE.GLTFLoader();
self.onmessage = function(event) {
const { url } = event.data;
loader.load(url, function(gltf) {
self.postMessage({ type: 'model', data: gltf });
}, undefined, function(error) {
self.postMessage({ type: 'error', data: error });
});
};
`;
const blob = new Blob([workerCode], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.postMessage({ url: '/bane10-20.gltf' });
worker.onmessage = function(event: MessageEvent) {
const { type, data } = event.data;
if (type === 'model') {
const gltf: GLTF = data;
const model = gltf.scene;
model.traverse((object: THREE.Object3D) => {
if ((object as THREE.Mesh).isMesh) {
const mesh = object as THREE.Mesh;
if (!mesh.material) {
mesh.material = new THREE.MeshStandardMaterial({ color: 0x555555 });
}
}
});
scene.add(model);
document.body.removeChild(loadingDiv);
} else if (type === 'error') {
console.error('An error occurred while loading the GLTF model:', data);
document.body.removeChild(loadingDiv);
}
};
}
function animate() {
if (renderer) {
frameId = requestAnimationFrame(animate);
renderer.render(scene, camera);
}
}
function onResize() {
if (renderer && camera) {
const width = container.clientWidth;
const height = container.clientHeight;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
}
window.addEventListener('resize', onResize);
init();
return () => {
if (frameId) cancelAnimationFrame(frameId);
if (renderer) {
renderer.dispose();
if (renderer.domElement.parentElement) {
renderer.domElement.parentElement.removeChild(renderer.domElement);
}
}
document.body.removeChild(loadingDiv);
window.removeEventListener('resize', onResize);
};
}));
return <div></div>;
});