我最近在写three.js相关的代码,然后我也不想去说什么原理的事情,我刚看文档照着去写的。
先看这个球吧!
实际上是很流畅的,哈哈,只是我限制了图片的大小,gif不能录得太大。
在写球之前呢,先把准备工作做好!
准备工作
准备工作得有摄影机(观众视角),场景,控制器(摄影机的轨道),灯光(选配)
需要安装的库
npm install --save three
我的是vue项目,这个自行解决哈
模版代码:
<template>
<div id="container" ref="container">
<div class="loading" v-show="isLoading">
正在非常玩命加载中...
</div>
<div class="content-part" v-show="!isLoading">
<div id="canvas-container" ref="canvasDom">
</div>
</div>
</div>
</template>
<style>
.loading {
z-index: 1000;
position: fixed;
text-align: center;
line-height: 100vh;
font-size: 5vw;
height: 100vh;
width: 100vw;
}
</style>
<script>
import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
export default {
name: 'App',
data() {
return {
camera: null,
scene: null,
render: null,
controller: null,
isLoading: true,
isTouch: false,
earthMesh: null,
isWechatBrowser: false
};
},
mounted() {
//修复部分纹理随机黑色问题
let ua = navigator.userAgent;
if (/MicroMessenger/.test(ua) || /AlipayClient/.test(ua)) {
this.isWechatBrowser = true
} else {
this.isWechatBrowser = false;
}
const IS_IOS =
/^(iPad|iPhone|iPod)/.test(window.navigator.platform) ||
(/^Mac/.test(window.navigator.platform) && window.navigator.maxTouchPoints > 1);
if (IS_IOS || this.isWechatBrowser) {
window.createImageBitmap = undefined;
}
this.init();
this.doRender();
},
methods: {
doRender() {
this.render.render(this.scene, this.camera);
if (this.controller) {
this.controller.update();
}
if (!this.isTouch && this.earthMesh) {
this.earthMesh.rotation.x += 0.0001;
this.earthMesh.rotation.y -= 0.0005;
}
requestAnimationFrame(this.doRender);
},
async init() {
//场景
this.scene = new THREE.Scene();
//相机
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
if (this.isWechatBrowser) {
this.camera.position.set(16, 16, 16);
} else {
this.camera.position.set(10, 10, 10);
}
//渲染器,抗锯齿
this.render = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
//大小
this.render.setSize(window.innerWidth, window.innerHeight);
let canvasDom = document.getElementById('canvas-container');
canvasDom.appendChild(this.render.domElement);
//设置渲染背景
this.render.setClearColor("#000");
this.render.setPixelRatio(window.devicePixelRatio);
this.scene.background = new THREE.Color("#ccc");
this.scene.environment = new THREE.Color("#ccc");
//网格
let grid = new THREE.GridHelper(30, 30);
grid.opticity = 0.5;
grid.material.transparent = true;
this.scene.add(grid);
//坐标
const axeshelper = new THREE.AxesHelper(30);
this.scene.add(axeshelper);
//控制器
this.controller = new OrbitControls(this.camera, this.render.domElement);
this.controller.addEventListener('start', () => {
this.isTouch = true;
});
this.controller.addEventListener('end', () => {
this.isTouch = false;
});
}
}
}
</script>
放内容
有了前面这个环境,我们可以往里面放我们想要的东西了
于是我多加了一个方法initContent
<template>
<div id="container" ref="container">
<div class="loading" v-show="isLoading">
正在非常玩命加载中...
</div>
<div class="content-part" v-show="!isLoading">
<div id="canvas-container" ref="canvasDom">
</div>
</div>
</div>
</template>
<style>
.loading {
z-index: 1000;
position: fixed;
text-align: center;
line-height: 100vh;
font-size: 5vw;
height: 100vh;
width: 100vw;
}
</style>
<script>
import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
export default {
name: 'App',
data() {
return {
camera: null,
scene: null,
render: null,
controller: null,
isLoading: true,
isTouch: false,
earthMesh: null,
isWechatBrowser: false
};
},
mounted() {
//修复部分纹理随机黑色问题
let ua = navigator.userAgent;
if (/MicroMessenger/.test(ua) || /AlipayClient/.test(ua)) {
this.isWechatBrowser = true
} else {
this.isWechatBrowser = false;
}
const IS_IOS =
/^(iPad|iPhone|iPod)/.test(window.navigator.platform) ||
(/^Mac/.test(window.navigator.platform) && window.navigator.maxTouchPoints > 1);
if (IS_IOS || this.isWechatBrowser) {
window.createImageBitmap = undefined;
}
this.init();
this.initContent();
this.doRender();
},
methods: {
doRender() {
this.render.render(this.scene, this.camera);
if (this.controller) {
this.controller.update();
}
if (!this.isTouch && this.earthMesh) {
this.earthMesh.rotation.x += 0.0001;
this.earthMesh.rotation.y -= 0.0005;
}
requestAnimationFrame(this.doRender);
},
async init() {
//场景
this.scene = new THREE.Scene();
//相机
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
if (this.isWechatBrowser) {
this.camera.position.set(16, 16, 16);
} else {
this.camera.position.set(10, 10, 10);
}
//渲染器
this.render = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
//大小
this.render.setSize(window.innerWidth, window.innerHeight);
let canvasDom = document.getElementById('canvas-container');
canvasDom.appendChild(this.render.domElement);
//设置渲染背景
this.render.setClearColor("#000");
this.render.setPixelRatio(window.devicePixelRatio);
this.scene.background = new THREE.Color("#ccc");
this.scene.environment = new THREE.Color("#ccc");
//网格
// let grid = new THREE.GridHelper(30, 30);
// grid.opticity = 0.5;
// grid.material.transparent = true;
// this.scene.add(grid);
//坐标
// const axeshelper = new THREE.AxesHelper(30);
// this.scene.add(axeshelper);
//控制器
this.controller = new OrbitControls(this.camera, this.render.domElement);
this.controller.addEventListener('start', () => {
this.isTouch = true;
});
this.controller.addEventListener('end', () => {
this.isTouch = false;
});
},
initContent(){
let texturePainting = await new THREE.TextureLoader().load('https://sob-public-dev-1256182135.cos.ap-chongqing.myqcloud.com/lh/earth.png');
let materialPainting = new THREE.MeshBasicMaterial({color: 0xffffff, map: texturePainting});
this.earthMesh = new THREE.Mesh(
new THREE.SphereBufferGeometry(9, 100, 100),
materialPainting
// new THREE.MeshNormalMaterial( { flatShading: true } )
);
this.scene.add(this.earthMesh);
setInterval(() => {
this.isLoading = false;
}, 1000);
}
}
}
</script>
到这里,我们的球就出来了
扩展
贴图内容,贴图我是从腾讯抠的
可是上传了就有水印了,我加一个动态的连接吧,动态没有水印
我还做了啥呢?
椅子,多亏了断点帮忙切图