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); } }); }, };