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滚动条多种样式,推荐
Feb 05 Javascript
JQuery textlimit 显示用户输入的字符数 限制用户输入的字符数
May 14 Javascript
jquery1.4 教程二 ajax方法的改进
Feb 25 Javascript
javascript显示用户停留时间的简单实例
Aug 05 Javascript
node.js适合游戏后台开发吗?
Sep 03 Javascript
浅析node.js中close事件
Nov 26 Javascript
详解JavaScript中的异常处理方法
Jun 16 Javascript
Javascript页面跳转常见实现方式汇总
Nov 28 Javascript
Jquery 整理元素选取、常用方法一览表
Nov 26 Javascript
protractor的安装与基本使用教程
Jul 07 Javascript
vue设置全局访问接口API地址操作
Aug 14 Javascript
vue中的计算属性和侦听属性
Nov 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防止刷新重复提交页面的示例代码
2015/11/11 PHP
javascript与asp.net(c#)互相调用方法
2009/12/13 Javascript
简单实例处理url特殊符号&amp;处理(2种方法)
2013/04/02 Javascript
JavaScript中发布/订阅模式的简单实例
2014/11/05 Javascript
jquery复选框多选赋值给文本框的方法
2015/01/27 Javascript
jquery常用函数与方法汇总
2015/09/01 Javascript
Bootstrap每天必学之导航条
2015/11/27 Javascript
js获取及修改网页背景色和字体色的方法
2015/12/29 Javascript
js中利用tagname和id获取元素的方法
2016/01/03 Javascript
详解Bootstrap四种图片样式
2016/01/04 Javascript
BootStrap智能表单实战系列(九)表单图片上传的支持
2016/06/13 Javascript
JS实现pasteHTML兼容ie,firefox,chrome的方法
2016/06/22 Javascript
浅谈JS中的反柯里化( uncurrying)
2017/08/17 Javascript
layui表格checkbox选择全选样式及功能的实例
2018/03/07 Javascript
vue图片上传组件使用详解
2019/12/23 Javascript
[08:53]DOTA2-DPC中国联赛 正赛 PSG.LGD vs LBZS 选手采访
2021/03/11 DOTA
python实现ping的方法
2015/07/06 Python
Python脚本获取操作系统版本信息
2016/12/17 Python
python 实现任务管理清单案例
2020/04/25 Python
Pytho爬虫中Requests设置请求头Headers的方法
2020/09/22 Python
解决canvas转base64/jpeg时透明区域变成黑色背景的方法
2016/10/23 HTML / CSS
HTML5触摸事件实现移动端简易进度条的实现方法
2018/05/04 HTML / CSS
悬挂训练绳:TRX
2017/12/14 全球购物
Cotton On香港网站:澳洲时装连锁品牌
2018/11/01 全球购物
Raffaello Network西班牙:意大利拉斐尔时尚购物网
2019/03/12 全球购物
银行类自荐信
2014/02/04 职场文书
教师学习群众路线心得体会
2014/11/04 职场文书
2014年机关党建工作总结
2014/11/11 职场文书
2014个人年终工作总结范文
2014/12/15 职场文书
销售员岗位职责范本
2015/04/11 职场文书
离婚代理词范文
2015/05/23 职场文书
婚宴领导致辞
2015/07/28 职场文书
《正比例》教学反思
2016/02/23 职场文书
Python基础之元组与文件知识总结
2021/05/19 Python
python使用BeautifulSoup 解析HTML
2022/04/24 Python
Java Redisson多策略注解限流
2022/09/23 Java/Android