Files
Pandora/kit.js
2025-08-11 23:49:58 +08:00

130 lines
4.2 KiB
JavaScript

require("three/build/three");
require("three/examples/js/loaders/GLTFLoader");
require("three/examples/js/controls/TrackballControls");
// 工具组
const Kit = {
// 添加事件
addCaster(renderer, camera, objects, click) {
let raycaster, mouse;
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
$("#model").bind("click", onDocumentMouseDown, false);
$("#model").bind("touchstart", onDocumentMouseDown, false);
function onDocumentMouseDown(event) {
event.preventDefault();
try {
mouse.x = (event.touches[0].clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -(event.touches[0].clientY / renderer.domElement.clientHeight) * 2 + 1;
} catch (err) {
mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1;
}
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(objects);
for (let a = 0; a < intersects.length; a++) {
click && click(intersects[a]);
}
}
},
// gLTF格式模型
gLTFModel(options) {
const { ele, src, minDistance, maxDistance, rotateSpeed, AmbientLight, DirectionalLight, SpotLight, cameraPosition, setMate, loading, click } = options;
const that = this;
return new Promise(next => {
let container, camera, scene, renderer, controls;
let { width, height } = document.querySelector(ele).getBoundingClientRect();
init();
animate();
function init() {
const ambientLight = new THREE.AmbientLight(0xffffff, AmbientLight || 0);
const directionalLight = new THREE.DirectionalLight(0xffffff, DirectionalLight || 0);
const spotLight = new THREE.SpotLight(0xffffff, SpotLight || 0);
const manager = new THREE.LoadingManager();
container = document.createElement("div");
document.querySelector(ele).appendChild(container);
camera = new THREE.PerspectiveCamera(2, width / height, 1, 1000);
camera.position.z = cameraPosition || 100;
// scene
scene = new THREE.Scene();
directionalLight.position.set(0, 1, 0);
spotLight.position.set(1, 0, 1);
scene.add(ambientLight);
scene.add(directionalLight);
camera.add(spotLight);
scene.add(camera);
// model
function onProgress(xhr) {
if (xhr.lengthComputable) {
let percentComplete = (xhr.loaded / xhr.total) * 100;
loading && loading(Math.round(percentComplete, 2));
console.log("已加载:" + Math.round(percentComplete, 2) + "%");
}
}
new THREE.GLTFLoader(manager).load(
`${src}.gltf`,
function (mod) {
const gltf = mod.scene;
for (let a = 0; a < gltf.children.length; a++) {
gltf.children[a].castShadow = true;
gltf.children[a].receiveShadow = true;
}
setMate(gltf);
scene.add(mod.scene);
that.addCaster(renderer, camera, gltf.children, click);
render();
next();
},
onProgress
);
renderer = new THREE.WebGLRenderer({ alpha: true });
// renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
container.appendChild(renderer.domElement);
window.addEventListener("resize", onWindowResize, false);
// controls
controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.rotateSpeed = rotateSpeed || 0;
controls.minDistance = minDistance || 10;
controls.maxDistance = maxDistance || 30;
}
function onWindowResize() {
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
});
},
};