three.js 结合控制器,TWEEN插件,FLTF加载器实现加载glb格式模型,模型的热点的点击、相机在场景中的移动效果,

1. 技术点:结合控制器,TWEEN插件,FLTF加载器实现加载glb格式模型,模型的热点的点击、相机在场景中的移动效果,

2. 效果地址

案例地址(只做了pc端移动端不兼容)

3.全部代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link type="text/css" rel="stylesheet" href="../../three.js-r115/examples/main.css">
</head>
<body>
<div id="container" style="width: 100%; height: 100%;"></div>
</body>
<script type="module">
    import * as THREE from '../../three.js-r115/build/three.module.js';
    import {OrbitControls} from "../../three.js-r115/examples/jsm/controls/OrbitControls.js";
    import Stats from '../../three.js-r115/examples/jsm/libs/stats.module.js'
    import {GLTFLoader} from "../../three.js-r115/examples/jsm/loaders/GLTFLoader.js";
    import {TWEEN} from "../../three.js-r115/examples/jsm/libs/tween.module.min.js";

    let nowLookModel = {x: 0, y: 0, z: 0}; // 当前位置
    let scene, camera, renderer, orbitControls, state = new Stats(), // 场景、相机、加载器、控制器、性能检测器
        raycaster = new THREE.Raycaster(), mouse = new THREE.Vector2(), container = {}; // 射线、鼠标或触摸位置、容器大小
    let isMove = false; // 判断鼠标是否移动

    function initCamera() {
        camera = new THREE.PerspectiveCamera(90, container.aspect, 0.1, 1000);
        // camera.position.setY(100)
    } // 初始化相机
    function initScene() {
        scene = new THREE.Scene();
        scene.position.set(...Object.values(nowLookModel))
    } // 初始化场景
    function initRenderer() {
        renderer = new THREE.WebGLRenderer({antialias: true});
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(container.w, container.h);
        $id('container').appendChild(renderer.domElement);
    } // 初始化渲染器
    function initControls() {
        orbitControls = new OrbitControls(camera, renderer.domElement);
        orbitControls.target.set(0, 0, 0.01)
    } // 初始化控制器
    function initLight() {
        let ambientLight = new THREE.AmbientLight(0xffffff, 5);
        ambientLight.position.set(200, 200, 0);
        scene.add(ambientLight);
    } // 初始化灯光
    function initModel() {
        let loader = new GLTFLoader();
        let imageLoader = new THREE.TextureLoader();
        loader.load('../../static/models/sh_hot_floor.glb', function (gltf) {
            gltf = gltf.scene
            gltf.position.setY(-2)
            let texture = imageLoader.load('../../static/images/floor.jpeg', (t) => {
                scene.getObjectByName('floor_1').material = new THREE.MeshBasicMaterial({map: t,});
            })
            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            texture.repeat.set(100, 100);
            gltf.name = 'gltf'
            scene.add(gltf);
        })
    } // 初始化模型
    function initHelper() {
        $id('container').appendChild(state.domElement)
    } // 初始化辅助线
    function onWindowResize() {
        setContainerSize()
        camera.aspect = container.aspect;
        camera.updateProjectionMatrix();
        renderer.setSize(container.w, container.h);
    } // 调整窗口大小
    function animate() {
        requestAnimationFrame(animate);
        render()
        state.update()
    } //动画
    function render() {
        orbitControls.update();
        scene.position.set(...Object.values(nowLookModel))
        renderer.render(scene, camera);
        TWEEN.update()
    } //渲染
    function onDown(event) {
        setMouseXYZ(event)
        isMove = false
    } // 按下
    function onMove(event) {
        setMouseXYZ(event)
    } // 移动
    function onUp(event) {
        setMouseXYZ(event)
        if (!isMove) {
            raycaster.setFromCamera(mouse, camera);
            let intersectObjects = raycaster.intersectObject(scene.getObjectByName('gltf'), true);
            console.log(intersectObjects);
            let move = raycaster.intersectObject(scene.getObjectByName('gltf'), true);
            let hot = raycaster.intersectObject(scene.getObjectByName('gltf'), true);
            if (hot[0] && hot[0].object.name.indexOf('热点') != -1) {
                alert(hot[0].object.name)
            } else if (move[0] && move[0].object.name == 'floor_1') {
                new TWEEN.Tween(nowLookModel).to({
                    x: nowLookModel.x - move[0].point.x,
                    z: nowLookModel.z - move[0].point.z,
                }, 300).start();
            }
        }
    } // 弹起
    function addEL() {
        window.addEventListener('resize', onWindowResize, false);

        $id().addEventListener('mousedown', onDown, false);
        $id().addEventListener('mousemove', onMove, false);
        $id().addEventListener('mouseup', onUp, false);
    } //添加监听器
    function setMouseXYZ(event) {
        event.preventDefault();
        if (Math.abs(event.movementX) > 1 || Math.abs(event.movementY) > 1) {
            mouse.x = (event.offsetX / $id().offsetWidth) * 2 - 1;
            mouse.y = -(event.offsetY / $id().offsetHeight) * 2 + 1;
            isMove = true
        } // 处理点击的时候可能会移动的误差
    }// 设置mouse的坐标
    function setContainerSize() {
        container.w = window.innerWidth
        container.h = window.innerHeight
        container.aspect = window.innerWidth / window.innerHeight
    } // 获取容器大小并设置给container
    (function main() {
        setContainerSize() // 打开的窗口容器大小
        initCamera(); // 初始化相机
        initScene(); // 初始化场景
        initRenderer(); // 初始化渲染器
        initControls(); // 初始化控制器
        initLight(); // 初始化灯光
        initHelper(); // 初始化辅助线
        initModel(); // 初始化模型
        addEL(); // 添加监听器
        animate(); // 动画
    })() // 方法运行的main函数
    function $id(id) {
        return !id ? renderer.domElement : document.getElementById(id);
    } // 获取画布或者根据id获取document对象
</script>
</html>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淋雨一直走~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值