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 相关文章推荐
js/jquery去掉空格,回车,换行示例代码
Nov 05 Javascript
javascript+canvas实现刮刮卡抽奖效果
Jul 29 Javascript
浏览器兼容的JS写法总结
Apr 27 Javascript
利用jQuery实现打字机字幕效果实例代码
Sep 02 Javascript
AngularJS定时器的使用与移除操作方法【interval与timeout】
Dec 14 Javascript
jquery dataTable 获取某行数据
May 05 jQuery
基于JavaScript实现百度搜索框效果
Jun 28 Javascript
vue click.stop阻止点击事件继续传播的方法
Sep 04 Javascript
谈谈JavaScript中super(props)的重要性
Feb 12 Javascript
vue中英文切换实例代码
Jan 21 Javascript
解决vue-loader加载不上的问题
Oct 21 Javascript
js判断两个数组相等的5种方法
May 06 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中利用str_pad函数生成数字递增形式的产品编号
2013/09/30 PHP
PHP转换文本框内容为HTML格式的方法
2016/07/20 PHP
YII框架批量插入数据的方法
2017/03/18 PHP
swoole锁的机制代码实例讲解
2021/03/04 PHP
日历查询的算法 如何计算某一天是星期几
2012/12/12 Javascript
基于JQuery 选择器使用说明介绍
2013/04/18 Javascript
nodejs npm install全局安装和本地安装的区别
2014/06/05 NodeJs
深入解读JavaScript中的Iterator和for-of循环
2015/07/28 Javascript
jquery模拟进度条实现方法
2015/08/03 Javascript
easyui Droppable组件实现放置特效
2015/08/19 Javascript
AngularJS手动表单验证
2016/02/01 Javascript
jQuery实现点击后高亮背景固定显示的菜单效果【附demo源码下载】
2016/09/21 Javascript
百度地图JavascriptApi Marker平滑移动及车头指向行径方向
2017/03/13 Javascript
JS简单实现点击按钮或文字显示遮罩层的方法
2017/04/27 Javascript
jquery Ajax实现Select动态添加数据
2017/06/08 jQuery
jQuery实现动态加载select下拉列表项功能示例
2018/05/31 jQuery
mpvue开发音频类小程序踩坑和建议详解
2019/03/12 Javascript
Node.js实现一个HTTP服务器的方法示例
2019/05/13 Javascript
Vue3.0数据响应式原理详解
2019/10/09 Javascript
Node.js API详解之 net模块实例分析
2020/05/18 Javascript
Python3连接SQLServer、Oracle、MySql的方法
2018/06/28 Python
使用Flask-Cache缓存实现给Flask提速的方法详解
2019/06/11 Python
Python OpenCV 调用摄像头并截图保存功能的实现代码
2019/07/02 Python
Flask框架中request、请求钩子、上下文用法分析
2019/07/23 Python
Python如何实现强制数据类型转换
2019/11/22 Python
python如何输出反斜杠
2020/06/18 Python
详解css3中dispaly的Grid布局与Flex布局
2020/09/11 HTML / CSS
Superdry极度乾燥官网:日本街头风格,纯英国制造品牌
2016/10/31 全球购物
英国手工制作的现代与经典的沙发和床:Love Your Home
2020/09/26 全球购物
自荐信格式范文
2013/10/07 职场文书
快递业务员岗位职责
2014/01/06 职场文书
初婚未育未抱养证明
2014/01/12 职场文书
党支部公开承诺践诺书
2014/03/28 职场文书
幼儿园教师求职信
2015/03/20 职场文书
超级实用的公文标题大全!
2019/07/19 职场文书
MySQL数据库索引的最左匹配原则
2021/11/20 MySQL