示例是一個 星球,頂點上 是 文字。可旋轉,縮放:html
<html> <head> <title>球狀旋轉_sprite_v2.html</title> <meta charset="utf-8"> <style> body { margin: 0; } </style> </head> <body> </body> <script src="js/three.js"></script> <script src="js/OrbitControls.js"></script> <script> /** * 3d加載步驟 * 一、獲得三大基礎模塊:scene, camera, renderer * 二、繪製結果與DOM掛鉤 * 三、加載攝像頭控制器(可選) * 四、添加場景內 模型 * 五、渲染 * 六、事件設置(可選) */ var scene, camera, renderer, controls, group; var container; var startX, startY; container = document.createElement( 'div' ); document.body.appendChild( container ); /*1*/ scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera( 40, window.innerWidth/window.innerHeight, 1, 1000 ); camera.position.z = 50; renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); /*2*/ container.appendChild( renderer.domElement ); /*3*/ // controls controls = new THREE.OrbitControls( camera, renderer.domElement ); controls.minDistance = 20; controls.maxDistance = 50; controls.maxPolarAngle = Math.PI / 2; /*4*/ group = new THREE.Group(); scene.add( group ); var vertices = new THREE.DodecahedronGeometry( 10 ).vertices; //多個精靈 vertices.forEach(function (item, index) { var sprite = createSpriteTextNoPosition(index); sprite.position.set(item.x, item.y, item.z); sprite.clickFlag = true; sprite.aa = '序號:' + index; group.add(sprite); }); /*5*/ var animate = function () { requestAnimationFrame( animate ); // group.rotation.x += 0.005; group.rotation.y += 0.005; renderer.render( scene, camera ); }; animate(); /*6*/ //監聽移動端touchstart事件 function onTouchStart(e) { // console.log('觸摸開始') // console.log(e) var touch = e.touches[0]; //獲取第一個觸點 var x = Number(touch.pageX); //頁面觸點X座標 var y = Number(touch.pageY); //頁面觸點Y座標 //記錄觸點初始位置 startX = x; startY = y; } //監聽移動端touchEnd事件 function onTouchEnd(e) { // console.log('觸摸結束') // console.log(e); if (e.changedTouches[0].pageX == startX && e.changedTouches[0].pageY == startY) getClickMap(e); } function getClickMap(event) { event.preventDefault(); var mouse = {}; mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; if(event.touches) { mouse.x = (event.changedTouches[0].pageX / window.innerWidth) * 2 - 1; mouse.y = -(event.changedTouches[0].pageY / window.innerHeight) * 2 + 1; } var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5); vector = vector.unproject(camera); var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); var intersects = raycaster.intersectObjects(group.children); //TODO 這個50 距離原點的距離, 正好就是 攝像頭 到 球心的距離應該是。 if (intersects.length > 0 && intersects[0].distance < 50 && intersects[0].object.clickFlag) { console.log(intersects[0].object.aa); } } function createSpriteTextNoPosition(index){ //先用畫布將文字畫出 let canvas = document.createElement("canvas"); canvas.width = 400; let ctx = canvas.getContext("2d"); ctx.fillStyle = "#ffff00"; ctx.font = "Bold 100px Arial"; ctx.lineWidth = 4; ctx.fillText("薩克拉" + index,4,104); let texture = new THREE.Texture(canvas); texture.needsUpdate = true;//不設置,會 不出現 //使用Sprite顯示文字 let material = new THREE.SpriteMaterial({map:texture}); let textObj = new THREE.Sprite(material); textObj.scale.set(4, 2, 1); return textObj; } document.addEventListener('mousedown', getClickMap, false); document.addEventListener('touchstart', onTouchStart, false); document.addEventListener('touchend', onTouchEnd, false); </script> </html>
一、geometry 帶有頂點的 幾何圖形canvas
二、獲取幾何圖形的頂點,數組
利用屬性 vertices數組
三、group 組的概念,用於 多個模型分組。
經常使用於 整個組 內容 一塊兒 旋轉之類。瀏覽器
四、group.children 可獲取到 組內全部的 模型。scene.children同理
五、光投影 app
六、orbitControls 與移動端 touchmove事件衝突,不能共存
七、利用 touchStart 和 touchEnd 判斷是否爲點擊事件
利用 touch事件對象 的 changedTouches[0];start和 end皆有; 若是 start裏的 座標 等於 end 裏的 座標,則爲點擊。dom
八、模型上移
不作其餘改變,使用定位,將畫布絕對定位 top=-100px;點擊事件裏 pageY + 100google
九、bug:手機瀏覽器 畫布過大,超過屏幕,與google調試不一致;
強行指定canvas給渲染器,並 important 寬高 爲100%。spa
十、球形頂點 多點旋轉:點與數據量實施方案
頂點數須大於數據量:遍歷頂點,數據量不夠則再來一遍。鋪滿3d
十一、MeshPhongMaterial 鏡面材質,須要燈光
十二、MeshBasicMaterial 基礎材質,普通上色,不需燈光調試
1三、動效切換,清除
a、中止動效 (必須cancelAnimationFrame)
b、清除場景內模型 (須要深清除,內存裏的)
移除場景內的子元素,需注意 不要移除 攝像機和燈光(子元素包含了)。
c、有綁定事件的 移除事件
1四、canvas文本顯示不清晰,解決:使用textObj.scale.set(4,2,1); 對sprite 進行縮放,參數是 縮放量,三維的。改變前兩參數就行