用Canvas為網頁添加動態背景

來源:互聯網
上載者:User

標籤:html5   javascript   前端   動畫   canvas   

最近剛剛接到為公眾帳號“玩轉三裡屯”製作首頁的任務。考慮到頁面只在手機中瀏覽,而且手機對canvas的支援又非常好,所以打算使用canvas做點不一樣的動畫。

首先來看下。


要實現這樣的動畫普通的CSS3是鞭長莫及了,只能使用Canvas。好在使用canvas也非常簡單。

Step1.

建立一個畫布(<canvas>)元素,並放在在所有按鈕和logo的下方以免遮擋前面的元素。

<canvas id="canvas" style="position:absolute;top:0px;left:0px;z-index:1;"></canvas>  


將Canvas的寬高設定成其父元素的寬高,以充滿他的父元素。也可以直接使用window.innerHeight,window.innerWidth。使其充滿整個螢幕。

var canvas = document.getElementById('canvas');var ctx = canvas.getContext('2d');canvas.width = canvas.parentNode.offsetWidth;canvas.height = canvas.parentNode.offsetHeight;


var canvas = document.getElementById('canvas');var ctx = canvas.getContext('2d');canvas.width = canvas.parentNode.offsetWidth;canvas.height = canvas.parentNode.offsetHeight;
Step2.

在畫布中畫一個充滿半個螢幕的矩形。

我們只需要找到矩形的四個定點的座標,使用Canvas的繪製路徑並填充這個路徑。四個點分別是:

(0, 畫布高度t/2)
(畫布寬度, 畫布高度t/2)
(畫布寬度 畫布高度t/2)
(0, 畫布高度t/2)

注意:座標的(0,0)在畫布的左上方。

//填充顏色ctx.fillStyle = "rgba(0,222,255, 0.2)";//開始繪製路徑ctx.beginPath();//左上方ctx.moveTo(0, canvas.height/2);//右上方ctx.lineTo(canvas.width, canvas.height/2);//右下角ctx.lineTo(canvas.width, canvas.height);//左下角ctx.lineTo(0, canvas.height);//左上方ctx.lineTo(0, canvas.height/2);//閉合路徑ctx.closePath();//填充路徑ctx.fill();


//填充顏色ctx.fillStyle = "rgba(0,222,255, 0.2)";//開始繪製路徑ctx.beginPath();//左上方ctx.moveTo(0, canvas.height/2);//右上方ctx.lineTo(canvas.width, canvas.height/2);//右下角ctx.lineTo(canvas.width, canvas.height);//左下角ctx.lineTo(0, canvas.height);//左上方ctx.lineTo(0, canvas.height/2);//閉合路徑ctx.closePath();//填充路徑ctx.fill();

運行代碼:


Step3.

讓矩形動起來。要做動畫我們需要持續的清空畫布並重新繪製新的矩形,就像電影每秒播放24張圖片。我們建立一個loop函數,用來繪製每一幀的映像,並使用requestAnimFrame來告訴瀏覽器每一幀都要使用loop來繪製。

//如果瀏覽器支援requestAnimFrame則使用requestAnimFrame否則使用setTimeoutwindow.requestAnimFrame = (function(){return  window.requestAnimationFrame       ||window.webkitRequestAnimationFrame ||window.mozRequestAnimationFrame    ||function( callback ){          window.setTimeout(callback, 1000 / 60);        };})();function loop(){requestAnimFrame(loop);}loop();


把之前繪製矩形的代碼放到loop中,並在繪製矩形的代碼之前清空畫布中所有的圖形。
function loop(){//清空canvasctx.clearRect(0,0,canvas.width,canvas.height);//繪製矩形ctx.fillStyle = "rgba(0,222,255, 0.2)";ctx.beginPath();ctx.moveTo(0, canvas.height/2);ctx.lineTo(canvas.width, canvas.height/2);ctx.lineTo(canvas.width, canvas.height);ctx.lineTo(0, canvas.height);ctx.lineTo(0, canvas.height/2);ctx.closePath();ctx.fill();requestAnimFrame(loop);}


function loop(){//清空canvasctx.clearRect(0,0,canvas.width,canvas.height);//繪製矩形ctx.fillStyle = "rgba(0,222,255, 0.2)";ctx.beginPath();ctx.moveTo(0, canvas.height/2);ctx.lineTo(canvas.width, canvas.height/2);ctx.lineTo(canvas.width, canvas.height);ctx.lineTo(0, canvas.height);ctx.lineTo(0, canvas.height/2);ctx.closePath();ctx.fill();requestAnimFrame(loop);}
接下來我們更改每一幀中的矩形的高度來類比波浪的形態,波浪其實是在波峰與波穀之間做周期性運動。我們假設波峰與波穀間都是50px,那麼矩形的高度的變化值應該在-50px到50px之間。為了達到周期性的效果我們採用正弦函數sin(x),因為不管x值怎麼變化sin(x)的值始終在-1與1之間。我們建立一個變數 var step =0 使其在每一幀中自增,表示每一幀角度增加一度,並用Math.sin()取他的正弦值。JS中的sin使用的弧度值,我們需要把step轉換成弧度值,var angle = step*Math.PI/180; 取角度的正弦值乘以50得到了矩形高度的變化量。將變化量加在矩形的左上與右上兩個頂點的y座標上。

//初始角度為0var step = 0;function loop(){ctx.clearRect(0,0,canvas.width,canvas.height);ctx.fillStyle = "rgba(0,222,255, 0.2)";//角度增加一度step++;//角度轉換成弧度var angle = step*Math.PI/180;//矩形高度的變化量    var deltaHeight   = Math.sin(angle) * 50;    ctx.beginPath();    //在矩形的左上與右上兩個頂點加上高度變化量    ctx.moveTo(0, canvas.height/2+deltaHeight);    ctx.lineTo(canvas.width, canvas.height/2+deltaHeight);    ctx.lineTo(canvas.width, canvas.height);    ctx.lineTo(0, canvas.height);    ctx.lineTo(0, canvas.height/2+deltaHeight);    ctx.closePath();    ctx.fill();requestAnimFrame(loop);}


運行代碼:



將右上頂點的變化值改為角度的餘弦,使其左右不同步。var deltaHeightRight   = Math.cos(angle) * 50;

//初始角度為0var step = 0;function loop(){ctx.clearRect(0,0,canvas.width,canvas.height);ctx.fillStyle = "rgba(0,222,255, 0.2)";//角度增加一度step++;//角度轉換成弧度var angle = step*Math.PI/180;//矩形高度的變化量    var deltaHeight   = Math.sin(angle) * 50;    //矩形高度的變化量(右上頂點)    var deltaHeightRight   = Math.cos(angle) * 50;    ctx.beginPath();    ctx.moveTo(0, canvas.height/2+deltaHeight);    //右上頂點    ctx.lineTo(canvas.width, canvas.height/2+deltaHeightRight);    ctx.lineTo(canvas.width, canvas.height);    ctx.lineTo(0, canvas.height);    ctx.lineTo(0, canvas.height/2+deltaHeight);    ctx.closePath();    ctx.fill();requestAnimFrame(loop);}


運行代碼:


Step4

將矩形的頂上的邊變成曲線。

在上面的代碼中我們用lineTo來繪製矩形的邊,為了要繪製曲線我們需要

bezierCurveTo(cpX1, cpY1, cpX2, cpY2, x, y)

函數。繪製的起點是矩形的左上頂點,結束點為右上頂點。bezierCurveTo函數的參數中(cpX1,cpY1)與(cpX2,cpY2)分別是起點與結束點的控制點,(x,y)為結束點。我們將兩個控制點的x值設定在畫布的正中心,y值在起始點與終點的y值上面減去50;(canvas.width /2, canvas.height/2+deltaHeight-50),(canvas.width / 2,canvas.height/2+deltaHeightRight-50),可以根據效果調整。

ctx.bezierCurveTo(canvas.width /2, canvas.height/2+deltaHeight-50, canvas.width / 2, canvas.height/2+deltaHeightRight-50, canvas.width,canvas.height/2+deltaHeightRight);

ctx.beginPath();ctx.moveTo(0, canvas.height/2+deltaHeight);//ctx.lineTo(canvas.width, canvas.height/2+deltaHeightRight);//畫曲線ctx.bezierCurveTo(canvas.width /2, canvas.height/2+deltaHeight-50, canvas.width / 2, canvas.height/2+deltaHeightRight-50, canvas.width, canvas.height/2+deltaHeightRight);ctx.lineTo(canvas.width, canvas.height);ctx.lineTo(0, canvas.height);ctx.lineTo(0, canvas.height/2+deltaHeight);ctx.closePath();


ctx.beginPath();ctx.moveTo(0, canvas.height/2+deltaHeight);//ctx.lineTo(canvas.width, canvas.height/2+deltaHeightRight);//畫曲線ctx.bezierCurveTo(canvas.width /2, canvas.height/2+deltaHeight-50, canvas.width / 2, canvas.height/2+deltaHeightRight-50, canvas.width, canvas.height/2+deltaHeightRight);ctx.lineTo(canvas.width, canvas.height);ctx.lineTo(0, canvas.height);ctx.lineTo(0, canvas.height/2+deltaHeight);ctx.closePath();
運行代碼:


Step5

一個波浪畫好了。我們只需要同時畫3個不同顏色的波浪,並且使不同波浪的角度不同就可以得到中的效果了。


//定義三條不同波浪的顏色var lines = ["rgba(0,222,255, 0.2)",               "rgba(157,192,249, 0.2)",               "rgba(0,168,255, 0.2)"];function loop(){ctx.clearRect(0,0,canvas.width,canvas.height);step++;//畫3個不同顏色的矩形for(var j = lines.length - 1; j >= 0; j--) {ctx.fillStyle = lines[j];//每個矩形的角度都不同,每個之間相差45度    var angle = (step+j*45)*Math.PI/180;    var deltaHeight   = Math.sin(angle) * 50;    var deltaHeightRight   = Math.cos(angle) * 50;    ctx.beginPath();    ctx.moveTo(0, canvas.height/2+deltaHeight);    ctx.bezierCurveTo(canvas.width /2, canvas.height/2+deltaHeight-50, canvas.width / 2, canvas.height/2+deltaHeightRight-50, canvas.width, canvas.height/2+deltaHeightRight);    ctx.lineTo(canvas.width, canvas.height);    ctx.lineTo(0, canvas.height);    ctx.lineTo(0, canvas.height/2+deltaHeight);    ctx.closePath();    ctx.fill();}requestAnimFrame(loop);}


運行代碼:


Step6

添加好按鈕與logo的HTML代碼就大功告成了。



查看所有代碼請去Github


如有問題或者建議請微博@UED天機。我會及時回複


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.