3d-scene-creator
Version:
A simple utility to create and manage 3D scenes
172 lines (171 loc) • 6.1 kB
JavaScript
var l = Object.defineProperty;
var d = (o, t, e) => t in o ? l(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
var r = (o, t, e) => (d(o, typeof t != "symbol" ? t + "" : t, e), e);
import * as a from "three";
import c from "gsap";
import { OrbitControls as m } from "three/examples/jsm/controls/OrbitControls";
class f {
constructor(t, e, i, n) {
r(this, "scene");
r(this, "renderer");
r(this, "container");
r(this, "cWidth");
r(this, "cHeight");
r(this, "camera");
r(this, "initialCamPos");
r(this, "initialTargetPos");
r(this, "prevCamPos");
r(this, "controls");
r(this, "additionalRenderFn");
r(this, "stopLoop", !1);
r(this, "scale", 1);
r(this, "animating", 0);
this.scene = new a.Scene(), this.renderer = new a.WebGLRenderer({
antialias: !0,
alpha: !0
}), e && (this.scale = e), this.cWidth = 0, this.cHeight = 0, this.camera = new a.PerspectiveCamera(
50,
this.cWidth / this.cHeight,
0.1 * this.scale,
2e3 * this.scale
), i ? this.initialCamPos = i : this.initialCamPos = new a.Vector3(10 * this.scale, 10 * this.scale, 10 * this.scale), this.prevCamPos = new a.Vector3(this.initialCamPos.x + 1, 1, 1), n ? this.initialTargetPos = n : this.initialTargetPos = new a.Vector3(0, 0, 0), this.camera.position.set(this.initialCamPos.x, this.initialCamPos.y, this.initialCamPos.z);
var s = this.initialTargetPos;
this.camera.lookAt(s), this.resizeListener(), t && this.attachRenderer(t);
}
addControls(t = {}) {
this.controls = new m(this.camera, this.renderer.domElement);
const e = {
enabled: !0,
enableDamping: !0,
dampingFactor: 0.25,
maxPolarAngle: Math.PI / 2,
maxDistance: 100 * this.scale,
minDistance: 0,
rotateSpeed: 1,
enableZoom: !0,
enablePan: !0
}, i = Object.assign(e, t);
return Object.assign(this.controls, i), this.controls.target.set(
this.initialTargetPos.x,
this.initialTargetPos.y,
this.initialTargetPos.z
), this;
}
setAdditionalRenderFn(t) {
this.additionalRenderFn = t;
}
resetSizes() {
this.container && (this.cWidth = this.container.clientWidth, this.cHeight = this.container.clientHeight);
}
animateModelColor(t, e, i = 2) {
const n = this.scene.getObjectByName(t);
if (n) {
let s = new a.Color(e);
n.traverse((h) => {
h instanceof a.Mesh && (this.animating++, c.to(h.material.color, {
duration: i,
r: s.r,
b: s.b,
g: s.g,
onComplete: () => {
this.animating--;
}
}));
});
}
return this;
}
animateModelOpacity(t, e, i = 2) {
const n = this.scene.getObjectByName(t);
return n && n.traverse((s) => {
s instanceof a.Mesh && (s.material.transparent = !0, s.material.needsUpdate = !0, this.animating++, c.to(s.material, {
duration: i,
opacity: e,
onComplete: () => {
this.animating++, s.material.needsUpdate = !0;
}
}), s.material.needsUpdate = !0);
}), this;
}
animateModelPosition(t, e, i = 2) {
const n = this.scene.getObjectByName(t);
return n && c.to(n.position, {
duration: i,
x: e.x,
y: e.y,
z: e.z
}), this;
}
attachRenderer(t) {
return this.container = t, this.resetSizes(), this.camera.aspect = this.cWidth / this.cHeight, this.camera.updateProjectionMatrix(), this.renderer.setSize(this.cWidth, this.cHeight), this.container.appendChild(this.renderer.domElement), this.scene.updateMatrixWorld(!0), this.startRenderLoop(), this;
}
addLighting() {
const t = new a.AmbientLight(16777215, 0.4);
this.scene.add(t);
const e = new a.DirectionalLight(16777215, 0.3);
e.position.set(1, 1, 0), this.scene.add(e);
const i = new a.DirectionalLight(16777215, 0.2);
return i.position.set(-1, 1, -1), this.scene.add(i), this;
}
addSkybox(t, e = "#B2FFFF", i) {
const n = new a.SphereGeometry(100 * this.scale, 60, 60);
n.scale(-1, 1, 1);
let s;
t ? (a.TextureLoader.prototype.crossOrigin = "anonymous", s = new a.MeshBasicMaterial({
map: new a.TextureLoader().load(t)
})) : s = new a.MeshStandardMaterial({ color: e });
const h = new a.Mesh(n, s);
return h.name = i || "skybox", this.scene.add(h), this;
}
resizeListener() {
this.resetSizes(), window.addEventListener(
"resize",
() => {
this.resetSizes();
const t = this.camera, e = this.renderer;
t.aspect = this.cWidth / this.cHeight, t.updateProjectionMatrix(), e.setSize(this.cWidth * 1, this.cHeight * 1), t.position.x = t.position.x + 1e-3;
},
!1
);
}
stopRenderLoop() {
return this.stopLoop = !0, this;
}
startRenderLoop() {
return this.stopLoop = !1, this.renderLoop(), this;
}
renderLoop() {
if (this.stopLoop)
return;
requestAnimationFrame(this.renderLoop.bind(this));
const t = this.scene, e = this.renderer, i = this.camera;
(i.position.x !== this.prevCamPos.x || i.position.y !== this.prevCamPos.y || i.position.z !== this.prevCamPos.z || this.animating) && e.render(t, i), this.prevCamPos = this.camera.position.clone(), this.additionalRenderFn && this.additionalRenderFn(), this.controls && this.controls.update();
}
resetCameraPosition() {
this.moveCamera(this.initialCamPos, this.initialTargetPos);
}
moveCamera(t, e, i) {
const n = this.camera;
let s;
return this.controls && (s = this.controls.enabled, this.controls.enabled = !1), c.to(n.position, {
duration: 3,
x: t.x,
y: t.y,
z: t.z,
onComplete: () => {
this.controls && (this.controls.enabled = s), typeof i == "function" && i();
}
}), e && this.controls && c.to(this.controls.target, {
duration: 3,
x: e.x,
y: e.y,
z: e.z
}), this;
}
loadModel(t, e) {
return e || (e = new a.ObjectLoader()), e.loadAsync(t).then((i) => (this.scene.add(i), i));
}
}
export {
f as SceneCreator
};