three.js 帶更新文字的旋轉地球
阿新 • • 發佈:2019-04-17
主要用到幾個知識點
(1)顯示文字是使用了three.js 的精靈(Sprite),精靈的文字方向始終面向相機,文字是在canvas中畫的,精靈的材質就是載入的帶有文字的canvas
function showText(){ const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); ctx.canvas.width =256; const x =0; const y=32; ctx.fillStyle = "red"; ctx.font = "30px arial"; ctx.textAlign = "left"; ctx.textBaseline = "middle"; ctx.fillText(text,x,y) }
var sprite function showSprite(){ showText() const canvasTexture = new THREE.CanvasTexture( document.querySelector("#canvas") ) const spritMaterial = new THREE.SpriteMaterial({ map:canvasTexture }) sprite = new THREE.Sprite(spritMaterial) sprite.position.set(-280,0,0); //精靈的預設大小很小估計是[1,1,1] sprite.scale.set(0.64*256,0.64*64,1); scene.add(sprite) }
(2)文字更新的方法是為canvas的文字重新賦值,並在動畫中移除上次載入的精靈,否則精靈會重疊
scene.remove(sprite)
(3)視窗變化時自適應
window.addEventListener("resize", onWindowResize, false); function onWindowResize() { width = document.getElementById('canvas-frame').clientWidth; height = document.getElementById('canvas-frame').clientHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height); }
完整程式碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>旋轉地球</title>
<script src="assets/plus/threejs/three.min.js"></script>
<script src="assets/plus/threejs/js/controls/OrbitControls.js"></script>
<script src="assets/plus/threejs/js/libs/stats.min.js"></script>
<style type="text/css">
body {
margin: 0px;
}
div#canvas-frame {
border: none;
cursor: pointer;
width: 80%;
margin:0 auto;
height:100vh;
background-color: #EEEEEE;
}
img {
width: 0px;
height: 0px;
opacity: 0;
}
</style>
</head>
<body>
<canvas id="canvas" width="64" height="64" style="display:none;"></canvas>
<!-- 存放canvas的容器 -->
<div id="canvas-frame"></div>
</body>
<script>
document.addEventListener('DOMContentLoaded', function () {
threeStart();
})
var text = "first text";
function showText(){
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.canvas.width =256;
const x =0;
const y=32;
ctx.fillStyle = "red";
ctx.font = "30px arial";
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillText(text,x,y)
}
// 渲染器
var renderer;
var width, height;
function initThree() {
width = document.getElementById('canvas-frame').clientWidth;
height = document.getElementById('canvas-frame').clientHeight;
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
canvas: renderer
});
renderer.setSize(width, height);
document.getElementById('canvas-frame').appendChild(renderer.domElement);
renderer.setClearColor(0x000000, 1.0);
}
// 相機
var camera;
function initCamera() {
// 透視相機 視角越大,看到的場景越大,那麼中間的物體相對於整個場景來說,就越小了
camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 700;
//camera.lookAt({ x: 0, y: 0, z: 0 });
}
// 場景
var scene;
function initScene() {
scene = new THREE.Scene();
}
// 光源
var light;
function initLight() {
// 環境光
light = new THREE.AmbientLight(0xFFFFFF);
light.position.set(100, 100, 200);
scene.add(light);
// 平行光
// 位置不同,方向光作用於物體的面也不同,看到的物體各個面的顏色也不一樣
// light = new THREE.DirectionalLight(0xffffbb, 1);
// light.position.set(-1, 1, 1);
// scene.add(light);
}
// 地球
var earthMesh;
function initEarth() {
var earthGeo = new THREE.SphereGeometry(200, 100, 100);
var earthMater = new THREE.MeshPhongMaterial({
map: new THREE.TextureLoader().load('./assets/earth.jpg'),
//side: THREE.DoubleSide
});
earthMesh = new THREE.Mesh(earthGeo, earthMater);
scene.add(earthMesh);
}
// 雲
var cloudsMesh;
function initClouds() {
var cloudsGeo = new THREE.SphereGeometry(201, 100, 100);
var cloudsMater = new THREE.MeshPhongMaterial({
alphaMap: new THREE.TextureLoader().load('./assets/clouds.jpg'),
transparent: true,
opacity: 0.2
});
cloudsMesh = new THREE.Mesh(cloudsGeo, cloudsMater);
scene.add(cloudsMesh);
}
var controls;
function threeStart() {
initThree();
//initStats();
initCamera();
initScene();
initLight();
initEarth();
initClouds();
// 載入控制器
controls = new THREE.OrbitControls(camera, renderer.domElement);
window.addEventListener("resize", onWindowResize, false);
//renderer.clear();
animate();
}
function onWindowResize() {
width = document.getElementById('canvas-frame').clientWidth;
height = document.getElementById('canvas-frame').clientHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
var sprite
function showSprite(){
showText()
const canvasTexture = new THREE.CanvasTexture(
document.querySelector("#canvas")
)
//canvasTexture.needsUpdate = true; //注意這句不能少
const spritMaterial = new THREE.SpriteMaterial({
map:canvasTexture
})
sprite = new THREE.Sprite(spritMaterial)
sprite.position.set(-280,0,0);
//精靈的預設大小很小估計是[1,1,1]
sprite.scale.set(0.64*256,0.64*64,1);
scene.add(sprite)
}
function animate() {
text="new text";
scene.remove(sprite)
showSprite();
controls.update();
//stats.update();
// 地球自轉
earthMesh.rotation.y -= 0.002;
// 漂浮的雲層
cloudsMesh.rotation.y -= 0.005;
cloudsMesh.rotation.z += 0.005;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
</script>
</html>