threejs实现三维泡泡球聚集碰撞物理动画效果代码

代码语言:html

所属分类:三维

代码描述:threejs实现三维泡泡球聚集碰撞物理动画效果代码

代码标签: 泡泡 聚集 碰撞 物理 动画 效果

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="UTF-8">

 
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel='stylesheet' href='https://cdn.jsdelivr.net/gh/alphardex/aqua.css/dist/aqua.min.css'>

    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
        }

:root {
            --white-grad-1: linear-gradient(to top, #e6e9f0 0%, #eef1f5 100%);
        }

        .bg-white-grad-1 {
            background: var(--white-grad-1);
        }
    </style>




</head>

<body>
    <div class="relative w-screen h-screen">
        <div class="bouncy-balloon w-full h-full bg-black bg-white-grad-1"></div>
    </div>


    <script type="module">
        import * as THREE from "https://cdn.skypack.dev/three@0.124.0";
        import ky from "https://cdn.skypack.dev/kyouka@1.2.5";
        import {
            OrbitControls
        } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/controls/OrbitControls";
        import {
            GLTFLoader
        } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/loaders/GLTFLoader";
        import {
            FBXLoader
        } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/loaders/FBXLoader";
        import Stats from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/libs/stats.module";
        import * as CANNON from "https://cdn.skypack.dev/cannon-es@0.18.0";
        import {
            EffectComposer,
            RenderPass,
            NormalPass,
            SSAOEffect,
            EffectPass
        } from "https://cdn.skypack.dev/postprocessing@6.22.2";
        const calcAspect = (el) => el.clientWidth / el.clientHeight;
        const getNormalizedMousePos = (e) => {
            return {
                x: (e.clientX / window.innerWidth) * 2 - 1,
                y: -(e.clientY / window.innerHeight) * 2 + 1
            };
        };
        // 三维点
        class Point {
            constructor(p) {
                this.x = p.x;
                this.y = p.y;
                this.z = p.z;
            }
        }
        // 数组转化为点
        const array2Point = (arr) => new Point({
            x: arr[0], y: arr[1], z: arr[2]
        });
        // 点转化为数组
        const point2Array = (point) => [point.x, point.y, point.z];
        // 多个数组转化为多个点
        const arrays2Point = (arrs) => arrs.map((item) => array2Point(item));
        // 点转化为Three.js的向量
        const point2ThreeVector = (point) => new THREE.Vector3(point.x, point.y, point.z);
        // 点转化为Cannon.js的向量
        const point2CannonVec = (point) => new CANNON.Vec3(point.x, point.y, point.z);
        class MeshPhysicsObject {
            constructor(mesh, body, copyPosition = true, copyQuaternion = true) {
                this.mesh = mesh;
                this.body = body;
                this.copyPosition = copyPosition;
                this.copyQuaternion = copyQuaternion;
            }
        }
        class Base {
            constructor(sel, debug = false) {
                this.debug = debug;
                this.container = document.querySelector(sel);
                this.perspectiveCameraParams = {
                    fov: 75,
                    near: 0.1,
                    far: 100
                };
                this.orthographicCameraParams = {
                    zoom: 2,
                    near: -100,
                    far: 1000
                };
                this.cameraPosition = new THREE.Vector3(0, 3, 10);
                this.lookAtPosition = new THREE.Vector3(0, 0, 0);
                this.rendererParams = {
                    outputEncoding: THREE.LinearEncoding,
                    config: {
                        alpha: true,
                        antialias: true
                    }
                };
                this.mousePos = new THREE.Vector2(0, 0);
                this.mouseSpeed = 0;
            }
            // 初始化
            init() {
                this.createScene();
                this.createPerspectiveCamera();
                this.createRenderer();
                this.createMesh({});
                this.createLight();
                this.createOrbitControls();
                this.addListeners();
                this.setLoop();
            }
            // 创建场景
            createScene() {
                const scene = new THREE.Scene();
                if (this.debug) {
                    scene.add(new THREE.AxesHelper());
                    const stats = Stats();
                    this.container.appendChild(stats.dom);
                    this.stats = stats;
                }
                this.scene = scene;
            }
            // 创建透视相机
            createPerspectiveCamera() {
                const {
                    perspectiveCameraParams,
                    cameraPosition,
                    lookAtPosition
                } = this;
                const {
                    fov,
                    near,
                    far
                } = perspectiveCameraParams;
                const aspect = calcAspect(this.container);
                const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
                camera.position.copy(cameraPosition);
                camera.lookAt(lookAtPosition);
                this.camera = camera;
            }
            // 创建正交相机
            createOrthographicCamera() {
                const {
                    orthographicCameraParams,
                    cameraPosition,
                    lookAtPosition
                } = this;
                const {
                    left,
                    right,
                    top,
                    bottom,
                    near,
                    far
                } = orthographicCameraParams;
                const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
                camera.position.copy(cameraPosition);
                camera.lookAt(lookAtPosition);
                this.camera = camera;
            }
            // 更新正交相机参数
            updateOrthographicCameraParams() {
                const {
                    container
                } = this;
                const {
                    zoom,
                    near,
                    far
                } = this.orthographicCameraParams;
                const aspect = calcAspect(container);
                this.orthographicCameraParams = {
                    left: -zoom * aspect,
                    right: zoom * aspect,
                    top: zoom,
                    bottom: -zoom,
                    near,
                    far,
                    zoom
                };
            }
            // 创建渲染
            createRenderer(useWebGL1 = false) {
                var _a;
                const {
                    rendererParams
                } = this;
                const {
                    outputEncoding,
                    config
                } = rendererParams;
                const renderer = !useWebGL1
                ? new THREE.WebGLRenderer(config): new THREE.WebGL1Renderer(config);
                renderer.setSize(this.container.clientWidth, this.container.clientHeight);
                renderer.outputEncoding = outputEncoding;
                this.resizeRendererToDisplaySize();
                (_a = this.container) === null || _a === void 0 ? void 0: _a.appendChild(renderer.domElement);
                this.renderer = renderer;
                this.renderer.setClearColor(0x000000, 0);
            }
            // 允许投影
            enableShadow() {
                this.renderer.shadowMap.enabled = true;
            }
            // 调整渲染器尺寸
            resizeRendererToDisplaySize() {
                const {
                    renderer
                } = this;
                if (!renderer) {
                    return;
                }
                const canvas = renderer.domElement;
                const pixelRatio = window.devicePixelRatio;
                const {
                    clientWidth,
                    clientHeight
                } = canvas;
                const width = (clientWidth * pixelRatio) | 0;
                const height = (clientHeight * pixelRatio) | 0;
                const isResizeNeeded = canvas.width !== width || canvas.height !== height;
                if (isResizeNeeded) {
                    renderer.setSize(width, height, false);
                }
                return isResizeNeeded;
            }
            // 创建网格
            createMesh(meshObject, container = this.scene) {
                const {
                    geometry = new THREE.BoxGeometry(1, 1, 1),
                    material = new THREE.MeshStandardMaterial({
                        color: new THREE.Color("#d9dfc8")
                    }),
                    position = new THREE.Vector3(0, 0, 0)
                } = meshObject;
                const mesh = new THREE.Mesh(geometry, material);
                mesh.position.copy(position);
                container.add(mesh);
                return mesh;
            }
            // 创建光源
            createLight() {
                const dirLight = new THREE.DirectionalLight(new THREE.Color("#ffffff"), 0.5);
                dirLight.position.set(0, 50, 0);
                this.scene.add(dirLight);
                const ambiLight = new THREE.AmbientLight(new THREE.Color("#ffffff"), 0.4);
                this.scene.add(ambiLight);
            }
            // 创建轨道控制
            createOrbitControls() {
                const controls = new OrbitControls(this.camera, this.renderer.domElement);
                const {
                    lookAtPosition
                } = this;
                controls.target.copy(lookAtPosition);
                controls.update();
                this.controls = controls;
            }
            // 监听事件
            addListeners() {
                this.onResize();
            }
            // 监听画面缩放
            onResize() {
                window.addEventListener("resize", (e) => {
                    if (this.shaderMaterial) {
                        this.shaderMaterial.uniforms.uResolution.value.x = window.innerWidth;
                        this.shaderMaterial.uniforms.uResolution.value.y = window.innerHeight;
                        this.renderer.setSize(window.innerWidth, window.innerHeight);
                    } else {
                        if (this.camera instanceof THREE.PerspectiveCamera) {
                            const aspect = calcAspect(this.container);
                            const camera = this.camera;
                            camera.aspect = aspect;
                            camera.updateProjectionMatrix();
                        } else if (this.camera instanceof THREE.OrthographicCamera) {
                            this.updateOrthographicCameraParams();
                            const camera = this.camera;
                            const {
                                left,
                                right,
                                top,
                                bottom,
                                near,
                                far
                            } = this.orthographicCameraParams;
                            camera.left = left;
                            camera.right = right;
                            camera.top = top;
                            camera.bottom = bottom;
                            camera.near = near;
                            camera.far = far;
                            camera.updateProjectionMatrix();
                        }
                        this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
                    }
                });
            }
            // 动画
            update() {
                console.log("animation");
            }
            // 渲染
            setLoop() {
                this.renderer.setAnimationLoop(() => {
                    this.resizeRendererToDisplaySize();
                    this.update();
                    if (this.controls) {
                        this.controls.update();
                    }
                    if (this.stats) {
                        this.stats.update();
                    }
                    if (this.composer) {
                        this.composer.render();
                    } else {
                        this.renderer.render(this.scene, this.camera);
                    }
                });
            }
            // 创建文本
            createText(text = "",
                config,
                material = new THREE.MeshStandardMaterial({
                    color: "#ffffff"
                })) {
                const geo = new THREE.TextGeometry(text,
                    config);
                const mesh = new THREE.Mesh(geo,
                    material);
                return mesh;
            }
            // 创建音效源
            createAudioSource() {
                const listener = new THREE.AudioListener();
                this.camera.add(listener);
                const sound = new THREE.Audio(listener);
                this.sound = sound;
            }
            // 加载音效
            loadAudio(url) {
                const loader = new THREE.AudioLoader();
                return new Promise((resolve) => {
                    loader.load(url, (buffer) => {
                        this.sound.setBuffer(buffer);
                        resolve(buffer);
                    });
                });
            }
            // 加载模型
            loadModel(url) {
                const loader = new GLTFLoader();
                return new Promise((resolve, reject) => {
                    loader.load(url, (gltf) => {
                        const model = gltf.scene;
                        console.log(model);
                        resolve(model);
                    }, undefined, (err) => {
                        console.log(err);
                        reject();
                    });
                });
            }
            // 加载FBX模型
            loadFBXModel(url) {
                const loader = new FBXLoader();
                return new Promise((resolve, reject) => {
                    loader.load(url, (obj) => {
                        resolve(obj);
                    }, undefined, (err) => {
                        console.log(err);
                        reject();
                    });
                });
            }
            // 加载字体
            loadFont(url) {
                const loader = new THREE.FontLoader();
                return new Promise((resolve) => {
                    loader.load(url, (font) => {
                        resolve(font);
                    });
                });
            }
            // 创建点选模型
            createRaycaster() {
                this.raycaster = new THREE.Raycaster();
                this.trackMousePos();
            }
            // 追踪鼠标位置
            trackMousePos() {
                window.addEventListener("mousemove",
                    (e) => {
                        this.setMousePos(e);
                    });
                window.addEventListener("touchstart",
                    (e) => {
                        this.setMousePos(e.touches[0]);
                    },
                    {
                        passive: false
                    });
                window.addEventListener("touchmove",
                    (e) => {
                        this.setMousePos(e.touches[0]);
                    });
            }
            // 设置鼠标位置
            setMousePos(e) {
                const {
                    x, y
                } = getNormalizedMousePos(e);
                this.mousePos.x = x;
                this.mousePos.y = y;
            }
            // 获取点击物
            getInterSects(container = this.scene) {
                this.raycaster.setFromCamera(this.mousePos,
                    this.camera);
                const intersects = this.raycaster.intersectObjects(container.children,
                    true);
                return intersects;
            }
            // 选中点击物时
            onChooseIntersect(target,
                container = this.scene) {
                const intersects = this.getInterSects(container);
                const intersect = intersects[0];
 .........完整代码请登录后点击上方下载按钮下载查看

网友评论0