canvas三角函数模拟水波效果的示例代码


Posted in HTML / CSS onJuly 03, 2018

最近项目中,ui设计了个水波效果的背景动画,然而并没有gif或svg动画,开始试着用css实现了一下,动画效果并不是很好,网上查了下基本都是用贝赛尔曲线实现,想起以看的各种前波形图,于是想着用三角函数图像初略模拟一下

一、绘制sin函数图像

sin函数表达式如下,

y=Asin(wx+φ)+h

其中 A表示振幅,ω表示角频率(ω=2π/T,T为函数的周期),φ表示初相,h表示图像向y轴正方向平移的长度 ;(这里需要注意一下:h在数学学的本来是表示向上平移的,但在canvas中采用的是屏幕坐标系,即左上角为原点,h则表示向下平移);

绘制代码如下:

(1)添加canvas标签

<canvas id="canvas"></canvas>

(2)添加css样式,设置canvas宽高

html,
body {
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
}
canvas {
  width: 100%;
  height: 100%;
}

(3)绘制函数图像

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext('2d'),
    width = canvas.width = canvas.offsetWidth,
    height = canvas.height = canvas.offsetHeight;
//声明参数
var A=50,
    W=1 / 50,
    Q=0,
    H= height / 2;
//绘图方法
(function draw(){
  ctx.clearRect(0, 0, width, height);//清空画布
  ctx.beginPath();                   //开始路径
  ctx.strokeStyle="#000";            //设置线条颜色
  ctx.lineWidth = 1;                 //设置线条宽度
  ctx.moveTo(0, height /2);          //起始点位置

  for (let x = 0; x <=  width; x++) {// 绘制x对应y的 
    var y = A*Math.sin(W*x+Q) +H
    ctx.lineTo(x, y)
  }

  ctx.stroke();                      //绘制路径
  ctx.closePath();                   //闭合路径
})()

这样我们可以得到以下图像:

canvas三角函数模拟水波效果的示例代码

二、为函数图像添加动画

上面得到的是是一个静态的函数图像,而我们一般见到的的波形图或水波都是随时间连续变化的,这里就要用到上一步中的参数相位φ,(js即代码中的Q) ,我们将φ随时间不断增加或减小,即可得到不同时间的不同图像;使用window.requestAnimationFrame实现帧动画;

修改以上代码为:

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext('2d'),
    width = canvas.width = canvas.offsetWidth,
    height = canvas.height = canvas.offsetHeight;
//声明参数
var A=50,
    W=1 / 50,
    Q=0,
    H= height / 2;
//绘图方法
(function draw(){
  ctx.clearRect(0, 0, width, height);//清空画布
  ctx.beginPath();                   //开始路径
  ctx.strokeStyle="#000";            //设置线条颜色
  ctx.lineWidth = 1;                 //设置线条宽度
  ctx.moveTo(0, height /2);          //起始点位置

  for (let x = 0; x <=  width; x++) {// 绘制x对应y的 
    var y = A*Math.sin(W*x+Q) +H
    ctx.lineTo(x, y)
  }

  ctx.stroke();                      //绘制路径
  ctx.closePath();                   //闭合路径
})()

效果如下(渣渣截图软件):

canvas三角函数模拟水波效果的示例代码

三、绘制完整填充路径

以上路径虽有闭合,但却不满足我们需要填充的部分,直接填充效果如下:

canvas三角函数模拟水波效果的示例代码

完整填充路径应如图所示:

canvas三角函数模拟水波效果的示例代码

闭合路径后创建一个渐变颜色,作为填充颜色,代码如下:

var lingrad = ctx.createLinearGradient(0,0,width,0);
 lingrad.addColorStop(0, 'rgba(0,186,128,0.8)');
 lingrad.addColorStop(1, 'rgba(111,224,195,1)');   

(function draw(){
  window.requestAnimationFrame(draw);
  ctx.clearRect(0, 0, width, height);
  ctx.beginPath();
  ctx.strokeStyle="#000";
  ctx.fillStyle = lingrad;
  ctx.lineWidth = 1;
  ctx.moveTo(0, height /2);  
  Q+=speed;
  for (let x = 0; x <=  width; x++) {
    var y = A*Math.sin(W*x+Q) +H;
    ctx.lineTo(x, y);
  }
  ctx.lineTo(width, height);
  ctx.lineTo(0, height);
  ctx.fill();
  ctx.closePath();
})()

效果如下:

canvas三角函数模拟水波效果的示例代码

四、完善水波动画

1、首先可以对上面波形叠加一个频率更高的波形,使波形无规矩

var s = 0.1*Math.sin(x/150)+1;
var y = A*Math.sin(W*x+Q) +H;
y=y*s;

2、再添加一个相位变化不同的波形,其渐变填充与上一个渐变方向相反使其形成相互重叠的阴影效果;并设置路径重叠效果globalCompositeOperation; 

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

var A=30,
   W=1 /200,
   Q=0,
   H= height / 2;

var A2=30,
   W2=1/300,
   Q2=0,
   H2= height / 2;

var speed=-0.01;
var speed2=-0.02;

var lingrad = ctx.createLinearGradient(0,0,width,0);
lingrad.addColorStop(0, 'rgba(0,186,128,0.8)');
lingrad.addColorStop(1, 'rgba(111,224,195,1)');  

var lingrad2 = ctx.createLinearGradient(0,0,width,0);
lingrad2.addColorStop(0,'rgba(111,224,195,1)');
lingrad2.addColorStop(1, 'rgba(0,186,128,0.8)'); 

(function draw(){
  window.requestAnimationFrame(draw);
  ctx.clearRect(0, 0, width, height);
  ctx.beginPath();
  ctx.fillStyle = lingrad;
  ctx.moveTo(0, height /2);
  //绘制第一个波形
  Q+=speed;
  for (let x = 0; x <=  width; x++) {
    var s = 0.1*Math.sin(x/150)+1;
    var y = A*Math.sin(W*x+Q) +H;
    y=y*s;
    ctx.lineTo(x, y);
  }
  ctx.lineTo(width, height);
  ctx.lineTo(0, height);
  ctx.fill();
  ctx.closePath()
  //设置重叠效果
  ctx.globalCompositeOperation = "destination-over"
  //绘制第二个波形
  ctx.beginPath();
  ctx.fillStyle = lingrad2;
  Q2+=speed2;
  for (let x = 0; x < width; x++) {
    var y = A2*Math.sin(x*W2+Q2) +H2;
    ctx.lineTo(x, y);
  }
  ctx.lineTo(width,height);
  ctx.lineTo(0,height);
  ctx.fill()
  ctx.closePath();

})()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
CSS3 Flexbox中flex-shrink属性的用法示例介绍
Dec 30 HTML / CSS
CSS3制作炫酷的自定义发光文字
Mar 28 HTML / CSS
Html5移动端弹幕动画实现示例代码
Aug 27 HTML / CSS
HTML5 新事件 小结
Jul 16 HTML / CSS
html5 乒乓球(碰撞检测)实例二
Jul 25 HTML / CSS
实例教程 HTML5 Canvas 超炫酷烟花绽放动画实现代码
Nov 05 HTML / CSS
浅析HTML5的WebSocket与服务器推送事件
Feb 19 HTML / CSS
AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas的示例代码
Aug 19 HTML / CSS
AmazeUI 平滑滚动效果的示例代码
Aug 20 HTML / CSS
简单实现一个手持弹幕功能+文字抖动特效
Mar 31 HTML / CSS
html+css 实现简易导航栏功能
Apr 07 HTML / CSS
css3中transform属性实现的4种功能
Aug 07 HTML / CSS
你可能不熟练的十个前端HTML5经典面试题
Jul 03 #HTML / CSS
canvas实现飞机打怪兽射击小游戏的示例代码
Jul 09 #HTML / CSS
canvas绘制表情包的示例代码
Jul 09 #HTML / CSS
html5 利用canvas手写签名并保存的实现方法
Jul 12 #HTML / CSS
详解Html5微信支付爬坑之路
Jul 24 #HTML / CSS
基于Html5实现的react拖拽排序组件示例
Aug 13 #HTML / CSS
基于HTML5的WebSocket的实例代码
Aug 15 #HTML / CSS
You might like
一个简单的域名注册情况查询程序
2006/10/09 PHP
PHP similar_text 字符串的相似性比较函数
2010/05/26 PHP
jquery 操作单选框,复选框,下拉列表实现代码
2009/10/27 Javascript
web的各种前端打印方法之jquery打印插件jqprint实现网页打印
2013/01/09 Javascript
jQuery不间断滚动效果(模拟百度新闻支持文字/图片/垂直滚动)
2013/02/05 Javascript
javascript操作html控件实例(javascript添加html)
2013/12/02 Javascript
举例说明JavaScript中的实例对象与原型对象
2016/03/11 Javascript
高效利用Angular中内置服务$http、$location等
2016/03/22 Javascript
网络传输协议(http协议)
2016/11/18 Javascript
微信小程序 picker-view 组件详解及简单实例
2017/01/10 Javascript
jQuery模拟爆炸倒计时功能实例代码
2017/08/21 jQuery
深入理解JavaScript 中的匿名函数((function() {})();)与变量的作用域
2018/08/28 Javascript
详解keep-alive + vuex 让缓存的页面灵活起来
2019/04/19 Javascript
[50:11]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第三场
2018/04/09 DOTA
Python 文件和输入输出小结
2013/10/09 Python
python中遍历文件的3个方法
2014/09/02 Python
python字典DICT类型合并详解
2017/08/17 Python
对pandas replace函数的使用方法小结
2018/05/18 Python
基于Django ORM、一对一、一对多、多对多的全面讲解
2019/07/26 Python
PyQt5 如何让界面和逻辑分离的方法
2020/03/24 Python
CSS3轻松实现圆角效果
2017/11/09 HTML / CSS
【HTML5】Canvas绘制简单图片教程
2016/05/13 HTML / CSS
德国最大的拼图在线商店:Puzzle.de
2016/12/17 全球购物
DC Shoes俄罗斯官网:美国滑板鞋和服饰品牌
2020/08/19 全球购物
几道数据库的概念性面试题
2014/05/30 面试题
STP的判定过程
2012/10/01 面试题
会计专业毕业生自我鉴定
2013/10/29 职场文书
函授毕业生的自我鉴定
2013/11/26 职场文书
哈理工毕业生的求职信
2013/12/22 职场文书
告诉你怎样写创业计划书
2014/01/27 职场文书
大学生自我鉴定书
2014/03/24 职场文书
禁止酒驾标语
2014/06/25 职场文书
2017新年晚会开幕词
2016/03/03 职场文书
草系十大最强宝可梦,纸片人上榜,榜首大家最熟悉
2022/03/18 日漫
mysql使用FIND_IN_SET和group_concat两个方法查询上下级机构
2022/04/20 MySQL
基于redis+lua进行限流的方法
2022/07/23 Redis