您好,登錄后才能下訂單哦!
這篇文章主要介紹“什么是H5頁面及如何制作”,在日常操作中,相信很多人在什么是H5頁面及如何制作問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”什么是H5頁面及如何制作”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
TypeScript + Canvas 實現網頁落雪動畫效果技術方案
在前端范疇內,動畫效果一般通過CSS transition/animation或者由JS控制DOM元素去實現,但是這種普遍的方案并不適用于落雪效果,前者的局限性在于不能精確控制動畫元素的行為和隨機性,而后者會對頁面性能造成極大的影響(上千個DOM元素持續毫秒級更新)。
SVG存在理論上的可行性但和CSS animation同樣不能精確地控制動畫元素的行為。那剩下的最佳方案就只有Canvas了。
什么樣的雪花才更加逼真
采用第二種方案的雪花不僅看起來會更加逼真,而且因為形狀簡單,極大地降低了性能開銷。經試驗在我自己的電腦上,同等數量雪花的前提下,后者性能為前者的約30倍左右。
用最少的代碼在Canvas上畫出一片雪花
// 創建canvas元素
const canvas = document.createElement('canvas');
// 獲取畫布實例
const ctx = canvas.getContext('2d');
// 進入繪畫模式
ctx.beginPath();
// 畫曲線 (雪花的圓形實際為一個閉合的曲線)
ctx.arc(100, 100, 3, 0, Math.PI * 2, false);
// 閉合曲線
ctx.closePath();
// 填充曲線內部為白色
ctx.fillStyle = '#ffffff';
ctx.fill();
好了,這是整個效果最基礎也最核心的代碼,它看起來是下面這樣的。
也許這和你心里想想的落雪效果還差那么一點點,那么讓我們來加入一個循環,渲染20片雪花并讓它們隨機分布。
for (let i = 0; i < 20; i++) { // 隨機確定雪花的x,y坐標 const x = Math.random() * 300; const y = Math.random() * 200; // ... // 隨機透明度 ctx.globalAlpha = 0.5 + Math.random() * 0.5; // 隨機大小 const radius = 1 + Math.random() * 2; // 渲染 ctx.arc(x, y, radius, 0, Math.PI * 2, false); // ... } 讓雪花動起來
現在我們已經實現了最簡單的靜態雪花效果,下一步則是最關鍵核心的步驟:讓雪花動起來。
也許你已經想到了,想要讓雪花動起來,其實就是改變它的當前坐標值x,y,并在極短的時間內不停重復這個步驟,模擬這種移動效果。這種移動看似簡單,其實大有發揮空間,你可以賦予雪花一個速度值以及加速度值,每次刷新或者在特定時間間隔內改變這個加速度的大小和方向,使雪花的飄落產生大量隨機行為。你甚至可以借助各種開源JS物理引擎的幫助,幫你來算出每一幀x,y坐標需要改變多少。
但是經過我的實際實驗,添加大量的隨機性和提升雪花的逼真程度并不是完全成正比,而且會極大增加性能方面的開銷。因此我這里采用的最終方案為賦予雪花一個隨機初始速度值,并在lifetime內保持不變。
實現這個步驟的代碼如下:
// ...
// 生成y軸速度值
this.vy = 1 + Math.random() * 3;
// 生成x軸速度值 (雪花整體運動軌跡為從上至下,因此x軸橫向速度遠小于縱向速度)
this.vx = 0.5 - Math.random();
// 渲染當前這片雪花的下一幀
function draw() {
this.y += this.vy;
this.x += this.vx;
// ...
// 渲染
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
}
好了,以上就是最核心的運動算法(是不是非常簡單?)
接下來最重要的步驟,是我們需要決定什么時候應該渲染下一幀?
有些同學可能會說setInterval(),沒錯這個其實也算一種方案,但對于落雪效果這個量級的動畫來講,幾乎沒有實用性存在。有過H5游戲編程經驗的同學肯定會知道HTML5提供一個已經存在多年的動畫函數:
Window.requestAnimationFrame()
這個函數的作用很簡單,就是讓瀏覽器決定什么時候最適合渲染動畫的下一幀。相對于setInterval,它的優勢是:
根據電腦(瀏覽器)性能自動決定動畫幀數
低性能電腦上動畫會變慢(但不跳幀),而setInterval()會使動畫變卡(跳幀)
當前網頁窗口未被激活時,動畫自動暫停
好了,下面我們要做的很簡單,就是寫一個遞歸函數,讓渲染函數不停的調用自己。
// 渲染所有雪花的下一幀
function updateFrame() {
// 清空當前畫布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 調用所有雪花的渲染函數
flakes.forEach(f => {
f.draw();
});
// 通過瀏覽器動畫接口遞歸請求自己
requestAnimationFrame(() => updateFrame());
}
好了,至此我們已經是現在落雪效果中最核心的所有內容。剩下的更多是體力活以及優化微調。后續需要處理的問題主要有:
雪花的初始位置需要均勻分布在網頁頂部看不見的空間內,避免開始落雪時同時落入可視范圍,產生“雪崩”效果 ┓( ′?` )┏
雪花飄落到屏幕左側,右側或者底部看不見的空間后,要回收并重新放置到屏幕頂部,保證動畫的持續性。
落雪效果需要有開始和停止方法,停止后正在屏幕內的雪花能繼續飄落到場景外,而不是生硬的強制消失。
落雪效果停止并且所有雪花已經走出場景后,回收整個canvas以避免影響頁面性能。
落雪場景DOM容器尺寸改變時,算法坐標系需要適應新的尺寸,防止網頁內容未加載完即開始動畫從而導致雪花作用于錯誤的坐標系內。
封裝動畫,提高易用性,發布npm包。
到此,關于“什么是H5頁面及如何制作”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。