本文搬自我的Github,,https://github.com/555chy/three.js-example-comment,,有興趣的可以一起來完善,這個為Three.js的Example進(jìn)行注解,,方便初學(xué)者閱讀
three.js 官網(wǎng) Example 地址:https:///examples/
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js software - geometry - earth</title>
<meta charset="utf-8">
<!--
如果沒有設(shè)置viewport的width的話,,網(wǎng)頁很可能會超出手機(jī)屏幕寬度,,具體多寬,要看瀏覽器定義的默認(rèn)寬度是多少
user-scalable=no,,規(guī)定了用戶不能縮放網(wǎng)頁,,但有些瀏覽器對該項支持不是很好,故需要設(shè)置minimum-scale和maximum-scale相同來限制用戶縮放
-->
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #808080;
font-family:Monospace;
font-size:13px;
text-align:center;
background-color: #ffffff;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px;
/*
relative的div:width默認(rèn)是window.innerWidth
absolute的div:width默認(rèn)是內(nèi)容大小
由于在body上指定了text-align,,因此這里只需要設(shè)置width:100%就可以讓文本居中了
*/
width: 100%;
padding: 5px;
}
/*
未訪問 a:link {color:blue;}
已訪問 a:visited {color:blue;}
鼠標(biāo)懸停 a:hover {color:red;}
鼠標(biāo)按下 a:active {color:yellow;}
*/
a {
color: #0080ff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info"><a href="http://" target="_blank">three.js</a> - earth demo</div>
<script src="../build/three.js"></script>
<!--
想要使用CanvasRenderer,,必須添加如下兩個js文件
第一個文件顧名思義上將3d圖像投影到Canvas("2d")上,如果沒有該文件會報如下錯誤
THREE.Projector has been moved to /examples/js/renderers/Projector.js. three.js:42883:3
TypeError: THREE.RenderableVertex is not a constructor
-->
<script src="js/renderers/Projector.js"></script>
<script src="js/renderers/SoftwareRenderer.js"></script>
<!--
統(tǒng)計插件(FPS,,渲染時間,,chrome內(nèi)存使用率),min表示js代碼經(jīng)過壓縮
-->
<script src="js/libs/stats.min.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
var group;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.getElementById( 'container' );
/*
透視相機(jī)
PerspectiveCamera(fov, aspect, near, far)
fov(視場):從相機(jī)位置能夠看到的部分場景,。推薦默認(rèn)值45
aspect(長寬比):渲染結(jié)果輸出區(qū)域的橫向長度和縱向長度的比值,。推薦默認(rèn)值window.innerWidth/window.innerHeight
near(近面):定義從距離相機(jī)多近的地方開始渲染場景。推薦默認(rèn)值0.1
far(遠(yuǎn)面):定義相機(jī)可以從它所處的位置看多遠(yuǎn),。默認(rèn)值1000
*/
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
//定義相機(jī)的位置,,有如下兩種方式。如果不設(shè)置的話,,相機(jī)位置為默認(rèn)的Vector3{x:0,y:0,z:0}
//camera.position.set(0,0,500);
camera.position.z = 500;
scene = new THREE.Scene();
//three.js中的分組,,同一個分組中的對象可以一起執(zhí)行某項操作,不用再進(jìn)行遍歷判斷
group = new THREE.Group();
scene.add( group );
// earth
var loader = new THREE.TextureLoader();
/*
TextureLoader.load: function ( url, onLoad, onProgress, onError )
function onLoad( texture ) {……}
function onProgress ( event ) {……}
function onEvent ( event ) {……}
從源碼可以看出,,TextureLoader實際上是對ImageLoader的封裝,,加載完成后調(diào)用onLoad函數(shù)。
此外在ImageLoader的源碼中onProgress方法的回調(diào)被注釋掉了,,因此如果傳遞該函數(shù)則不會被執(zhí)行
*/
loader.load( 'textures/land_ocean_ice_cloud_2048.jpg', function ( texture ) {
/*
創(chuàng)建半徑為200,,寬高各切20等分的球體
function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {……}
*/
var geometry = new THREE.SphereGeometry( 200, 20, 20 );
/*
MeshLambertMaterial的紋理顏色會隨著光照改變
overdraw:過渡描繪。如果用THREE.CanvasRenderer對象,,有縫隙時需設(shè)置該值,。例如當(dāng)前如果使用0.5以下的值,,三角形的分界線就很明顯,。但是使用WebGLRenderer則不會有分割線
*/
var material = new THREE.MeshLambertMaterial( { map: texture, overdraw: 0.5 } );
//網(wǎng)格化或?qū)嵗象w
var mesh = new THREE.Mesh( geometry, material );
group.add( mesh );
} );
// shadow
var canvas = document.createElement( 'canvas' );
canvas.width = 128;
canvas.height = 128;
var context = canvas.getContext( '2d' );
/*
context.createRadialGradient(x0,y0,r0,x1,y1,r1);
x0 漸變的開始圓的 x 坐標(biāo)
y0 漸變的開始圓的 y 坐標(biāo)
r0 開始圓的半徑
x1 漸變的結(jié)束圓的 x 坐標(biāo)
y1 漸變的結(jié)束圓的 y 坐標(biāo)
r1 結(jié)束圓的半徑
*/
var gradient = context.createRadialGradient(
canvas.width / 2,
canvas.height / 2,
0,
canvas.width / 2,
canvas.height / 2,
canvas.width / 2
);
gradient.addColorStop( 0.1, 'rgba(210,210,210,1)' );
gradient.addColorStop( 1, 'rgba(255,255,255,1)' );
context.fillStyle = gradient;
context.fillRect( 0, 0, canvas.width, canvas.height );
//畫布紋理,使用畫布初始化某個紋理
var texture = new THREE.CanvasTexture( canvas );
var geometry = new THREE.PlaneBufferGeometry( 300, 300, 3, 3 );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.y = - 250;
mesh.rotation.x = - Math.PI / 2;
group.add( mesh );
/*
這里如果直接換成WebGLRenderer的話,地球是黑的,,這是因為沒有環(huán)境光。所以要這么替換
renderer = new THREE.WebGLRenderer();
scene.add( new THREE.AmbientLight( 0xffffff ) );
*/
renderer = new THREE.SoftwareRenderer();
//設(shè)置渲染器的"清除色"和"透明度"
renderer.setClearColor( 0x000000 );
//設(shè)置待渲染場景的大小
renderer.setSize( window.innerWidth, window.innerHeight );
//將渲染器的DOM元素(即Canvas)添加到HTML中
container.appendChild( renderer.domElement );
//左上角的統(tǒng)計信息(FPS,,渲染時間,,chrome內(nèi)存使用率)
stats = new Stats();
//這里注意,統(tǒng)計插件的dom元素是"dom",,而不是domElement
container.appendChild( stats.dom );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
//重新設(shè)置相機(jī)的寬高比,。如果寬高比不對,,那么正方形可能就不是正方形了
camera.aspect = window.innerWidth / window.innerHeight;
//更新透視相機(jī)的投影矩陣
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
//記錄與屏幕中心點的距離
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
function animate() {
requestAnimationFrame( animate );
render();
//這里可以在render前后使用stats.begin和stats.end,也可以在每次渲染的時候調(diào)用一次stats.update
stats.update();
}
function render() {
/*
即如下兩個公式,,由于瀏覽器的X軸方向與WebGL的X軸方向相同,,而Y軸方向相反,所以X用正的,,而Y用負(fù)的
camera.position.x = camera.position.x * 0.95 + mouseX * 0.05;
camera.position.y = camera.position.y * 0.95 - mouseY * 0.05;
*/
camera.position.x += ( mouseX - camera.position.x ) * 0.05;
camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
//相機(jī)重新注視場景中央,,否則相機(jī)只會對著原lookAt計算出的向量方向
camera.lookAt( scene.position );
//將旋轉(zhuǎn)的角度按右手螺旋定則繞著Y軸旋轉(zhuǎn),有以下兩種方式實現(xiàn)旋轉(zhuǎn)
group.rotation.y -= 0.005;
//group.rotateY(0.005);
renderer.render( scene, camera );
}
</script>
</body>
</html>
|