130 lines
4.2 KiB
JavaScript
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);
|
|
}
|
|
});
|
|
},
|
|
};
|