用HTML5 Canvas為網頁添加動態波浪背景


 

<!DOCTYPE html>
<html>
<head>
    <title>三里屯SOHO商盟</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
    <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
    <meta name="apple-mobile-web-app-title" content=""/>
    <meta name="apple-touch-fullscreen" content="YES" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="format-detection" content="telephone=no" />
    <meta name="HandheldFriendly" content="true" />
    <meta http-equiv="x-rim-auto-match" content="none" />
    <meta name="format-detection" content="telephone=no" />
    <!-- This is to force IE into the latest version mode, overriding 'compatibility' mode which breaks everything. -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="apple-touch-icon-precomposed" sizes="57x57" href="" />
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="" />
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="" />
    <link rel="apple-touch-icon-precomposed" sizes="144x144" href="" />
    <link href="assets/css/reset.css" rel="stylesheet" type="text/css">
    <link href="assets/css/base.css" rel="stylesheet" type="text/css">
    <!--feature-->
    <link href="assets/css/index.css" rel="stylesheet" type="text/css">
    <style type="text/css">

    </style>
</head>
<body>
    <section class="doc doc--bg2" style="width: 400px;height: 400px;margin: 0 auto;border-radius: 400px;position: relative;border:1px#efefef solid;overflow: hidden;">
        <canvas id="canvas" style="position:absolute;top:0px;left:0px;z-index:1;"></canvas>
    </section>
    <script type="text/javascript">
        var canvas = document.getElementById('canvas');  
        var ctx = canvas.getContext('2d');  
        canvas.width = canvas.parentNode.offsetWidth;  
        canvas.height = canvas.parentNode.offsetHeight;


        //如果瀏覽器支持requestAnimFrame則使用requestAnimFrame否則使用setTimeout  
        window.requestAnimFrame = (function(){  
        return  window.requestAnimationFrame       ||  
                window.webkitRequestAnimationFrame ||  
                window.mozRequestAnimationFrame    ||  
                function( callback ){  
                  window.setTimeout(callback, 1000 / 60);  
                };  
        })();  
        //初始角度為0  
        var step = 0;  
        //定義三條不同波浪的顏色  
        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);  
        }  
        loop(); 
    </script>
</body>
</html>
View Code

 

首先來看下效果圖。

wKioL1OqoWHi8F2-AAJE_rASUl0068.gif

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

Step1.

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

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

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

1
2
3
4
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)在畫布的左上角。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//填充顏色
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();

運行代碼:

wKioL1OqobyCOIJBAAA9vTNYksU822.jpg

 

Step3.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
//如果瀏覽器支持requestAnimFrame則使用requestAnimFrame否則使用setTimeout
window.requestAnimFrame = ( function (){
return   window.requestAnimationFrame       ||
         window.webkitRequestAnimationFrame ||
         window.mozRequestAnimationFrame    ||
         function ( callback ){
           window.setTimeout(callback, 1000 / 60);
         };
})();
function  loop(){
     requestAnimFrame(loop);
}
loop();


把之前繪制矩形的代碼放到loop中,並在繪制矩形的代碼之前清空畫布中所有的圖形。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function  loop(){
     //清空canvas
     ctx.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坐標上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//初始角度為0
var  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);
}

運行代碼:

wKiom1Oqoh_wspXWAABXAgzP24I168.gif

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//初始角度為0
var  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);
}

運行代碼:

wKioL1OqogmwojF9AACY3v8zvLk244.gif

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),可以根據效果調整。

1
2
3
4
5
6
7
8
9
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();

運行代碼:

wKiom1Oqolyw2WdxAACAKLANCXM315.gif

Step5

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//定義三條不同波浪的顏色
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);
}

運行代碼:

wKiom1OqonTAtueIAAJ1DyYAXBc916.gif

 

Step6

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

wKiom1OqooLTogroAAJE_rASUl0997.gif

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM