搜尋
首頁web前端H5教程HTML5邊玩邊學(七)-動畫初步之飛舞的精靈

一、為什麼選擇HTML5

HTML5 邊玩邊學算上這篇已經是第七篇了,在這篇開始之前,我想先說明為什麼叫「HTML5」 邊玩邊學,因為有人對HTML5 提出質疑,畢竟他是新生事物。我承認我用HTML5 來吸引眼球了,如果看過邊玩邊學系列的每一篇,你會發現前六篇文章內容的和HTML5 關係不是太大,真正的內容其實是2D 圖形圖像編程的學習筆記。

如果我們想學習2D 編程,其實可供選擇的程式環境數不勝數:MFC、Delphi都有圖形影像處理功能(即GDI),Java、.Net 更不用說了,如果你支援開源, GTK、QT、wxPython 也是不錯的選擇,Flash 更是拿手好戲,甚至幾個流行的只能手機平台應該也有2D 模組。

如果你選擇了上面任何一款編程環境學習2D 編程,你會發現他們的內容基本上是一樣的:線型、填充、顏色、漸變、圖像、組合、裁剪區、變形等等,甚至連函數名很多都是一摸一樣,畢竟他們的理論基礎都是圖形學。

 搞清楚我們真正想學習什麼以後,其實程式環境只是個工具而已,我們依照個人喜好,選擇最方便的一款來使用。其實我比較青睞 Python 程式環境,只是如果我用了Python,估計跟我交流的人就不會太多了,大家機器裡安裝 Python 運行時的估計不會太多。

那為什麼選擇 HTML5 而不是其他呢?首先,Javascript 語法簡潔靈活,對應的函式庫小巧但是夠用, HTML5 Canvas 標籤的 2D 表現能力也達到了要求,Chrome 瀏覽器的運作速度讓人滿意。除此之外,我們不用安裝笨重的整合開發環境,不需要安裝執行時,我們只需要一個加強功能的記事本、一個瀏覽器就可以去實踐我們的想法,並且直接將效果呈現在網路上。我們只是發表文章與其他人分享自己的想法而已,至於平台、框架、語言特性,這些無關的東西當然牽扯的越少越好,這就是我選擇 HTML5 的原因。

所以,請大家不要誤解了標題的含義:這個系列並不是HTML5 的學習筆記,而只是用HTML5 來展現一些知識內容而已,你更多關注的應該是知識和內容本身,你可以在任何其他一款程式設計環境下再現他們。

二、動畫初步

動畫就是一系列連續的畫面按順序呈現出來而已,只是,在電影電視中,這些畫面實現已經被準備好了,而在電腦程式中,我們見到每一瞬間的畫面都是即時繪製的,大體流程可以表述如下:

a、輕微改變圖形的資料(座標、形狀、顏色等等)

b、清空畫布

c、繪製圖形

d、回到步驟a

當然,這裡只是給了一個最簡單的流程框架,要實現複雜的動畫可能還要考慮更多的問題,例如局部清除、碰撞偵測之類的。

另外,繪製過程中有兩個速度需要控制:

第一個是繪製速度,即每秒鐘繪製多少次(幀),或者也可以這樣說,每一幀暫停多少時間。如果你的動畫每一幀都是一個樣子,只是位置不同,這個速度影響不大。

第二個圖形移動的速度。

所以,千萬不要把這兩個速度搞混了,繪製的越快,只能代表動畫更流暢,但不代表你的圖像移動的更快。

 

使用HTML5 繪製動畫基本上就是上面這個流程,只是你還需要注意兩點:

1、為了方便繪製的圖形,我們常常會改變上下文物件的的狀態,所以在繪製圖形前後,千萬別忘了保存和恢復狀態,如果你不太了解狀態是什麼,請看前面的一篇文章《 HTML5邊玩邊學(6):汽車人,變形......》

2、我們需要將整個繪製動作放到計時器裡面,否則整個瀏覽器將失去響應。 Javascript 有兩個定時器方法,分別是:

setInterval(code,millisec) 和 setTimeout(code,millisec)

這兩個方法我就介紹了,可以去 Google 相關的資料。

下面我們給出一個上下移動方塊的小動畫,當遇到頂部或底部時,會改變方向。程式碼如下:

基本动画



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><canvas id="canvas1" width="250" height="300" style="background-color:black">

    你的浏览器不支持 Canvas 标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

帧数:<input  id="txt1" type="text" value="25"/><br/>

每次移动距离:<input type="text" id="txt2" value="10"/><br/>

<input type="button" value="开始" onclick="move_box()"/>

<input type="button" value="暂停" onclick="stop()"/>





<script type="text/javascript">

    //定时器

    var interval=null;

    

    //停止动画

    function stop(){

        clearInterval(interval);

    }



    //===================================================================

    //基本动画

    //====================================================================

    function move_box(){

        //停止动画

        stop();

        //移动速度

        var delta=parseInt(document.getElementById(&#39;txt1&#39;).value);

        //每秒绘制多少次

        var fps=parseInt(document.getElementById(&#39;txt2&#39;).value);



        //画布对象

        var canvas=document.getElementById("canvas1")

        //获取上下文对象

        var ctx = canvas.getContext("2d");

        //设置颜色

        ctx.fillStyle="red";

        

        //方块的初始位置

        var x=100;var y=50;

        //方块的长度和宽度

        var w=30;var h=30;

        

        //开始动画

        interval = setInterval(function(){

            //改变 y 坐标

            y=y+delta;

            //上边缘检测

            if(y<0){

                y=0;

                delta=-delta;

            }

            //下边缘检测

            if((y+h)>canvas.getAttribute("height")){

                y=canvas.getAttribute("height")-h;

                delta=-delta;

            } 

            //清空画布

            ctx.clearRect(0,0,canvas.getAttribute("width"),canvas.getAttribute("height"));

            //保存状态

            ctx.save();

            //移动坐标

            ctx.translate(x,y);

            //重新绘制

            ctx.fillRect(0,0,w,h);

            //恢复状态

            ctx.restore();

        },1000/fps);

    }    

</script>

 

三、重新組織程式碼

上面的程式碼能正常運作了,但是存在很多問題,主要有以下幾點:

1、計算方塊位置的程式碼和繪製方塊的程式碼混雜一起,即邏輯和視圖混雜,基本上不能擴展了

2、代码没办法复用,比如我们需要绘制多个不同的方块对象:起始位置、大小、颜色、速度各不相同,每一种情况都需要重写一遍。

下面我们重新组织一下代码,把方块的共同属性抽象出来,组成一个 Box 类,由这个 Box 类负责计算每一帧方块的位置,这样就可以解决上面两个问题了。代码如下:

重新组织代码



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><canvas id="canvas2" width="250" height="300" style="background-color:black">

    你的浏览器不支持 Canvas 标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

<input type="button" value="开始" onclick="move_box2()"/>

<input type="button" value="暂停" onclick="stop()"/>



<script type="text/javascript">

    //定时器

    var interval=null;

    

    //停止动画

    function stop(){

        clearInterval(interval);

    }



    //===================================================================

    //重新组织代码

    //====================================================================

    //方块的构造函数

    function Box(color,x,y,w,h,delta){

        this.color=color;

        this.x=x;

        this.y=y;

        this.w=w;

        this.h=h;

        this.delta=delta;

        //三十帧

        this.fps=30;

        //每一帧的延迟时间

        this.delay=1000/this.fps;

        //上一次重绘的时间

        this.last_update=0;

    }

    

    //方块更新

    Box.prototype.update=function(canvas){

        //获取当前时间

        var now=(new Date()).getTime();

        //如果达到了延迟时间,则更新数据

        if((now-this.last_update)>this.delay){

        

            //改变 y 坐标

            this.y=this.y+this.delta;

            //上边缘检测

            if(this.y<0){

                this.y=0;

                this.delta=-this.delta;

            }

            //下边缘检测

            if((this.y+this.h)>canvas.getAttribute("height")){

                this.y=canvas.getAttribute("height")-this.h;

                this.delta=-this.delta;

            } 

            //记下最新一次绘制时间

            this.last_update=now;

        }

        

    }

    

    

    function move_box2(){

        //停止动画

        stop();

        //画布对象

        var canvas=document.getElementById("canvas2")

        //获取上下文对象

        var ctx = canvas.getContext("2d");

        //清空画布

        ctx.clearRect(0,0,canvas.getAttribute("width"),canvas.getAttribute("height"));

        

        //创建多个方块对象

        var boxes=[];

        boxes[0]= new Box("red",3,2,10,35,2,10);//速度10

        boxes[1]= new Box("blue",60,28,44,15,5);//速度20

        boxes[2]= new Box("green",130,200,23,18,10);//速度30

        boxes[3]= new Box("pink",200,150,35,10,20);//速度40

        

        //开始动画绘制

        interval = setInterval(function(){

            for(var i=0;i<boxes.length;i++){

                //取出一个方块

                var box=boxes[i];

                //清空这个方块

                ctx.clearRect(box.x,box.y,box.w,box.h);

                //更新数据

                box.update(canvas);

                //保存状态

                ctx.save();

                //设置颜色

                ctx.fillStyle=box.color;

                //移动坐标

                ctx.translate(box.x,box.y);

                //重新绘制

                ctx.fillRect(0,0,box.w,box.h);

                //恢复状态

                ctx.restore();

            }

        },1);//尽可能快的循环

    }    

</script>

 

四、精灵登场

据说在很久远的年代,有多远我也不知道,可能是任天堂红白机是哪个年代吧,由于游戏机处理器的计算速度有限,所以专门设置了一个硬件用来处理角色图像的相关数据,这些数据可能包括:

1、计算当前的角色应该绘制哪一帧。上面我们的方块虽然在移动,但是始终都是一个样子;可是在游戏中,一个跑动的精灵,跑动动作是由很多幅连续的图像组成,我们需要知道现在应该绘制其中的哪一幅图像;

2、表现精灵动作的很多幅连续的图像通常是集中放置在一个大图中,我们需要计算当前绘制的那一幅,在大图中处于什么位置,并把它截取出来

上面说到这个硬件,曾经被叫做 Sprite 精灵。现如今,我们的处理器已经十分强大,不再需要 Sprite 这样的辅助硬件,但是这样的功能仍然需要,只不过用软件来实现罢了,所以,我们依然用 Sprite 来称呼游戏中的一个角色。

这里有一幅图像,他描绘了一个小精灵的飞行动作

 

下面我们将实现一个 Sprite 类,让他在浏览器里面飞起来。

精灵登场



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><canvas id="canvas3" width="250" height="300" style="background-color:black">

    你的浏览器不支持 <canvas>标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

帧数:<input  id="txt4" type="text" value="10"/><br/>

速度:<input type="text" id="txt5" value="5"/><br/>

比例:<input type="text" id="txt6" value="2"/><br/>

<input type="button" value="开始" onclick="animate()"/>

<input type="button" value="暂停" onclick="stop()"/>



<script type="text/javascript">

    //定时器

    var interval=null;

    

    //停止动画

    function stop(){

        clearInterval(interval);

    }

    

    //===================================================================

    //精灵登场

    //====================================================================

    //每一帧在大图中的位置

    var frames=[];

    frames[0]=[0,4,19,19];

    frames[1]=[22,1,24,19];

    frames[2]=[49,0,18,17];

    frames[3]=[1,32,18,17];

    frames[4]=[22,33,24,19];

    frames[5]=[49,36,19,19];

    

    //精灵类

    function Sprite(dx,dy,delta,fps){

        this.dx=dx;

        this.dy=dy;

        this.fps=fps;

        this.delay=1000/fps;

        this.last_update=0;

        //移动速度

        this.delta=-delta;

        //帧编号

        this.index=0;

        //方向

        this.dir_left=true;

    }

    

    Sprite.prototype.update=function(canvas){

        //获取当前时间

        var now=(new Date()).getTime();

        if((now-this.last_update)>this.delay){

            if(this.dir_left){

                //方向朝左,只绘制0 1 2帧

                if(this.index>2)

                    this.index=0;

            }

            else{

                //方向朝右,只绘制 3 4 5 帧

                if(this.index>5)

                    this.index=3;

            }

            //取出当前帧的坐标

            this.frame=frames[this.index];

            

            //当前帧在大图中的位置

            this.sx=this.frame[0];

            this.sy=this.frame[1];

            this.sw=this.frame[2];

            this.sh=this.frame[3];

            

            //当前帧大小

            this.dw=this.frame[2];

            this.dh=this.frame[3];

            

            //改变 x 坐标

            this.dx=this.dx+this.delta;

            //左边缘检测

            if(this.dx<0){

                this.dx=0;

                //转向

                this.delta=-this.delta;

                this.dir_left=false;

                this.index=3;

            }

            //右边缘检测

            if((this.dx+this.dw)>canvas.getAttribute("width")){

                this.dx=canvas.getAttribute("width")-this.dw;

                //转向

                this.delta=-this.delta;

                this.dir_left=true;

                this.index=0;

            }         

            this.dy=this.dy;//y 不移动

            



            this.index++;

            this.last_update=now;

        }

    }

    

    function animate(){

        //停止动画

        stop();

        //移动速度

        var delta=parseInt(document.getElementById(&#39;txt4&#39;).value);

        //每秒绘制多少次

        var fps=parseInt(document.getElementById(&#39;txt5&#39;).value);

        //比例

        var scale=parseInt(document.getElementById(&#39;txt6&#39;).value);

        

        //画布对象

        var canvas=document.getElementById("canvas3")

        //获取上下文对象

        var ctx = canvas.getContext("2d");

        //清空画布

        ctx.clearRect(0,0,canvas.getAttribute("width"),canvas.getAttribute("height"));

        

        var img=new Image();

        img.src="http://images.cnblogs.com/cnblogs_com/myqiao/html5/sprite.gif";



        var sprite=new Sprite(120,150,delta,fps);

        interval = setInterval(function(){

            //清空画布

            ctx.clearRect(0,0,canvas.getAttribute("width"),canvas.getAttribute("height"));

            //更新数据

            sprite.update(canvas);

            //保存状态

            ctx.save();

            //移动坐标

            ctx.translate(sprite.dx,sprite.dy);

            ctx.scale(scale,scale);

            ctx.drawImage(img,sprite.sx,sprite.sy,sprite.sw,sprite.sh,0,0,sprite.dw,sprite.dh);

            //恢复状态

            ctx.restore();

        },1);

        

    }

    

</script>


以上是HTML5邊玩邊學(七)-動畫初步之飛舞的精靈的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
H5是HTML5的速記嗎?探索細節H5是HTML5的速記嗎?探索細節Apr 14, 2025 am 12:05 AM

H5不僅僅是HTML5的簡稱,它代表了一個更廣泛的現代網頁開發技術生態:1.H5包括HTML5、CSS3、JavaScript及相關API和技術;2.它提供更豐富、互動、流暢的用戶體驗,能在多設備上無縫運行;3.使用H5技術棧可以創建響應式網頁和復雜交互功能。

H5和HTML5:網絡開發中常用的術語H5和HTML5:網絡開發中常用的術語Apr 13, 2025 am 12:01 AM

H5與HTML5指的是同一個東西,即HTML5。 HTML5是HTML的第五個版本,帶來了語義化標籤、多媒體支持、畫布與圖形、離線存儲與本地存儲等新功能,提升了網頁的表現力和交互性。

H5指的是什麼?探索上下文H5指的是什麼?探索上下文Apr 12, 2025 am 12:03 AM

H5referstoHTML5,apivotaltechnologyinwebdevelopment.1)HTML5introducesnewelementsandAPIsforrich,dynamicwebapplications.2)Itsupportsmultimediawithoutplugins,enhancinguserexperienceacrossdevices.3)SemanticelementsimprovecontentstructureandSEO.4)H5'srespo

H5:工具,框架和最佳實踐H5:工具,框架和最佳實踐Apr 11, 2025 am 12:11 AM

H5開發需要掌握的工具和框架包括Vue.js、React和Webpack。 1.Vue.js適用於構建用戶界面,支持組件化開發。 2.React通過虛擬DOM優化頁面渲染,適合複雜應用。 3.Webpack用於模塊打包,優化資源加載。

HTML5的遺產:當前了解H5HTML5的遺產:當前了解H5Apr 10, 2025 am 09:28 AM

HTML5hassignificantlytransformedwebdevelopmentbyintroducingsemanticelements,enhancingmultimediasupport,andimprovingperformance.1)ItmadewebsitesmoreaccessibleandSEO-friendlywithsemanticelementslike,,and.2)HTML5introducednativeandtags,eliminatingthenee

H5代碼:可訪問性和語義HTMLH5代碼:可訪問性和語義HTMLApr 09, 2025 am 12:05 AM

H5通過語義化元素和ARIA屬性提升網頁的可訪問性和SEO效果。 1.使用、、等元素組織內容結構,提高SEO。 2.ARIA屬性如aria-label增強可訪問性,輔助技術用戶可順利使用網頁。

H5與HTML5相同嗎?H5與HTML5相同嗎?Apr 08, 2025 am 12:16 AM

"h5"和"HTML5"在大多數情況下是相同的,但它們在某些特定場景下可能有不同的含義。 1."HTML5"是W3C定義的標準,包含新標籤和API。 2."h5"通常是HTML5的簡稱,但在移動開發中可能指基於HTML5的框架。理解這些區別有助於在項目中準確使用這些術語。

H5的功能是什麼?H5的功能是什麼?Apr 07, 2025 am 12:10 AM

H5,即HTML5,是HTML的第五個版本,它為開發者提供了更強大的工具集,使得創建複雜的網頁應用變得更加簡單。 H5的核心功能包括:1)元素允許在網頁上繪製圖形和動畫;2)語義化標籤如、等,使網頁結構清晰,利於SEO優化;3)新API如GeolocationAPI,支持基於位置的服務;4)跨瀏覽器兼容性需要通過兼容性測試和Polyfill庫來確保。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)