UNPKG

threeasy

Version:

A wrapper and some sensible defaults to make the early stages of learning ThreeJS easier

2 lines (1 loc) 5.54 kB
class e{constructor(e){this.app=e,this.tasks=[]}add(e){this.tasks.push(e)}animate(){requestAnimationFrame(this.animate.bind(this)),this.tasks.forEach((e=>e())),this.app.render()}}class t{constructor(e,t){this.app=e,this.THREE=e.THREE,this.settings={load:()=>{this.app.init()},gltfExtensions:[".gltf",".glb"],objExtensions:[".obj"],textureExtensions:[".jpg",".jpeg",".png",".gif",".bmp",".tga"],...t},this.manager=new this.THREE.LoadingManager((()=>this.settings.load()),((e,t,s)=>this.progress(e,t,s))),this.setUpLoaders()}progress(e,t,s){}setUpLoaders(){this.TextureLoader=!1,this.GLTFLoader=!1,this.OBJLoader=!1,this.app.settings.GLTFLoader&&(this.GLTFLoader=new this.app.settings.GLTFLoader(this.manager)),this.app.settings.OBJLoader&&(this.OBJLoader=new this.app.settings.OBJLoader(this.manager)),this.TextureLoader=new this.THREE.TextureLoader(this.manager)}load(){this.handleNesting(this.app.settings.preload)}handleNesting(e,t=this.app){for(let s in e)if(e.hasOwnProperty(s)){const i=e[s];"string"==typeof i?this.handleAsset(t,s,i):this.handleNesting(i,t[s]={})}}handleAsset(e,t,s){this.endsWith(s,this.settings.gltfExtensions)&&this.handleGLTF(e,t,s),this.endsWith(s,this.settings.objExtensions)&&this.handleOBJ(e,t,s),this.endsWith(s,this.settings.textureExtensions)&&this.handleTexture(e,t,s)}handleGLTF(e,t,s){this.GLTFLoader?this.GLTFLoader.load(s,(s=>{e[t]=s.scene})):console.warn(`ThreeasyLoader: GLTFLoader is not defined trying to load: ${s}`)}handleOBJ(e,t,s){this.OBJLoader?this.OBJLoader.load(s,(s=>{e[t]=s})):console.warn(`ThreeasyLoader: OBJLoader is not defined trying to load: ${s}`)}handleTexture(e,t,s){this.TextureLoader.load(s,(s=>{e[t]=s,this.setUpTexture(e[t])}))}endsWith(e,t){return t.some((t=>e.endsWith(t)))}setUpTexture(e){e.colorSpace=this.THREE.SRGBColorSpace,e.wrapT=this.THREE.RepeatWrapping,e.wrapS=this.THREE.RepeatWrapping}}class s{constructor(e){this.app=e,this.tasks=[]}add(e){this.tasks.push(e)}load(){this.tasks.forEach((e=>e()))}}class i{constructor(e){this.app=e,this.clicks=[],this.hovers=[],this.app.settings.interactions&&(this.raycaster=new e.THREE.Raycaster,this.pointer=new e.THREE.Vector2,this.app.mouse=this.pointer,this.interactions())}noInteractions=()=>0==this.clicks.length&&0==this.hovers.length;interactions(){this.app.animator.add((()=>{this.noInteractions()||(this.raycaster.setFromCamera(this.pointer,this.app.camera),this.intersects=[],this.intersects=this.raycaster.intersectObjects(this.app.scene.children))})),this.app.renderer.domElement.addEventListener("mousemove",(e=>{this.noInteractions()||(this.calculatePosition(e),this.calculateIntersects("mouseMove",e))})),this.app.renderer.domElement.addEventListener("click",(e=>{this.noInteractions()||(this.calculatePosition(e),this.calculateIntersects("click",e))})),this.app.renderer.domElement.addEventListener("mouseup",(e=>{this.noInteractions()||(this.calculatePosition(e),this.calculateIntersects("mouseup",e))}))}calculatePosition(){this.pointer.x=event.clientX/window.innerWidth*2-1,this.pointer.y=-(event.clientY/window.innerHeight*2-1)}calculateIntersects(e,t){let s=[];for(let i=0;i<this.intersects.length;i++){const n=this.intersects[i];if(s.push(n.object.uuid),"click"==e){const e=this.clicks.find((e=>n.object.uuid==e.el.uuid));e&&e.fn(t,n)}}"mouseMove"==e&&this.hovers.forEach((e=>{const i=s.indexOf(e.el.uuid)>-1,n=e.el.hovered;i&&!n&&(e.el.hovered=!0,e.fns.enter&&e.fns.enter(t,e.el)),!i&&n&&(e.el.hovered=!1,e.fns.leave&&e.fns.leave(t,e.el))}))}onClick(e,t){this.clicks.push({el:e,fn:t})}onHover(e,t){e.hovered=!1,this.hovers.push({el:e,fns:t})}}class n{constructor(n,h){if(this.settings={light:!0,alpha:!1,interactions:!1,domElement:document.body,...h},!this.settings.domElement)throw new Error("Threeasy: settings.domElement not found.");this.THREE=n,this.setSize(),this.animator=new e(this),this.scene=new n.Scene,this.camera=new n.PerspectiveCamera(75,this.sizes.w/this.sizes.h,1,200),this.camera.position.x=0,this.camera.position.y=0,this.camera.position.z=2,this.scene.add(this.camera),this.renderer=new n.WebGLRenderer({antialias:!0,alpha:this.settings.alpha}),this.renderer.setSize(this.sizes.w,this.sizes.h),this.renderer.setPixelRatio(Math.min(2,window.devicePixelRatio)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=n.PCFSoftShadowMap,this.mouse={x:null,y:null},this.interactions=new i(this),this.models={},this.textures={},this.loader=new t(this),this.postLoader=new s(this),this.settings.light&&(this.light=new n.AmbientLight(16777215,1),this.scene.add(this.light)),this.clock=new n.Clock,this.clock.start(),this.settings.domElement.appendChild(this.renderer.domElement),this.renderer.domElement.style.maxWidth="100%",window.addEventListener("resize",(()=>this.resize())),this.resizeObserver=new ResizeObserver((e=>this.resize())),this.resizeObserver.observe(this.settings.domElement),this.preload()}setSize(){this.settings.domElement===document.body?this.sizes={w:window.innerWidth,h:window.innerHeight}:this.sizes={w:this.settings.domElement.clientWidth,h:this.settings.domElement.clientHeight}}preload(){this.settings.preload?this.loader.load():this.init()}postload(e){this.postLoader.add(e)}render(){this.renderer.render(this.scene,this.camera)}animate(e){this.animator.add(e)}init(){this.postLoader.load(),this.animator.animate()}resize(){this.setSize(),this.camera.aspect=this.sizes.w/this.sizes.h,this.camera.updateProjectionMatrix(),this.renderer.setSize(this.sizes.w,this.sizes.h),this.renderer.setPixelRatio(Math.min(2,window.devicePixelRatio))}}export{n as default};