three.js(二)
- 参考
- 前言
- 正文
- 简单开始(不使用任何框架)
- 补充
- 粗略带过(使用Vue框架)
- 细致讲解(比如我使用react框架)
- App.jsx 的进阶版
- 项目打包
- 补充
- 打包遇到的问题:
- 原因:
- 解决办法:
参考
https://threejs.org/docs/
前言
上一集中,我们用到了three.js的一个cdn的方法可以快速搭建一个前端页面,
现在我们尝试使用react框架来打包一下前端页面,然后在运行到我们已经搭建好的cpp-httplib框架搭建的后端服务器.
正文
简单开始(不使用任何框架)
npm init vite@latest
然后一路回车
cd vite-project
npm install
npm run dev
然后你就搭建成功了!
ctrl + c停掉
然后
(base) root@racknerd-cecdb9:~/myspace/three/noFrame-three-app/vite-project# npm install three
#假如你就想下0.153的版本,你可以直接npm install three@0.153
然后你就可以使用
https://threejs.org/docs/#manual/zh/introduction/Creating-a-scene
的例子了
(稍作部分修改)
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script type="module" src="src/main.js"></script>
</body>
</html>
- main.js
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
//创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//创建几何体
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
//创建材质
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
//创建网格=几何体+材质
const cube = new THREE.Mesh( geometry, material );
//将网格添加到场景
scene.add( cube );
//正对着我们的是z轴
camera.position.z = 5;
//默认看向原点
camera.lookAt(0,0,0);
function animate() {
//播放下一帧,继续调用animate函数
requestAnimationFrame( animate );
//旋转
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
//渲染
renderer.render( scene, camera );
}
//调用函数
animate();
然后就直接诶直接可以npm run dev
补充
canvas:画布
粗略带过(使用Vue框架)
npm init vite@latest
然后不要一路回车了!!!!
你可以在这里选择相关的前端框架,你可以看到非常的多,在这里我们选择Vue框架
# 我们选择Vue+JavaScript
✔ Project name: … vite-project
✔ Select a framework: › Vue
✔ Select a variant: › JavaScript
cd vite-project
npm install
npm run dev
然后你就搭建成功了!
ctrl + c停掉
然后
(base) root@racknerd-cecdb9:~/myspace/three/noFrame-three-app/vite-project# npm install three
- 你只需要修改Vue.app,然后npm run dev就欧克了
<script setup>
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
//创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
//创建材质
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
//创建网格=几何体+材质
const cube = new THREE.Mesh(geometry, material);
//将网格添加到场景
scene.add(cube);
//正对着我们的是z轴
camera.position.z = 5;
//默认看向原点
camera.lookAt(0, 0, 0);
function animate() {
//播放下一帧,继续调用animate函数
requestAnimationFrame(animate);
//旋转
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
//渲染
renderer.render(scene, camera);
}
//调用函数
animate();
</script>
<template>
<div></div>
</template>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>
细致讲解(比如我使用react框架)
npm init vite@latest
然后不要一路回车了!!!!
你可以在这里选择相关的前端框架,你可以看到非常的多,在这里我们选择React框架
选择结果:
Vanilla
✔ Select a framework: › React
✔ Select a variant: › JavaScript
cd vite-project
npm install
npm install three
npm run dev
- 修改App.jsx
import { useState, useEffect, Component } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import * as THREE from 'three';
// function App() {
// useEffect(() => {
// const scene = new THREE.Scene();
// const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// //创建渲染器
// const renderer = new THREE.WebGLRenderer();
// renderer.setSize(window.innerWidth, window.innerHeight);
// document.body.appendChild(renderer.domElement);
// //创建几何体
// const geometry = new THREE.BoxGeometry(1, 1, 1);
// //创建材质
// const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// //创建网格=几何体+材质
// const cube = new THREE.Mesh(geometry, material);
// //将网格添加到场景
// scene.add(cube);
// //正对着我们的是z轴
// camera.position.z = 5;
// //默认看向原点
// camera.lookAt(0, 0, 0);
// //创建轨道控制器
// //const controls = new OrbitControls(camera, renderer.domElement);
// function animate() {
// //播放下一帧,继续调用animate函数
// requestAnimationFrame(animate);
// //旋转
// cube.rotation.x += 0.01;
// cube.rotation.y += 0.01;
// //渲染
// renderer.render(scene, camera);
// }
// //调用函数
// animate();
// }, [])
// return (
// <>
// <div className='App'></div>
// </>
// )
// }
class App extends Component {
render() {
return <div></div>
}
componentDidMount() {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
//创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
//创建材质
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
//创建网格=几何体+材质
const cube = new THREE.Mesh(geometry, material);
//将网格添加到场景
scene.add(cube);
//正对着我们的是z轴
camera.position.z = 5;
//默认看向原点
camera.lookAt(0, 0, 0);
//创建轨道控制器
//const controls = new OrbitControls(camera, renderer.domElement);
function animate() {
//播放下一帧,继续调用animate函数
requestAnimationFrame(animate);
//旋转
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
//渲染
renderer.render(scene, camera);
}
//调用函数
animate();
}
}
export default App
- 修改index.css
* {
margin: 0;
padding: 0;
}
canvas {
display: block;
position: fixed;
left: 0;
top: 0;
width: 0;
height: 0;
}
App.jsx 的进阶版
import { useState, useEffect, Component } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import * as THREE from 'three';
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 导入动画库
import gsap from "gsap";
// function App() {
// useEffect(() => {
// const scene = new THREE.Scene();
// const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// //创建渲染器
// const renderer = new THREE.WebGLRenderer();
// renderer.setSize(window.innerWidth, window.innerHeight);
// document.body.appendChild(renderer.domElement);
// //创建几何体
// const geometry = new THREE.BoxGeometry(1, 1, 1);
// //创建材质
// const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// //创建网格=几何体+材质
// const cube = new THREE.Mesh(geometry, material);
// //将网格添加到场景
// scene.add(cube);
// //正对着我们的是z轴
// camera.position.z = 5;
// //默认看向原点
// camera.lookAt(0, 0, 0);
// //创建轨道控制器
// //const controls = new OrbitControls(camera, renderer.domElement);
// function animate() {
// //播放下一帧,继续调用animate函数
// requestAnimationFrame(animate);
// //旋转
// cube.rotation.x += 0.01;
// cube.rotation.y += 0.01;
// //渲染
// renderer.render(scene, camera);
// }
// //调用函数
// animate();
// }, [])
// return (
// <>
// <div className='App'></div>
// </>
// )
// }
class App extends Component {
render() {
return <div></div>
}
componentDidMount() {
// const scene = new THREE.Scene();
// const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// //创建渲染器
// const renderer = new THREE.WebGLRenderer();
// renderer.setSize(window.innerWidth, window.innerHeight);
// document.body.appendChild(renderer.domElement);
// //创建几何体
// const geometry = new THREE.BoxGeometry(1, 1, 1);
// //创建材质
// const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// //创建网格=几何体+材质
// const cube = new THREE.Mesh(geometry, material);
// //将网格添加到场景
// scene.add(cube);
// //正对着我们的是z轴
// camera.position.z = 5;
// //默认看向原点
// camera.lookAt(0, 0, 0);
// //创建轨道控制器
// //const controls = new OrbitControls(camera, renderer.domElement);
// function animate() {
// //播放下一帧,继续调用animate函数
// requestAnimationFrame(animate);
// //旋转
// cube.rotation.x += 0.01;
// cube.rotation.y += 0.01;
// //渲染
// renderer.render(scene, camera);
// }
// //调用函数
// animate();
// console.log(THREE);
// 设置场景、相机
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera);
//渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 监听窗口大小变化事件
window.addEventListener('resize', function () {
var width = window.innerWidth;
var height = window.innerHeight;
// 更新相机的宽高比
camera.aspect = width / height;
// 更新相机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器大小
renderer.setSize(width, height);
// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
// 创建一个立方体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
/**************/
// 创建轨道控制器(此时你可以使用右键让模型动起来)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;
// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// 设置时钟
const clock = new THREE.Clock();
window.addEventListener("dblclick", () => {
const fullScreenElement = document.fullscreenElement;
if (!fullScreenElement) {
// 双击控制屏幕进入全屏,退出全屏
// 让画布对象全屏
renderer.domElement.requestFullscreen();
} else {
// 退出全屏,使用document对象
document.exitFullscreen();
}
// console.log(fullScreenElement);
});
/**************/
// 鼠标交互
let isDragging = false;
let previousMousePosition = {
x: 0,
y: 0
};
function onDocumentMouseDown(event) {
isDragging = true;
}
function onDocumentMouseMove(event) {
if (isDragging) {
var deltaMove = {
x: event.clientX - previousMousePosition.x,
y: event.clientY - previousMousePosition.y
};
const deltaRotationQuaternion = new THREE.Quaternion()
.setFromEuler(new THREE.Euler(
toRadians(deltaMove.y * 1),
toRadians(deltaMove.x * 1),
0,
'XYZ'
));
cube.quaternion.multiplyQuaternions(deltaRotationQuaternion, cube.quaternion);
}
previousMousePosition = {
x: event.clientX,
y: event.clientY
};
}
function onDocumentMouseUp(event) {
isDragging = false;
}
// 将鼠标事件监听器添加到渲染器的DOM元素
renderer.domElement.addEventListener('mousedown', onDocumentMouseDown, false);
renderer.domElement.addEventListener('mousemove', onDocumentMouseMove, false);
renderer.domElement.addEventListener('mouseup', onDocumentMouseUp, false);
// 动画循环渲染
function animate() {
// 如果没有鼠标交互,立方体会自动旋转
if (!isDragging) {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
}
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate(); // 开始动画循环
// 辅助函数:将角度转换为弧度
function toRadians(angle) {
return angle * (Math.PI / 180);
}
}
}
export default App
// // 目标:js控制画面全屏
// // 1、创建场景
// const scene = new THREE.Scene();
// // 2、创建相机
// const camera = new THREE.PerspectiveCamera(
// 75,
// window.innerWidth / window.innerHeight,
// 0.1,
// 1000
// );
// // 设置相机位置
// camera.position.set(0, 0, 10);
// scene.add(camera);
// // 添加物体
// // 创建几何体
// const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
// // 根据几何体和材质创建物体
// const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// // 修改物体的位置
// // cube.position.set(5, 0, 0);
// // cube.position.x = 3;
// // 缩放
// // cube.scale.set(3, 2, 1);
// // cube.scale.x = 5;
// // 旋转
// cube.rotation.set(Math.PI / 4, 0, 0, "XZY");
// // 将几何体添加到场景中
// scene.add(cube);
// console.log(cube);
// // 初始化渲染器
// const renderer = new THREE.WebGLRenderer();
// // 设置渲染的尺寸大小
// renderer.setSize(window.innerWidth, window.innerHeight);
// // console.log(renderer);
// // 将webgl渲染的canvas内容添加到body
// document.body.appendChild(renderer.domElement);
// // // 使用渲染器,通过相机将场景渲染进来
// // renderer.render(scene, camera);
// // 创建轨道控制器
// const controls = new OrbitControls(camera, renderer.domElement);
// // 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
// controls.enableDamping = true;
// // 添加坐标轴辅助器
// const axesHelper = new THREE.AxesHelper(5);
// scene.add(axesHelper);
// // 设置时钟
// const clock = new THREE.Clock();
// window.addEventListener("dblclick", () => {
// const fullScreenElement = document.fullscreenElement;
// if (!fullScreenElement) {
// // 双击控制屏幕进入全屏,退出全屏
// // 让画布对象全屏
// renderer.domElement.requestFullscreen();
// } else {
// // 退出全屏,使用document对象
// document.exitFullscreen();
// }
// // console.log(fullScreenElement);
// });
// function render() {
// controls.update();
// renderer.render(scene, camera);
// // 渲染下一帧的时候就会调用render函数
// requestAnimationFrame(render);
// }
// render();
// // 监听画面变化,更新渲染画面
// window.addEventListener("resize", () => {
// // console.log("画面变化了");
// // 更新摄像头
// camera.aspect = window.innerWidth / window.innerHeight;
// // 更新摄像机的投影矩阵
// camera.updateProjectionMatrix();
// // 更新渲染器
// renderer.setSize(window.innerWidth, window.innerHeight);
// // 设置渲染器的像素比
// renderer.setPixelRatio(window.devicePixelRatio);
项目打包
教程:https://juejin.cn/post/6869708334371602445
如果不想看教程,那就直接往下看
你就直接在项目的根目录下执行
npm run build
就行了
然后你就生成了一个dist目录,你把dist目录下的文件放在服务器下面就能直接跑!(假如你生成的文件夹和我的这个不一样,请看下面的补充)
补充
打包遇到的问题:
你可能会遇到下面三种情况:
- 只生成了dist目录
- 只生成了build目录
- 既生成了dist目录又生成了build目录
原因:
版本不同,操作系统不同,配置文件也有差异
解决办法:
- 如果只生成了一个dist文件,就只需要把
这一个文件下的内容
放在服务器下即可. - 如果build和dist都生成了,就把
他们两个的文件夹里面的内容
一起放在在服务器下. - 如果只生成了一个build文件,就只需要把
这一个文件下的内容
放在服务器下即可.