Canvas 制作动态进度加载水球详解及实例代码


Posted in Javascript onDecember 09, 2016

Canvas 动态进度加载水球

前言

之前看到一些球型的动态加载的效果,一直想自己动手做一个,正好这段时间重温了一个Canvas,所以就尝试了一下。

Canvas 制作动态进度加载水球详解及实例代码

实现思路

关于水波的实现,使用了sin()函数,通过每一帧不断的移动sin()函数曲线,实现水波动态效果。然后,通过绘制圆形路径,进行clip(),实现球型效果。

sin()函数相关

这里说一下sin()函数的相关基础,对于绘制水波的影响。

看一下图,回顾一下中学sin()函数的基础。

Canvas 制作动态进度加载水球详解及实例代码

从图中可以看出,当函数为sin(x)时,值域为[-1, 1],周期为

sin(x)乘以一个数,可以改变值域,也就是峰值,如下图:

Canvas 制作动态进度加载水球详解及实例代码

系数大于1时曲线更陡峭,小于1大于0时曲线更缓。

Canvas 制作动态进度加载水球详解及实例代码

sin(x ± 某个数)时,实现曲线的左右移动,减时右移,加时左移。

Canvas 制作动态进度加载水球详解及实例代码

sin(x * 某个数)时,曲线的周期会变化,某个数大于1时,周期变短;某个数小于1大于0时,周期变长。

在一点,sin()是一个周期函数,所以只要不断的给它值,它就会周期变化。

Canvas 制作动态进度加载水球详解及实例代码

好了,sin()的数学基础差不多了,接下来开始步入正题。

绘制 sin() 曲线

var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');

//画布属性
var mW = canvas.width = 700;
var mH = canvas.height = 300;
var lineWidth = 1;


//Sin 曲线属性
var sX = 0;
var sY = mH / 2;
var axisLength = mW; //轴长
var waveWidth = 0.011 ; //波浪宽度,数越小越宽 
var waveHeight = 70; //波浪高度,数越大越高

ctx.lineWidth = lineWidth;


//画sin 曲线函数
var drawSin = function(xOffset){
 ctx.save();

 var points=[]; //用于存放绘制Sin曲线的点

 ctx.beginPath();
 //在整个轴长上取点
 for(var x = sX; x < sX + axisLength; x += 20 / axisLength){
  //此处坐标(x,y)的取点,依靠公式 “振幅高*sin(x*振幅宽 + 振幅偏移量)”
  var y = -Math.sin((sX + x) * waveWidth);


  points.push([x, sY + y * waveHeight]);
  ctx.lineTo(x, sY + y * waveHeight);  
 }

 //封闭路径
 ctx.lineTo(axisLength, mH);
 ctx.lineTo(sX, mH);
 ctx.lineTo(points[0][0],points[0][1]);
 ctx.stroke()

 ctx.restore();
};
drawSin()
Canvas 制作动态进度加载水球详解及实例代码

此处通过waveWidthwaveHeight调节曲线的陡峭度和周期。

加入动态效果

var speed = 0.04; //波浪速度,数越大速度越快

var xOffset = 0; //波浪x偏移量

速度变量和x偏移变量

var y = -Math.sin((sX + x) * waveWidth + xOffset);

修改y点的函数。

var render = function(){
 ctx.clearRect(0, 0, mW, mH);

 drawSin(xOffset);
 xOffset += speed; //形成动态效果
 requestAnimationFrame(render);
}

render()

加入渲染。

Canvas 制作动态进度加载水球详解及实例代码

百分比控制

因为要加入百分比不同的涨幅效果,所以要对y的坐标时行百分比控制修改。

var dY = mH * (1 - nowRange / 100 );

球型显示

这里需要用到clip()进行球型裁切显示。

ctx.beginPath();
ctx.arc(r, r, cR, 0, 2 * Math.PI);
ctx.clip();

其他

可以通过修改如下变量来修改曲线的形状以及速度:

var waveWidth = 0.015 ; //波浪宽度,数越小越宽 
var waveHeight = 6; //波浪高度,数越大越高
var speed = 0.09; //波浪速度,数越大速度越快

完整代码

<!doctype html>
<html lang="en">
<head>
 <meta charset="UTF-8" />
 <title>Document</title>
 <style type="text/css">
  #c{
   margin: 0 auto;
   display: block;
  }
  #r{
   display: block;
   margin: 0 auto;
  }
  #r::before{
   color: black;
   content: attr(min);
   padding-right: 10px;
  }
  #r::after{
   color: black;
   content: attr(max);
   padding-left: 10px;
  }  
 </style>
</head>
<body>
 <canvas id="c"></canvas>
 <input type="range" id="r" min="0" max="100" step="1">

 <script type="text/javascript">
  var canvas = document.getElementById('c');
  var ctx = canvas.getContext('2d');
  var range = document.getElementById('r');

  //range控件信息
  var rangeValue = range.value;
  var nowRange = 0; //用于做一个临时的range

  //画布属性
  var mW = canvas.width = 250;
  var mH = canvas.height = 250;
  var lineWidth = 2;

  //圆属性
  var r = mH / 2; //圆心
  var cR = r - 16 * lineWidth; //圆半径

  //Sin 曲线属性
  var sX = 0;
  var sY = mH / 2;
  var axisLength = mW; //轴长
  var waveWidth = 0.015 ; //波浪宽度,数越小越宽 
  var waveHeight = 6; //波浪高度,数越大越高
  var speed = 0.09; //波浪速度,数越大速度越快
  var xOffset = 0; //波浪x偏移量

  ctx.lineWidth = lineWidth;

  //画圈函数
  var IsdrawCircled = false;
  var drawCircle = function(){

   ctx.beginPath();
   ctx.strokeStyle = '#1080d0';
   ctx.arc(r, r, cR+5, 0, 2 * Math.PI);
   ctx.stroke();
   ctx.beginPath();
   ctx.arc(r, r, cR, 0, 2 * Math.PI);
   ctx.clip();

  }

  //画sin 曲线函数
  var drawSin = function(xOffset){
   ctx.save();

   var points=[]; //用于存放绘制Sin曲线的点

   ctx.beginPath();
   //在整个轴长上取点
   for(var x = sX; x < sX + axisLength; x += 20 / axisLength){
    //此处坐标(x,y)的取点,依靠公式 “振幅高*sin(x*振幅宽 + 振幅偏移量)”
    var y = -Math.sin((sX + x) * waveWidth + xOffset);

    var dY = mH * (1 - nowRange / 100 );

    points.push([x, dY + y * waveHeight]);
    ctx.lineTo(x, dY + y * waveHeight);  
   }

   //封闭路径
   ctx.lineTo(axisLength, mH);
   ctx.lineTo(sX, mH);
   ctx.lineTo(points[0][0],points[0][1]);
   ctx.fillStyle = '#1c86d1';
   ctx.fill();

   ctx.restore();
  };

  //写百分比文本函数
  var drawText = function(){
   ctx.save();

   var size = 0.4*cR;
   ctx.font = size + 'px Microsoft Yahei';
   ctx.textAlign = 'center';
   ctx.fillStyle = "rgba(06, 85, 128, 0.8)";
   ctx.fillText(~~nowRange + '%', r, r + size / 2);

   ctx.restore();
  };

  var render = function(){
   ctx.clearRect(0, 0, mW, mH);

   rangeValue = range.value;

   if(IsdrawCircled == false){
    drawCircle(); 
   }

   if(nowRange <= rangeValue){
    var tmp = 1;
    nowRange += tmp;
   }

   if(nowRange > rangeValue){
    var tmp = 1;
    nowRange -= tmp;
   }

   drawSin(xOffset);
   drawText(); 

   xOffset += speed;
   requestAnimationFrame(render);
  }

  render();  
 </script>
</body>
</html>

效果

Canvas 制作动态进度加载水球详解及实例代码

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
超轻量级的基于jquery的三级展开列表
Apr 26 Javascript
jquery使用淘宝接口跨域查询手机号码归属地实例
Nov 28 Javascript
jQuery实现垂直半透明手风琴特效代码分享
Aug 21 Javascript
JS判断是否为JSON对象及是否存在某字段的方法(推荐)
Nov 29 Javascript
JavaScript实现多栏目切换效果
Dec 12 Javascript
js实现文本上下来回滚动
Feb 03 Javascript
完美解决linux下node.js全局模块找不到的情况
May 16 Javascript
angular2路由之routerLinkActive指令【推荐】
May 30 Javascript
详解vue组件开发脚手架
Jun 15 Javascript
对VUE中的对象添加属性
Sep 18 Javascript
基于JS实现数字动态变化显示效果附源码
Jul 18 Javascript
手写Spirit防抖函数underscore和节流函数lodash
Mar 22 Javascript
详解自动生成博客目录案例
Dec 09 #Javascript
微信小程序之仿微信漂流瓶实例
Dec 09 #Javascript
JS判断是否手机或pad访问实现方法
Dec 09 #Javascript
js实现一个可以兼容PC端和移动端的div拖动效果实例
Dec 09 #Javascript
利用JS实现页面删除并重新排序功能
Dec 09 #Javascript
Bootstrap table使用方法详细介绍
Dec 09 #Javascript
jQuery Validate设置onkeyup验证的实例代码
Dec 09 #Javascript
You might like
解析php中获取系统信息的方法
2013/06/25 PHP
php判断是否为json格式的方法
2014/03/04 PHP
JavaScript创建命名空间的5种写法
2014/06/24 PHP
深入浅出讲解:php的socket通信原理
2016/12/03 PHP
thinkphp关于简单的权限判定方法
2017/04/03 PHP
Javascript 类与静态类的实现
2010/04/01 Javascript
各浏览器中querySelector和querySelectorAll的实现差异分析
2012/05/23 Javascript
解决javascript:window.close()在chrome,Firefox下失效的问题
2013/05/07 Javascript
json格式的时间显示为正常年月日的方法
2013/09/08 Javascript
Javascript中Array.prototype.map()详解
2014/10/22 Javascript
jQuery使用slideUp方法实现控制元素缓慢收起
2015/03/27 Javascript
详解如何使用webpack打包多页jquery项目
2019/02/01 jQuery
分享Angular http interceptors 拦截器使用(推荐)
2019/11/10 Javascript
js将URL网址转为16进制加密与解密函数
2020/03/04 Javascript
Openlayers绘制地图标注
2020/09/28 Javascript
vue+echarts+datav大屏数据展示及实现中国地图省市县下钻功能
2020/11/16 Javascript
python使用clear方法清除字典内全部数据实例
2015/07/11 Python
Python实现模拟浏览器请求及会话保持操作示例
2018/07/30 Python
Python数据可视化实现正态分布(高斯分布)
2019/08/21 Python
pygame实现五子棋游戏
2019/10/29 Python
Python lambda表达式原理及用法解析
2020/08/18 Python
Python中BeautifulSoup通过查找Id获取元素信息
2020/12/07 Python
实例讲解CSS3中Transform的perspective属性的用法
2016/04/22 HTML / CSS
HTML5 Canvas概述
2009/08/26 HTML / CSS
HTML5播放实现rtmp流直播
2020/06/16 HTML / CSS
英国领先的维生素和补充剂品牌:Higher Nature
2019/08/26 全球购物
Ibatis中如何提高SQL Map的性能
2013/05/11 面试题
一些Solaris面试题
2013/03/22 面试题
送货司机岗位职责
2013/12/11 职场文书
小学家长会邀请函
2014/01/23 职场文书
旅行社各个岗位职责
2014/03/15 职场文书
九一八事变纪念日演讲稿
2014/09/14 职场文书
初婚初育证明范本
2014/11/24 职场文书
教师党员自我评价范文
2015/03/04 职场文书
微信小程序用户授权最佳实践指南
2021/05/08 Javascript
SpringBoot 集成短信和邮件 以阿里云短信服务为例
2022/04/22 Java/Android