Three.js + GreenSock 模擬簡單隨機動畫

什麼是three.js

Three.js封裝了底層的圖形接口,使得程序員可以在無需掌握繁冗的圖形學知識的狀況下,也能用簡單的代碼實現三維場景的渲染,相對於webGL,Three.js封裝了底層的圖形接口,在不瞭解圖形學的狀況下,也能用簡單的代碼實現三維場景的渲染javascript

預覽地址html

開始使用

CDN引入java

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.2/TweenMax.min.js"></script>
複製代碼

建立環境

一個基本的Three.js程序至少要包括渲染器(Renderer)、場景(Scene)、照相機(Camera),以及你在場景中建立的物體。git

  • 場景(Scene) 放置全部物體的空間容器,三維空間。直接new一個Scene類建立調用3d場景的實例 new scene = new THREE.Scene()
  • 照相機(Camera) three.js 採用的是右手座標系

共有四種:立方相機(Cube Camera)、正交(Orthographic Camera)、透視(Perspective Camera)、立體(Stereo Camera) 經常使用:正投影相機(THREE.OrthographicCamera) 和透視投影相機(THREE.PerspectiveCamera)。

其中 透視投影相機 (PerspectiveCamera)更真實的模仿人眼中的現實世界,本例也將用到程序員

THREE.PerspectiveCamera(fov, aspect, near, far)github

其構造函數接受四個不一樣的參數,接受參數類型皆爲Numberweb

fov — 攝像機視錐體垂直視野角度
aspect — 攝像機視錐體長寬比
near — 攝像機視錐體近端面
far — 攝像機視錐體遠端面
複製代碼

透視圖

var camera = new THREE.PerspectiveCamera(
                75,//視野縱橫比
                window.innerWidth / window.innerHeight,//基於瀏覽器寬高
                0.1,//近端距離 near
                1000,//遠端距離 far
            )
//設置相機在z軸上的位置
    camera.position.z = 5;
複製代碼
  • 渲染器(Renderer) 渲染器分別有 webGL| CSS2d | CSS3d | SVG ,其中webGL最靈活強大
var renderer = new THREE.WebGLRenderer({
    antialias: true, //是否反鋸齒。默認爲false
    /*
    canvas: canvas, //供渲染器繪製其輸出的canvas,若是沒有傳這個參數,會建立一個新canvas
    precision:'highp', // 着色器精度. highp|mediump|lowp|highp(默認)
    alpha: flase, // canvas是否包含alpha (透明度)。默認爲 false
    stencil: flase // 繪圖緩存是否有模板緩存。默認爲true
     */
    });
 renderer.setClearColor("#e5e5e5");
 renderer.setSize(window.innerWidth,window.innerHeight);

複製代碼

建立好後把 renderer 生成的 dom 結構(其實就是一個 canvas 標籤)append 到 html 裏 document.body.appendChild(renderer.domElement);ajax

建立物體

環境佈置好了,還差環境裏的物體 Three.js 中提供了不少類型的物體,它們都繼承自 Object3D 類,包括線段(Line)、骨骼(Bone)、粒子系統(ParticleSystem)。比較常見的是Mesh(網格),網格是由頂點、邊、面等組成的物體,網格越多,物體表面越平滑,更接近模仿真實。canvas

任何物體都有形狀,材質api

  • 形狀geometry 形狀有超多種嗷...圓環,球體,柱體,柱體,文字形狀...各類各樣任君挑選,但都是簡單基本模型,複雜模型仍是須要導入的,支持導入*.obj 的外部模型
  • 材質material 材質(Material)是獨立於物體頂點信息以外的與渲染效果相關的屬性。經過設置材質能夠改變物體的顏色、紋理貼圖、光照模式 這裏採用的是Lambert材質(MeshLambertMaterial)是符合Lambert光照模型的材質。Lambert光照模型的主要特色是隻考慮漫反射而不考慮鏡面反射的效果,對於大部分物體的漫反射效果都是適用的。
//3d物體包括物理形狀和材料
      var geometry = new THREE.BoxGeometry(1, 1, 1);//半徑、寬度、圓滑度
      var material = new THREE.MeshLambertMaterial({color: 0xf7f7f7});
      //建立MESH模型
      var mesh = new THREE.Mesh(geometry, material);
複製代碼

場景和物體都有了, 這個時候打開瀏覽器看到的是一個黑不溜秋的醜醜正方形,好像和3d搭不上邊嗷...

其實這裏還缺了關鍵的燈光,不一樣的光影效果可讓畫面更豐富。

Three.js 提供了包括環境光 (AmbientLight)、點光源 (PointLight)、聚光燈 (SpotLight)、方向光 (DirectionalLight)、半球光 (HemisphereLight) 等多種光源。 只要在場景中添加須要的光源,再加上必定的物體旋轉就行了。這裏用到PointLight,

var light = new THREE.PointLight(0xffffff, 1, 500);//顏色,強度,距離
    light.position.set(0,0,10); //設置光源位置
    scene.add(light);
    mesh.rotation.set(45,45,0);

複製代碼

而後頁面上的模型效果是這樣

製做動畫

動效庫有不少,這裏用使用gasp(green sock)複雜動畫序列使用的時間軸插件TimelineMax,詳見文檔tweenmax中文手冊

添加射線

瀏覽器是一個2d視口,而在裏面顯示three.js的內容是3d場景,因此,如今有一個問題就是如何將2d視口的x和y座標轉換成three.js場景中的3d座標。three.js已經有了解決相關問題的方案,那就是THREE.Raycaster射線,用於鼠標去獲取在3D世界被鼠標選中的一些物體

//聲明raycaster和mouse變量
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector3();
複製代碼

光線投射Raycaster使用的是官方文檔裏的案例光線投射

TweenMax API

  • .to( target, duration, vars, position)
參數 類型 說明
target Object 須要動畫的對象
duration Number 動畫持續的秒數(或幀)
vars Object 動畫參數(CSS屬性、延遲、重複次數等)
position 插入動畫的位置
  • ease:過渡效果的速度曲線(緩動效果),在動畫的參數中設置各類緩動來控制動畫的變化率, Expo :特殊緩動
function onMouseMove(event){
      event.preventDefault();
      // 將鼠標位置歸一化爲設備座標。x 和 y 方向的取值範圍是 (-1 to +1)            
      mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
      mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
      //傳入光線,經過攝像機和鼠標位置更新射線
      raycaster.setFromCamera( mouse, camera );
      // 計算物體和射線的焦點
      var intersects = raycaster.intersectObjects( scene.children ,true);
          for(let i = 0; i<intersects.length ; i++){
              //選中與射線相交的物體
                  this.tl = new TimelineMax().delay(.3);
                  //添加動效
                  this.tl.to(intersects[i].object.scale, 1, {x:2, ease: Expo.easeOut})//網點,持續時間
                  this.tl.to(intersects[i].object.scale, .5, {x:.5, ease: Expo.easeOut})
                  this.tl.to(intersects[i].object.position, .5, {x:2, ease: Expo.easeOut})
                  this.tl.to(intersects[i].object.rotation, .5, {y:Math.PI*.5, ease: Expo.easeOut}, "=-1.5")//提早-1.5s發生
                }
                }
            render();
            //添加監聽事件
            window.addEventListener('mousemove', onMouseMove)
複製代碼

這個時候能夠看到物體已經動起來了

效果實現

能夠看到最後的效果是隨機建立一個個模型並分散在頁面上的,因此這裏循環建立多個模型,經過random改變其在 x , y , z上的position來達到「迎面而來」 動畫效果

meshCount = 0;
    for( var i = 0 ;i < 20 ;i++) {
        var mesh = new THREE.Mesh(geometry, material);
        mesh.position.x =( Math.random() - 0.5) *10;
        mesh.position.y =( Math.random() - 0.5) *10;
        mesh.position.z =( Math.random() - 0.5) *10;
        scene.add(mesh);
        meshCount++;
  }
複製代碼

這個時候能夠看出光是不夠的,須要再加一個光源,光源的位置座標、強度、距離、衰退量能夠根據本身的感受調節

var light = new THREE.PointLight(0xffffff, 1, 1000);//顏色,強度,距離
light.position.set(0,0,0);
scene.add(light);
複製代碼

多個隨機模型 效果如圖

響應式

經過瀏覽器大小自動改變渲染的模型大小

//監聽窗口改變同時更新
  window.addEventListener('resize',()=>{
      renderer.setSize(window.innerWidth,window.innerHeight);
      camera.aspect = window.innerWidth / window.innerHeight;
      //注意,最後必定要調用updateProjectionMatrix()方法更新
      camera.updateProjectionMatrix();
  })
  //最後渲染
  var render = function(){
      //不會由於瀏覽器寬高影響圖形
      requestAnimationFrame(render);
      renderer.render(scene,camera);
  }
複製代碼

最後加個標題就完成了

最後

參考:

TimelineMax中文手冊

three.js文檔

three.js入門指南

學習three.js,除了還有官方的文檔和案例 還有就是羨轍小姐姐的three.js人門指南。羨轍姐姐是我在GitHub上第一個關注的人,超級喜歡她~

第一次在掘金髮文章,但願你們多多指點 ~

相關文章
相關標籤/搜索