整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          分享一個用canvas寫的生日祝福動畫,漫天煙火給你,你的感動給我

          果圖截圖:

          開始

          中途

          最終

          由于截圖無法顯示出動畫的震撼,請看視頻:

          <script src="https://lf6-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>

          流量不夠多的朋友可以看這里,gif動圖走起來:

          開始

          開始2

          中間

          最終

          太好看了有沒有!!

          朋友或者喜歡的他/她生日的時候,將這個美麗的場景發送給ta,一定會收獲滿滿的感動哦。

          html代碼:

          <div style="text-align:center;clear:both;">
          <script src="/gg_bd_ad_720x90.js" type="text/javascript"></script>
          <script src="/follow.js" type="text/javascript"></script>
          </div>
          <canvas></canvas>
          <canvas></canvas>
          <canvas></canvas>
          <script src="js/index.js"></script>
          

          js代碼中涉及到許多作圖函數,如果能認真研究透該項目的代碼,相信你一定會有所收獲的。

          需要完整代碼的朋友,可以私信或留言獲取哦~

          天小編我逛程序員論壇,看到了一位程序員小伙子分享的他的表白過程,中專生,暗戀某女孩好久了,但是程序員你懂得 很多人都說程序員不懂浪漫,乘女孩生日,寫了個網頁表白,不知后續如何。

          推薦下我自己的前端學習群:680847368,不管你是小白還是大牛,小編我都挺歡迎,不定期分享干貨,今天的這個JavaScript做的愛心表白網頁已上傳,包括我自己整理的一份2017最新的前端資料和零基礎入門教程,歡迎初學和進階中的小伙伴。

          話不多說先上效果圖

          源碼分享

          代碼太長,這里只能展示部分,需要完整版的可以進小編的前端學習群:680847368,不管你是小白還是大牛,小編我都挺歡迎,不定期分享干貨,今天的這個JavaScript做的愛心表白網頁已上傳,包括我自己整理的一份2017最新的前端資料和零基礎入門教程,歡迎初學和進階中的小伙伴。

          為整天和 UI 打交道的前端工程師,是否想在他(她)生日的時候用代碼送上一份驚喜呢?


          不妨用 Three.js 做個 3D 的蛋糕送給 ta,既浪漫又能展現你技術的魅力。


          這篇文章我們就來學習下如何用 Three.js 畫一個蛋糕。


          圖片


          代碼地址:https://github.com/QuarkGluonPlasma/threejs-exercize


          Three.js 相關基礎

          Three.js 是通過場景 Scene 來管理所有的物體的,加到 Scene 的物體還可以分個組:


          const scene = new THREE.Scene();


          scene.add(xxx);


          const group = new THREE.Group();

          group.add(yyy);

          group.add(zzz);


          scene.add(group);

          想要把 Scene 中的所有物體渲染出來,需要指定一個相機 camera,然后用 renderer 來渲染,如果有動畫效果,要用 requestAnimationFrame 來一幀幀不斷渲染。


          const renderer = new THREE.WebGLRenderer();


          function render() {

          renderer.render(scene, camera);

          requestAnimationFrame(render);

          }

          render();

          相機 camera 分為從一個點去看的透視相機 PerspectiveCamera,還有從一個面去投影的正交相機 OrthographicCamera。


          圖片

          圖片

          透視相機的特點是近大遠小,而正交的則不是,就是一個平行投影,大小不變。


          三維世界還需要指定一個光源,不然是全黑的,光源種類很多,常用的有這些:


          點光源:從一個點發射光線,就像燈泡一樣。

          平行光:平行的光線

          環境光:均勻照射每個地方

          聚光燈:舞臺聚光燈的光源

          三維場景中的物體有很多種,比如永遠面向相機的平面是 Sprite(我們做“漫天花雨”效果用的那個),還有由三角形構成的物體叫做 Mesh。


          圖片

          Mesh 比較常用,它是由一個個三角形構成的幾何體,還可以在每個面上貼圖。所以,參數有兩個,幾何體 Geometry 和材質 Material。


          比如圓柱體就是一個 Mesh,創建它的時候要指定圓柱幾何體 CylinderBufferGeometry 和每個面的材質 Material。


          const 圓柱幾何體 = new THREE.CylinderBufferGeometry(上圓半徑, 下圓半徑, 高度, 側面分段數量);


          const 側面材質 = new THREE.MeshBasicMaterial({map: 紋理圖片});

          const 上面材質 = new THREE.MeshBasicMaterial({color: 'red'});

          const 下面材質 = new THREE.MeshBasicMaterial({color: 'red'});


          const 圓柱 = new THREE.Mesh(圓柱幾何體, [側面材質, 上面材質, 下面材質]);

          MeshBasicMaterial 是基礎的材質,可以通過 color 來指定顏色,也可以通過 map 來指定紋理圖片 texture。


          各種 Mesh 中比較特殊是文字,它用的是 TextGeometry,文字需要從一個 xxx.typeface.json 中加載。


          而這種 json 文件可以用字體文件 ttf 來轉換得到。用ttf 轉 typeface.json 的這個網站來轉:


          圖片

          之后就可以顯示文字了:


          const fontLoader = new THREE.FontLoader();


          fontLoader.load('./font/xxx.typeface.json', function (font) {

          var textGeometry = new THREE.TextGeometry('文字', 參數);

          const textMaterial = [

          new THREE.MeshBasicMaterial({color: '字體顏色'}),

          new THREE.MeshBasicMaterial({color: '側面顏色'}),

          ];


          const text = new THREE.Mesh(textGeometry, textMaterial);

          });

          這些就是我們會用到的 Three.js 基礎,簡單做個小結:


          Three.js 是通過 Scene 來管理各種物體的,物體還可以分下組。


          物體中常見的有 Mesh 和 Sprite 等,Sprite 是永遠面向相機的一個平面,Mesh 是由三角形構成的三維物體。Mesh 要指定幾何體Geometry 和材質 Material,常用的材質可以是顏色或者紋理貼圖。其中文字 TextGeometry 比較特殊,需要一個 typeface.json 的文件,這個可以由 ttf 轉換得到。


          場景中的物體準備好之后,還需要設置下光源 Light 和相機 Camera,相機主要有從點去看的透視相機和從一個平面去投影的正交相機,之后就可以通過渲染器 Renderer 渲染出來了,結合 requestAnimationFrame 來一幀幀的渲染。


          基礎學完之后,正式開始畫蛋糕了。


          畫 3D 蛋糕

          蛋糕其實就是由 4 個圓柱體加上文字構成的,每個圓柱體都設置了不同的位置,圓柱體的側面和上下面都貼上不同的貼圖,就是一個蛋糕。


          我們先準備蛋糕的貼圖:


          圖片

          圖片

          圖片

          圖片

          使用紋理加載器 TextureLoader 去加載他們:


          const cakeTexture1 = new THREE.TextureLoader().load('img/cake1.png');

          const cakeTexture2 = new THREE.TextureLoader().load('img/cake2.png');

          const cakeTexture3 = new THREE.TextureLoader().load(`img/cake3.png`);

          const cakeTexture4 = new THREE.TextureLoader().load('img/cake4.png');

          然后構成紋理貼圖的材質:


          const cakeMaterail1 = new THREE.MeshBasicMaterial({map: cakeTexture1});

          const cakeMaterail2 = new THREE.MeshBasicMaterial({map: cakeTexture2});

          const cakeMaterail3 = new THREE.MeshBasicMaterial({map: cakeTexture3});

          const cakeMaterail4 = new THREE.MeshBasicMaterial({map: cakeTexture4});

          除了紋理貼圖的材質外,再準備個顏色構成的材質:


          const pinkMaterial = new THREE.MeshBasicMaterial({color: 'pink'});

          然后創建 4 個圓柱體的物體(Mesh),使用不同的貼圖材質和顏色材質:


          const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);

          const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);

          圓柱體的幾何體 CylinderBufferGeometry 的參數分別是 上面圓的半徑,下面圓的半徑,高度,側面的分割次數。


          上面圓半徑保持一致,這樣才是圓柱體。側面分割次數設置為 40,這樣比較圓滑。


          之后還設置下位移,然后就可以加到蛋糕分組里了。


          我們用同樣的方式創建四個圓柱體,設置不同的大小和位置,貼不同的圖:


          const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);

          const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);

          cakePart1.translateY(45)


          const cakeGeometry2 = new THREE.CylinderBufferGeometry(120, 120, 70, 40);

          const cakePart2 = new THREE.Mesh(cakeGeometry2,[cakeMaterail3, pinkMaterial, pinkMaterial]);

          cakePart2.translateY(-25)


          const cakeGeometry3 = new THREE.CylinderBufferGeometry(140, 140, 60, 40);

          const cakePart3 = new THREE.Mesh(cakeGeometry3, [cakeMaterail2, pinkMaterial, pinkMaterial]);

          cakePart3.translateY(-90)


          const cakeGeometry4 = new THREE.CylinderBufferGeometry(160, 160, 10, 40);

          const cakePart4 = new THREE.Mesh(cakeGeometry4, [cakeMaterail4, cakeMaterail4, cakeMaterail4]);

          cakePart4.translateY(-120)


          cake.add(cakePart1)

          cake.add(cakePart2)

          cake.add(cakePart3)

          cake.add(cakePart4)

          如果對坐標位置拿不準,可以在 Scene 中加上一個坐標的輔助工具 AxisHelper。參數是坐標軸長度。


          const axisHelper = new THREE.AxisHelper(2500);

          scene.add(axisHelper);

          圖片

          然后是文字的部分,這個要先通過字體文件 ttf 轉成 typeface.json 的文件,然后用 fontLoader 來加載,之后創建相應的 Mesh:


          fontLoader.load('./font/guang.typeface.json', function (font) {

          var textGeometry = new THREE.TextGeometry('光光', {

          font: font,

          size: 30,

          height: 5,

          bevelEnabled: true,

          bevelSize: 10,

          });

          const textMaterial = ['white', 'red'].map(color => new THREE.MeshBasicMaterial({color}));


          const text = new THREE.Mesh(textGeometry, textMaterial);

          text.translateY(90)

          text.translateX(-45)


          cake.add(text);

          });

          TextGeometry 需要設置的參數有字體大小 size,厚度 height,以及邊緣是否是曲面 bevelEnabled,和曲面的大小 bevelSize。


          我們這里的效果是需要開啟曲面的。


          圖片

          4 個圓柱體畫完了,文字也畫完了,那蛋糕就算是畫完了,之后設置下光源、相機,就可以用 Renderer 渲染了。


          光源使用環境光,因為要均勻的照射:


          const light = new THREE.AmbientLight(0xCCCCCC);

          scene.add(light);

          相機使用正交相機,因為不需要近大遠小的透視效果:


          const width = window.innerWidth;

          const height = window.innerHeight;

          //窗口寬高比

          const k = width / height;

          //三維場景顯示范圍的高度

          const s = 200;


          const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);


          camera.position.set(0, 100, 500)

          camera.lookAt(scene.position);

          正交相機的參數分別是左右上下遠近的三維視野范圍,我們指定高度為 200,然后根據窗口的寬高比算出寬度。遠近可以設置一個比較大的范圍。


          之后就可以用 Renderer 來渲染了。把渲染出的 canvas 的 dom 掛載到 body 上。


          const renderer = new THREE.WebGLRenderer();


          renderer.setSize(width, height);

          //設置背景顏色

          renderer.setClearColor(0xFFFFFF, 1);

          document.body.appendChild(renderer.domElement);


          function render() {

          renderer.render(scene, camera);


          cake.rotation.y += 0.005;


          requestAnimationFrame(render)

          }

          render()


          在每幀 render 之前,還做了個圍繞 y 軸的自動旋轉。


          還要支持手動的旋轉,這個直接使用 Three.js 的軌道控制器 OrbitControls 就行。


          const controls = new THREE.OrbitControls(camera);

          參數是相機,因為這種視野的改變就是通過改變相機位置和朝向來實現的。


          創建了 Scene 中的蛋糕的每一部分,設置好了光源、相機,用渲染器做了一幀幀的渲染,并且添加了用鼠標來改變視角的軌道控制器之后,就完成了 3D 蛋糕的制作。


          我們來看下效果:


          圖片


          代碼地址:https://github.com/QuarkGluonPlasma/threejs-exercize


          全部代碼:


          <!DOCTYPE html>

          <html lang="en">

          <head>

          <meta charset="UTF-8">

          <title>生日蛋糕</title>

          <style>

          body {

          margin: 0;

          overflow: hidden;

          }

          </style>

          <script src="./js/three.js"></script>

          <script src="./js/OrbitControls.js"></script>

          </head>

          <body>

          <script>

          const width = window.innerWidth;

          const height = window.innerHeight;

          //窗口寬高比

          const k = width / height;

          //三維場景顯示范圍的寬度

          const s = 200;


          const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);


          const fontLoader = new THREE.FontLoader();


          const scene = new THREE.Scene();


          const cake = new THREE.Group();


          const renderer = new THREE.WebGLRenderer();


          function create() {

          renderer.setSize(width, height);

          //設置背景顏色

          renderer.setClearColor(0xFFFFFF, 1);

          document.body.appendChild(renderer.domElement);


          camera.position.set(0, 100, 500)

          camera.lookAt(scene.position);


          const light = new THREE.AmbientLight(0xCCCCCC);

          scene.add(light);


          const axisHelper = new THREE.AxisHelper(2500);

          scene.add(axisHelper);


          const cakeTexture1 = new THREE.TextureLoader().load('img/cake1.png');

          const cakeTexture2 = new THREE.TextureLoader().load('img/cake2.png');

          const cakeTexture3 = new THREE.TextureLoader().load(`img/cake3.png`);

          const cakeTexture4 = new THREE.TextureLoader().load('img/cake4.png');


          const cakeMaterail1 = new THREE.MeshBasicMaterial({map: cakeTexture1});

          const cakeMaterail2 = new THREE.MeshBasicMaterial({map: cakeTexture2});

          const cakeMaterail3 = new THREE.MeshBasicMaterial({map: cakeTexture3});

          const cakeMaterail4 = new THREE.MeshBasicMaterial({map: cakeTexture4});


          const pinkMaterial = new THREE.MeshBasicMaterial({color: 'pink'});


          const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);

          const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);

          cakePart1.translateY(45)


          const cakeGeometry2 = new THREE.CylinderBufferGeometry(120, 120, 70, 40);

          const cakePart2 = new THREE.Mesh(cakeGeometry2,[cakeMaterail3, pinkMaterial, pinkMaterial]);

          cakePart2.translateY(-25)


          const cakeGeometry3 = new THREE.CylinderBufferGeometry(140, 140, 60, 40);

          const cakePart3 = new THREE.Mesh(cakeGeometry3, [cakeMaterail2, pinkMaterial, pinkMaterial]);

          cakePart3.translateY(-90)


          const cakeGeometry4 = new THREE.CylinderBufferGeometry(160, 160, 10, 40);

          const cakePart4 = new THREE.Mesh(cakeGeometry4, [cakeMaterail4, cakeMaterail4, cakeMaterail4]);

          cakePart4.translateY(-120)


          cake.add(cakePart1)

          cake.add(cakePart2)

          cake.add(cakePart3)

          cake.add(cakePart4)


          fontLoader.load('./font/guang.typeface.json', function (font) {

          var textGeometry = new THREE.TextGeometry('光光', {

          font: font,

          size: 30,

          height: 5,

          bevelEnabled: true,

          bevelSize: 10,

          });

          const textMaterial = ['white', 'red'].map(color => new THREE.MeshBasicMaterial({color}));


          const text = new THREE.Mesh(textGeometry, textMaterial);

          text.translateY(90)

          text.translateX(-45)

          cake.add(text);

          });


          scene.add(cake);

          }


          function render() {

          renderer.render(scene, camera);


          cake.rotation.y += 0.005;


          requestAnimationFrame(render)

          }


          create()

          render()


          const controls = new THREE.OrbitControls(camera);

          </script>

          </body>

          </html>

          總結

          本文我們用 Three.js 來實現了 3D 蛋糕的效果。


          首先我們學習了下 Three.js 的基礎:通過 Scene 來管理物體,物體可以分組,物體包括 Mesh、Sprite 等,Mesh 是三角形構成的 3D 物體,要分別指定幾何體 Geometry 和材質 Material。材質可以是紋理(Texture)貼圖、也可以是顏色。其中文字的 Mesh 需要做 ttf 到 typeface.json 的轉換,加載這個 json 才能顯示文字。


          物體創建完了之后,還要設置相機、燈光等,然后通過渲染器來一幀幀的渲染。


          調試的時候還可以添加 AxisHelper 坐標系輔助工具來輔助開發。


          然后我們實現了 3D 蛋糕:


          通過 4 個圓柱體 + 文字來畫的,圓柱體用了不同的紋理貼圖材質,設置了不同的位置,然后組成蛋糕的 group。


          設置了環境光,使用了正交相機,還啟用了軌道控制器 OrbitControls,來實現鼠標拖拽改變相機位置,進而改變視野角度的效果。


          下個他(她)的生日,不妨試試用 Three.js 畫個蛋糕送給他(她),或許會有不一樣的收獲哦。


          主站蜘蛛池模板: 国产亚洲福利精品一区二区| 日韩人妻精品一区二区三区视频| 波多野结衣电影区一区二区三区 | 国产成人精品无人区一区| 亚洲午夜电影一区二区三区 | 国产精品乱码一区二区三区| 亚洲AV无码一区二区大桥未久| 久久人妻内射无码一区三区| 国产精品视频一区二区三区不卡| 国产精品一区二区香蕉| 亚洲日韩一区二区三区| 国产一区二区三区乱码网站| 美女啪啪一区二区三区| 国产av天堂一区二区三区| 久久久人妻精品无码一区| 视频一区在线免费观看| 国产亚洲综合精品一区二区三区 | 91成人爽a毛片一区二区| 成人精品视频一区二区三区不卡| 亚洲视频一区二区| 无码AⅤ精品一区二区三区| 日韩精品一区在线| 国产成人久久一区二区不卡三区| 亚洲欧美一区二区三区日产| 亚洲国产欧美国产综合一区| 无码喷水一区二区浪潮AV| 日韩福利视频一区| 一本岛一区在线观看不卡| 中文国产成人精品久久一区| 国产福利精品一区二区| 日韩免费一区二区三区在线| 人妻视频一区二区三区免费| 国产成人无码aa精品一区| 一区二区中文字幕在线观看| 中文字幕一区二区免费| 亚洲国产一区二区a毛片| 三级韩国一区久久二区综合| 国产中的精品一区的| 亚洲一区视频在线播放| 国产精品熟女一区二区| 亚洲一区二区三区国产精品无码|