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

考虑到页面仅仅在手机中浏览。并且手机对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);
}

执行代码:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTY3OTY3NDk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

将右上顶点的变化值改为角度的余弦,使其左右不同步。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();
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);
}

执行代码:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTY3OTY3NDk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

Step6

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

查看全部代码请去Github

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

我会及时回复

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

======

相关阅读

1.css3动态背景

用Canvas为网页加入动态背景的更多相关文章

  1. Hexo Next配置百度分享、加入动态背景、接入网页在线联系功能、页脚增加统计功能、添加gitment、添加热度、阅读量排行

    Hexo Next配置百度分享.加入动态背景.接入网页在线联系功能.页脚增加统计功能.添加gitment.添加热度.阅读量排行: https://wangc1993.github.io/categor ...

  2. 基于HTML5 Canvas的网页画板实现教程

    HTML5的功能非常强大,尤其是Canvas的应用更加广泛,Canvas画布上面不仅可以绘制任意的图形,而且可以实现多种多样的动画,甚至是一些交互式的应用,比如网页网版.这次我们要来看的就是一款基于H ...

  3. html5 canvas首屏自适应背景动画循环效果代码

    模板描述:html5 canvas首屏自适应背景动画循环效果代码 由于动态图太大,怕以后服务器受不了,所以现在都改为静态图了,大家点击演示地址一样的,希望大家喜欢,你们的支持就是小海的动力!! 欢迎大 ...

  4. 利用canvas将网页元素生成图片并保存在本地

    利用canvas将网页元素生成图片并保存在本地 首先引入三个文件: 1.<script type="text/javascript" src="js/html2ca ...

  5. 如何把canvas元素作为网站背景总结详解

    如何把canvas元素作为网站背景总结详解 一.总结 一句话总结:最简单的做法是绝对定位并且z-index属性设置为负数. 1.如何把canvas元素作为网站背景的两种方法? a.设置层级(本例代码就 ...

  6. 用HTML5 Canvas为网页添加动态波浪背景

    查看所有代码请去Github 本文出自 “UED” 博客:http://5344794.blog.51cto.com/5334794/1430877 <!DOCTYPE html> < ...

  7. H5神器之canvas应用——网页修改保存图片

    因为最近项目上的要求,需要在页面中可以对一张图片进行涂改和添加文字,然后再保存到(服务器)本地,因为也是第一次接触这方面的,然后爬网页啊爬网页,之后发现了一款adobe开发的一款插件,适合 Anroi ...

  8. HTML5之Canvas时钟(网页效果--每日一更)

    今天,带来的是使用HTML5中Canvas标签实现的动态时钟效果. 话不多说,先看效果:亲,请点击这里 众所周知,Canvas标签是HTML5中的灵魂,HTML5 Canvas是屏幕上的一个由Java ...

  9. 使用canvas截图网页为图片并解决跨域空白以及模糊问题

    前几天给了个需求对浏览器网页进行截图,把网页统计数据图形表等截图保存至用户本地. 首先对于网页截图,我用的是canvas实现,获取你需要截图的模块的div,从而使用canvas对你需要的模块进行截图. ...

随机推荐

  1. Android只播放gif动画

    使用easygifanimator软件把gif动画打散为图片. 第一步:先上图片素材,以下素材放到res/drawable目录下: 转:http://blog.csdn.net/aminfo/arti ...

  2. UVA 10026 Shoemaker&#39;s Problem

    Shoemaker's Problem Shoemaker has N jobs (orders from customers) which he must make. Shoemaker can w ...

  3. guess-number-higher-or-lower-ii

    // https://discuss.leetcode.com/topic/51353/simple-dp-solution-with-explanation // https://en.wikipe ...

  4. Informatica 常用组件Lookup之一 概述

    转换类型:被动.已连接/未连接 在映射中使用查找转换以从平面文件或关系表.视图或同义词查找数据.您可以从 PowerCenter Client 和 PowerCenter Server 均连接至的任何 ...

  5. 第六章 JVM垃圾收集器(2)

    上一章记录了几种常见的垃圾收集器,见<第五章 JVM垃圾收集器(1)> 1.G1 说明: 从上图来看,G1与CMS相比,仅在最后的"筛选回收"部分不同(CMS是并发清除 ...

  6. hdu1226 超级密码 (BFS,里面用了大数取余原理)

    Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进 ...

  7. [leetcode]Binary Tree Zigzag Level Order Traversal @ Python

    原题地址:http://oj.leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ 题意: Given a binary tr ...

  8. 独特的deadlock(仅update语句也能造成死锁)

    最近遇到了一个看上去很奇怪,分析起来很有意思的死锁问题.这个死锁看上去难以理解.而分析过程中,又使用了很多分析SQL Server死锁的典型方法.记录下来整个分析过程还是很有意义的. 问题重现步骤: ...

  9. nginx配置解决vue单页面打包文件大,首次加载慢的问题

    cnpm run build 文件过大,其中主要是vender.js有1.5M,代码部署到服务器,首次访问加载页面时比较慢,耗时6.5s左右,所以需要优化下. 1.Nginx开启gzip 找到ngin ...

  10. 关于C++ 中POD类型的解析

    转自: http://liuqifly.spaces.live.com/blog/cns!216ae3a149106df9!221.entry (C++-98:1.8;5)给出的定义:将对象的各字节拷 ...