ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

three.js 针对光源的移动控制 demo

2022-06-01 09:36:06  阅读:171  来源: 互联网

标签:demo scene three camera let renderer new js THREE


import * as THREE from 'three';
// 视图旋转控件
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// 可视化平移控件
import { TransformControls } from 'three/examples/jsm/controls/TransformControls';

/**
 * 3d 鼠标拖拽,测试光源
 */
export class ThreeDragLight {
    constructor(canvasId) {
        this.work(canvasId);
    }

    work(canvasId) {
        // 创建 3d 场景
        let scene = new THREE.Scene();

        let width = window.innerWidth;
        let height = window.innerHeight;
        let renderer = new THREE.WebGLRenderer({
            antialias: true
        });

        renderer.setSize(width, height);
        // 最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。
        document.getElementById(canvasId).appendChild(renderer.domElement);
        scene.background = new THREE.Color(0x9e9e9e);

        let camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
        // 3d 视图(主视角)
        camera.position.set(240, 50, 240);
        //设置照相机的位置
        camera.lookAt(new THREE.Vector3(0, 0, 0)); //设置照相机面向(0,0,0)坐标观察 照相机默认坐标为(0,0,0); 默认面向为沿z轴向里观察;

        // 聚光灯
        let spotLight = new THREE.SpotLight(0xffffff, 100, 0);  //创建光源
        // 光源移动
        spotLight.position.set(0, 100, 0);
        scene.add(spotLight);  //在场景中添加光源

        // 网格辅助线
        let gridHelper = new THREE.GridHelper(200, 10, 0x444444, 0xffffff);
        scene.add(gridHelper);

        // 三维坐标轴参考线
        let axes = new THREE.AxesHelper(100);
        scene.add(axes);

        // 添加物体
        let geo = this.addBox(scene);

        // 渲染
        renderer.render(scene, camera);

        // 添加鼠标操作视图
        let tackBallC, orbC;
        orbC = this.initMouseControl(scene, camera, renderer);

        // 添加拖动事件,返回平移控件对象
        let transformControls = this.initDragControl(scene, camera, renderer, orbC);


        // 添加操作面板,绑定按钮事件,可切换光源对象
        this.addControlPanel(renderer, scene, camera, transformControls, spotLight);


        /**
         * 使用官方的THREE.Raycaster
         * THREE.Raycaster是three.js中的射线类,其实现监听的原理是由相机位置为射线起点,由鼠标位置为射线方向发射射线,
         * 其穿过的所有几何体都会被监测到。
         * @type {*[]}
         */
        let intersects = []; //几何体合集
        const pointer = new THREE.Vector2();
        // 给 canvas 加监听点击事件
        document.getElementsByTagName('canvas')[0].addEventListener('click', meshOnClick);
        let raycaster = new THREE.Raycaster();
        function meshOnClick(event) {

            //geometrys 为需要监听的Mesh合集,可以通过这个集合来过滤掉不需要监听的元素例如地面天空
            let geometrys = [];
            for (let i = 0; i < scene.children.length; i++) {
                console.log(scene.children[i].isLight);
                // 物体 和 光源都监听点击
                if (scene.children[i].isMesh || scene.children[i].isLight) {
                    geometrys.push(scene.children[i]);
                }
            }
            console.log(geometrys);
            pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
            pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
            raycaster.setFromCamera(pointer, camera);
            // true为不拾取子对象
            intersects = raycaster.intersectObjects(geometrys, true);
            // 被射线穿过的几何体为一个集合,越排在前面说明其位置离端点越近,所以直接取[0]
            console.log(intersects);
            if (intersects.length > 0) {
                transformControls.attach(intersects[0].object);
            } else {
                //若没有几何体被监听到,可以做一些取消操作,判断不到光源点击,直接移除控制不可行
                // transformControls.detach();
                // 当前控制器操控的对象
                // console.log(transformControls.object);
                console.log(1);
            }
            renderer.render(scene, camera);

        }
    }

    /**
     * 鼠标操作
     */
    initMouseControl(scene, camera, renderer) {
        // 添加鼠标操作
        let controls = new OrbitControls(camera, renderer.domElement);
        controls.addEventListener('change', () => {
            renderer.render(scene, camera);
        });
        return controls;
    }

    // 添加拖拽控件
    initDragControl(scene, camera, renderer, orbC) {
        /**
         * 添加平移控件,可视化操作,默认显示三维坐标系(因为是一个三维模型,所以需要添加到场景中)
         *
         * 变换控制器(TransformControls)
         * 该类可提供一种类似于在数字内容创建工具(例如Blender)中对模型进行交互的方式,来在3D空间中变换物体。 和其他控制器不同的是,变换控制器不倾向于对场景摄像机的变换进行改变。
         * TransformControls 期望其所附加的3D对象是场景图的一部分。
         *
         * TransformControls( camera : Camera, domElement : HTMLDOMElement )
         * camera: 被控制的摄像机。
         * domElement: 用于事件监听的HTML元素。
         * 创建一个新的 TransformControls 实例。
         *
         * 文档:https://threejs.org/docs/index.html#examples/zh/controls/TransformControls.detach
         *
         * .attach ( object : Object3D ) 设置应当变换的3D对象,并确保控制器UI是可见的。
         * .detach () 从控制器中移除当前3D对象,并确保控制器UI是不可见的。
         * @type {TransformControls}
         */
        let transformControls = new TransformControls(camera, renderer.domElement);
        scene.add(transformControls);
        // 监听改变,则更新界面
        transformControls.addEventListener("change", () => {
            renderer.render(scene, camera);
        });
        // 变换控制器监听 mousedown,禁用 鼠标拖拽
        transformControls.addEventListener("mouseDown", () => {
            orbC.enabled = false;
        });
        //
        transformControls.addEventListener("mouseUp", () => {
            orbC.enabled = true;
        });

        return transformControls;
    }

    /**
     * 添加物体,此为十二面体,可观察光影效果
     * @param scene
     * @return {Mesh}
     */
    addBox(scene) {
        // 添加 十二面体
        const geometry = new THREE.DodecahedronGeometry(20, 0);
        const material = new THREE.MeshStandardMaterial({ color: 0x049EF4 });
        const dodecahedron = new THREE.Mesh(geometry, material);
        scene.add(dodecahedron);
        // 添加边缘辅助线
        let edges = new THREE.EdgesHelper(dodecahedron, 0x00ff00);
        scene.add(edges);

        const box = new THREE.BoxHelper(dodecahedron, 0xffff00);
        scene.add(box);
        // 后续增加点击事件,抛出物体对象
        return dodecahedron;
    }

    /**
     * 添加操作面板,按钮控制光源对象切换,添加平移控件关联
     * @param renderer
     * @param scene
     * @param camera
     * @param transformControls 平移控制器对象
     * @param spotLight 聚光灯对象
     */
    addControlPanel(renderer, scene, camera, transformControls, spotLight) {
        let ele = `
            <div class="control-panel">
                <button class="spot-light">聚光灯</button>
            </div>
        `;
        $('body').append(ele);
        // 绑定按钮事件
        $('.spot-light').on('click', function (e) {
            // 标记光源控制器,测试光源拖拽效果,后续单独搞个 demo
            transformControls.attach(spotLight);
            renderer.render(scene, camera);
        });
    }
}

 

标签:demo,scene,three,camera,let,renderer,new,js,THREE
来源: https://www.cnblogs.com/guofan/p/16333145.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有