zoukankan      html  css  js  c++  java
  • 用Canvas为网页加入动态背景

    近期刚刚接到为微信公众帐号“玩转三里屯”制作首页的任务。

    考虑到页面仅仅在手机中浏览。并且手机对canvas的支持又很好,所以打算使用canvas做点不一样的动画。

    首先来看下效果图。


    要实现这种动画普通的CSS3是鞭长莫及了,仅仅能使用Canvas。好在使用canvas也很easy。

    Step1.

    新建一个画布(<canvas>)元素,并放在在全部button和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;


    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();
    


    执行代码:


    Step3.

    让矩形动起来。

    要做动画我们须要持续的清空画布并又一次绘制新的矩形。就像电影每秒播放24张图片。我们新建一个loop函数,用来绘制每一帧的图像,并使用requestAnimFrame来告诉浏览器每一帧都要使用loop来绘制。

    //假设浏览器支持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中。并在绘制矩形的代码之前清空画布中全部的图形。
    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坐标上。

    //初始角度为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);
    }


    执行代码:



    将右上顶点的变化值改为角度的余弦,使其左右不同步。var deltaHeightRight   = Math.cos(angle) * 50;

    //初始角度为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);
    }


    执行代码:


    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();


    执行代码:


    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

    加入好button与logo的HTML代码就大功告成了。



    查看全部代码请去Github


    如有问题或者建议请微博@UED天机

    我会及时回复

    也能够收藏天机的官网,http://ued.sexy/  常常更新最新的教程。



    ======

    相关阅读

    1.css3动态背景


  • 相关阅读:
    JSP基本使用
    Web介绍
    通用的数据库数据操作类
    Java集合与泛型
    我是如何刷 LeetCode
    这或许是东半球讲十大排序算法最好的一篇文章(c++版程序)
    【游戏后端】游戏服务器端开发的一些建议(转载)
    【高并发】Redis为什么是单线程,高并发快的3大原因详解
    【高可用】Redis哨兵、复制、集群的设计原理与区别
    深入理解各种排序的一些思路及分享
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6700469.html
Copyright © 2011-2022 走看看