Skip to content

页面上的按钮与场景中的物体实现交互

实际开发的时候,往往会通过前端的 HTML、CSS 代码创建按钮等交互界面,用来与 3D 场景交互

如果你是用 vue 或 react 开发 web3d 项目,也可以不用 HTML、CSS 自己写,也可以使用 UI 组件库

点击页面上的按钮改变 Mesh 颜色

html
<div id="red">红色</div>
<div id="green">绿色</div>

通过按钮与 3D 场景交互,改变 mesh 颜色

js
document.getElementById('red').addEventListener('click', () => {
  Model.material.color.set(0xff0000);
});
document.getElementById('green').addEventListener('click', () => {
  Model.material.color.set(0x00ff00);
});

完整代码

index.html

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="container">
      <div class="left">1</div>
      <div class="right">
        <div class="top">2</div>
        <div id="red">红色</div>
        <div id="green">绿色</div>
        <div class="bottom" id="three"></div>
      </div>
    </div>

    <script type="importmap">
      {
        "imports": {
          "three": "../../build/three.module.js",
          "three/addons/": "../../examples/jsm/"
        }
      }
    </script>

    <script src="./index.js" type="module"></script>
  </body>
</html>

<style>
  * {
    margin: 0;
    padding: 0;
    overflow: hidden;
  }

  .container {
    display: flex;
    height: 100vh;
  }

  .container .left {
    width: 200px;
    background-color: blue;
  }

  .container .right .top {
    width: calc(100vw - 200px);
    height: 100px;
    background-color: red;
  }

  .container .right .bottom {
    height: calc(100vh - 100px);
    background-color: gray;
    width: calc(100vw - 200px);
  }

  #red,
  #green {
    position: absolute;
    color: #fff;
    top: 75%;
    width: 50px;
    height: 30px;
    background-color: brown;
    text-align: center;
    line-height: 30px;
    border-radius: 10px;
    padding: 5px 10px;
    cursor: pointer;
  }

  #red {
    left: 50%;
  }

  #green {
    left: 57%;
  }
</style>

index.js

js
import * as THREE from 'three';
import Model from './model.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

const width = window.innerWidth - 200;
const height = window.innerHeight - 100;

const scene = new THREE.Scene();
scene.add(Model);

const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 1000);
camera.position.set(300, 300, 300);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);

const render = () => {
  renderer.render(scene, camera);
  window.requestAnimationFrame(render);
};

render();

new OrbitControls(camera, renderer.domElement);

document.getElementById('three').appendChild(renderer.domElement);
document.getElementById('red').addEventListener('click', () => {
  Model.material.color.set(0xff0000);
});
document.getElementById('green').addEventListener('click', () => {
  Model.material.color.set(0x00ff00);
});

window.onresize = () => {
  const width = window.innerWidth - 200;
  const height = window.innerHeight - 100;
  renderer.setSize(width, height);
  camera.aspect = width / height;
  camera.updateProjectionMatrix();
};

model.js

js
import * as THREE from 'three';

const geometry = new THREE.BoxGeometry(50, 50, 50);
const material = new THREE.MeshBasicMaterial({
  color: 0x0000ff,
});

const mesh = new THREE.Mesh(geometry, material);

export default mesh;

效果

上次更新于: