前言
ThreeJS是一个用JavaScript写的开源3D图形库,它有个简单但是功能强大的3D渲染引擎,可以在网页浏览器里快速创建和展示3D图形。ThreeJS是一个功能强大、使用简单的3D图形库,提供了一个强大的3D渲染工具,大大降低了创建3D应用程序的难度。
效果图
解析
安装
代码包可以到网上去找一些迷你版本的包,先放在本地用一下,然后跑终端可以从终端运行:npx vite
插件
Three.js 开箱即用,包含 3D 引擎的基础知识。其他 Three.js 组件(例如控件、加载器和后处理效果)是addons/目录的一部分。插件不需要单独安装,但需要单独导入。
轨道控制
轨道控制允许相机围绕目标旋转。 要使用此功能,与 /examples 目录中的所有文件一样,您必须将该文件单独包含在 HTML 中。
OrbitControls 是一个附加组件,必须显式导入。请参阅安装/插件。
import{OrbitControls}from'three/addons/controls/OrbitControls.js';
创建场景
为了真正能够用 Three.js 显示任何东西,我们需要三样东西:场景、相机和渲染器,这样我们就可以用相机渲染场景。
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 );
渲染场景
如果您将上面的代码复制到我们之前创建的 HTML 文件中,您将看不到任何内容。这是因为我们实际上还没有渲染任何东西。
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
添加轨道
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.minPolarAngle = Math.PI / 2 - 0.6;
controls.maxPolarAngle = Math.PI / 2 + 0.1;
controls.target.y = 2;
添加照片
function addBox(imageUrl) {
const texture = textureLoader.load(imageUrl);
const geometry = new THREE.BoxGeometry(5, 5, 0.2);
const material = new THREE.MeshLambertMaterial({ color: 0xffffff, map: texture });
const cube = new THREE.Mesh(geometry, material);
//cube.position.y = 2.5;
cube.position.setFromCylindricalCoords(random(15, 25), random(-Math.PI * 2, Math.PI * 2), 2.5);
cube.lookAt(0, 2, 0);
scene.add(cube);
const lookAtPosition = new THREE.Vector3(0, 2, 0);
lookAtPosition.lerp(cube.position, 0.3);
controls.target.copy(lookAtPosition);
}
代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three js</title>
<style>
html,
body {
height: 100%;
overflow: hidden;
margin: 0;
}
input {
position: fixed;
top: 90vh;
left: 50vw;
transform: translate(-50%, -50%);
background: transparent;
border: 1px solid #fff;
padding: 10px 20px;
font-size: 24px;
color: #fff;
opacity: 0.2;
outline: none;
transition: 0.5s;
border-radius: 5px;
}
input:focus {
opacity: 1;
}
</style>
</head>
<body>
<input type="text" id="caption" placeholder="Type a caption">
<script src="third_party/three.min.js"></script>
<script src="third_party/OrbitControls.js"></script>
<script src="js/index.js"></script>
</body>
</html>
index.js
function random(min, max) {
return min + Math.random() * (max - min);
}
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({
antialias: true,
powerPreference: 'high-performance'
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.outputEncoding = THREE.sRGBEncoding;
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.minPolarAngle = Math.PI / 2 - 0.6;
controls.maxPolarAngle = Math.PI / 2 + 0.1;
controls.target.y = 2;
const ambientLight = new THREE.AmbientLight(0x202020);
scene.add(ambientLight);
const hemiLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
hemiLight.color.setHSL(0.6, 1, 0.1);
hemiLight.groundColor.setHSL(0.1, 0.2, 0.1);
scene.add(hemiLight);
const gridHelper = new THREE.GridHelper(100, 20);
scene.add(gridHelper);
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(0, 10, 5);
scene.add(pointLight);
const groundGeo = new THREE.PlaneBufferGeometry(105, 105);
const groundMat = new THREE.MeshLambertMaterial({ side: THREE.DoubleSide });
groundMat.color.setHSL(0.095, 1, 0.75);
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
const textureLoader = new THREE.TextureLoader();
function addBox(imageUrl) {
const texture = textureLoader.load(imageUrl);
const geometry = new THREE.BoxGeometry(5, 5, 0.2);
const material = new THREE.MeshLambertMaterial({ color: 0xffffff, map: texture });
const cube = new THREE.Mesh(geometry, material);
//cube.position.y = 2.5;
cube.position.setFromCylindricalCoords(random(15, 25), random(-Math.PI * 2, Math.PI * 2), 2.5);
cube.lookAt(0, 2, 0);
scene.add(cube);
const lookAtPosition = new THREE.Vector3(0, 2, 0);
lookAtPosition.lerp(cube.position, 0.3);
controls.target.copy(lookAtPosition);
}
for (let i = 0; i < 10; i++) {
addBox('img/641.jpg')
}
camera.position.z = 5;
function generateImage(caption) {
const inputs = {
"caption": caption
};
fetch('http://localhost:8001/query', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(inputs)
})
.then(response => response.json())
.then(outputs => {
const { result } = outputs;
console.log(result);
addBox(result);
})
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
document.getElementById('caption').addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
const caption = e.currentTarget.value;
generateImage(caption);
e.currentTarget.value = '';
}
})
generateImage('a boat');