• threejs 实现易拉罐换肤功能


    功能需求:给导入的易拉罐 .obj 元素实现换肤。

    附件材料:3d模型制作软件导出的 .obj 文件 和 需要换肤的纹理图片。

    代码实现: 

    css:

    * {
        margin: 0;
        padding: 0;
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
            'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
    }
    
    html,
    body,
    #content {
        width: 100%;
        height: 100%;
        overflow: hidden;
    }
    ul,
    li {
        list-style-type: none;
    }
    
    
    
    .skin-btn {
        position: absolute;
        display: flex;
    }
    .skin-btn li {
        width: 40px;
        height: 40px;
        margin: 15px 10px;
    }
    .skin-btn--red {
        background-color: #c11d24;
    }
    .skin-btn--orange {
        background-color: #ff7800;
    }
    .skin-btn--blue {
        background-color: #00d2ff;
    }
    View Code

    js:

    import React, { useEffect } from 'react';
    import * as THREE from 'three';
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
    import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
    import fileObj from 'static/media/coca/file.obj';
    import cocaRed from 'static/media/coca/coca_red.jpg';
    import cocaOrange from 'static/media/coca/coca_orange.jpg';
    import cocaBlue from 'static/media/coca/coca_blue.jpg';
    
    import './index.css';
    function Skin() {
        // obj对象需贴图的面,为数据对象
        let objLoaderMaterialArr = [];
    
        // 更换皮肤
        const changeSkin = (color) => {
            // 纹理设置
            let TextureLoader = null;
            switch (color) {
                case 'red':
                    TextureLoader = new THREE.TextureLoader().load(cocaRed);
                    break;
                case 'orange':
                    TextureLoader = new THREE.TextureLoader().load(cocaOrange);
                    break;
                case 'blue':
                    TextureLoader = new THREE.TextureLoader().load(cocaBlue);
                    break;
                default:
            }
            // 给第一个纹理面设置相关图片
            objLoaderMaterialArr[0] = new THREE.MeshLambertMaterial({
                map: TextureLoader,
            });
        };
    
        const init = () => {
            // dom元素生成
            const contentEl = document.getElementById('content');
            const winWidth = window.innerWidth;
            const winHeight = window.innerHeight;
            contentEl.style.cssText = `${winWidth}px;height:${winHeight}px`;
    
            // 场景
            const scene = new THREE.Scene();
    
            // obj 元素加载器
            const objLoader = new OBJLoader();
            objLoader.load(fileObj, (obj) => {
                obj.scale.set(0.1, 0.1, 0.1);
                obj.traverse((child) => {
                    if (child instanceof THREE.Mesh) {
                        // 获取需贴纸的材质列表
                        objLoaderMaterialArr = child.material;
                        // 给第一个纹理面设置相关图片
                        objLoaderMaterialArr[0] = new THREE.MeshLambertMaterial({
                            map: new THREE.TextureLoader().load(cocaRed),
                        });
                    }
                });
                scene.add(obj);
            });
    
            // ------------------------------------------------------------------------------------------
            // 相机
            const camera = new THREE.PerspectiveCamera(45, winWidth / winHeight, 0.1, 1000);
            // 设置相机坐标
            camera.position.set(10, 30, 100);
            // 渲染器
            const renderer = new THREE.WebGLRenderer({
                antialias: true,
            });
            // 设置渲染器的颜色和大小
            renderer.setClearColor('#000');
            renderer.setSize(winWidth, winHeight);
            const canvas = renderer.domElement;
            document.body.appendChild(canvas);
            contentEl.append(canvas);
    
            // 鼠标控制旋转
            const orbitControls = new OrbitControls(camera, canvas);
            // 设置自动旋转及旋转速度
            orbitControls.autoRotate = true;
            orbitControls.autoRotateSpeed = 10;
    
            // 设置光源
            const light = new THREE.DirectionalLight(0xffffff, 0.5);
            light.position.setScalar(100);
            scene.add(light);
            scene.add(new THREE.AmbientLight(0xffffff, 0.5));
    
            // 执行实时刷新
            function render() {
                // 动画循环渲染
                requestAnimationFrame(render);
                // 渲染到页面上
                renderer.render(scene, camera);
    
                orbitControls.update();
            }
            render();
        };
        useEffect(() => {
            init();
        });
    
        return (
            <div id="content">
                <ul className="skin-btn">
                    <li
                        className="skin-btn--red"
                        onClick={() => {
                            changeSkin('red');
                        }}
                    ></li>
                    <li
                        className="skin-btn--orange"
                        onClick={() => {
                            changeSkin('orange');
                        }}
                    ></li>
                    <li
                        className="skin-btn--blue"
                        onClick={() => {
                            changeSkin('blue');
                        }}
                    ></li>
                </ul>
            </div>
        );
    }
    
    export default Skin;
    View Code

     运行截图: 

    代码地址:https://github.com/Zion0707/threejs/tree/master/src/pages/skin

  • 相关阅读:
    wpf中防止界面卡死的写法
    wpf list<T>与ObservableCollection<T>的区别
    wpf 将对象按照正圆的顺序排列的写法
    .net 如何高效地使用string(转)
    wpf 查找DataTemplate中的控件的实现方式
    wpf 属性变更通知类的实现
    wpf 3D图形的实现(转)
    SpringBoot之HandlerInterceptorAdapter
    websocket简单实现
    mockjs基本使用
  • 原文地址:https://www.cnblogs.com/zion0707/p/13549105.html
Copyright © 2020-2023  润新知