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


    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);
            });
        }
    }
  • 相关阅读:
    HTTP
    HTTP
    Tomcat
    Tomcat
    时下流行的9种恶意软件,你都了解吗?
    MYSQL中表级锁、行级锁、页级锁介绍
    MYSQL中表级锁、行级锁、页级锁介绍
    MYSQL存储引擎笔记
    MYSQL存储引擎笔记
    Shell脚本案例:批量新增用户
  • 原文地址:https://www.cnblogs.com/guofan/p/16333145.html
Copyright © 2020-2023  润新知