仿360水波评分特效、加速球特效、水波动态加载动画、可改造成圆形进度条,很丝滑!

先看一下最终效果

    

正弦曲线

正弦曲线公式  y = A sin(Bx + C) + D
         

   振幅是 A,A 值越大,曲线更陡峭
   B值越大 周期越短
   C水平位移
   垂直位移是 D,控制曲线上下移动

实现思路

首先来绘制曲线

  1.定义构造函数和初始化方法

//sin曲线构造函数
 function drawSin(option){
	this.init(option);
 }
 //初始化
 drawSin.prototype.init=function(o){
 	this.A=6;//振幅
 	this.B=0.02;//周期
 	this.C=0;//水平位移
 	this.D=H/2;//垂直位移
 	this.color='orange';//填充颜色
 	this.speed=-0.2; //移动速度
 	this.percent=0;//百分比
 	this.offsetX=0;//开始X坐标
 	
 	for(var key in o){//循环new时候传入的参数,如果存在,则覆盖,没有传则使用默认
 		if(typeof this[key] !=='undefined'){
 		   this[key] = o[key];
 		}
 	}
 }

2.添加一个render绘制函数

 //绘制曲线
 drawSin.prototype.render=function(c){
 	c.save();
 	c.beginPath();
 	var y=0;
 	for(var x=this.offsetX;x<W+this.offsetX;x+=0.01){
	 	//正弦曲线公式:y = A sin(Bx + C) + D
	 	//振幅是 A,A 值越大,曲线更陡峭
	 	//B值越大 周期越短
	 	//C水平位移
	 	//垂直位移是 D,控制曲线上下移动
	 	 y = this.A*Math.sin(this.B*(x+this.offsetX) + this.C) + this.D;
 	     c.lineTo(x,y);
 	}
 	c.lineTo(W,H);
 	c.lineTo(0,H);
 	c.fillStyle = this.color;
 	c.stroke()
 	c.closePath();
 	c.restore();
 	
 	return this;
 }

3.生成一根正弦曲线

 var sin1 = new drawSin({
 	A:20,B:0.025,
 	C:0,D:H/2-6,
 	color:'#3399FF'
 }).render(ctx);

4.看一下现在的效果

5.加上流动代码

  drawSin.prototype.update=function(){
 	this.C+=this.speed;//设定横向移动递增
  }

  function move(){
 	//执行动画帧
 	window.requestAnimationFrame(move);
 	//清理画布
 	ctx.clearRect(0,0,W,H);
 	//更新 
 	sin1.update();
 	//绘制
 	sin1.render(ctx);
 }
 window.requestAnimationFrame(move);

6.加上颜色

裁剪成圆形

 draw();
  function draw(){//画圆
  	ctx.strokeStyle='rgb(250,235,215)';
	ctx.lineWidth=10;
	ctx.beginPath();
	ctx.arc(W/2,H/2,160,0,Math.PI*2,true);
	ctx.stroke();
	ctx.clip();
  }

效果如下

加上百分比

<canvas id='canvas'></canvas>
		<div id='percent'>
			<input type='text' value=0 oninput="doInput(this)" style="display:none;" >
			<p style="text-align: center;color:orange;"></p>
		</div>
 //显示的百分比
 function text(val){
 	if(inputClick)return ;
 	percent.children[1].innerText=val;
	percent.children[0].value=val;
 }
 function doClick(e){
		var p=percent.children[1],input=percent.children[0];
		var e=e||window.event;
		var target=e.currentTarget;
			e.stopPropagation();//阻止冒泡
		if(target.tagName&&target.tagName.toUpperCase()==='DIV'){
			if(input.style.display==''){
				return;
			}
			//显示input
			input.style.display='';
			p.style.display='none';
			input.value=p.innerText;
			input.focus();
			inputClick=true;
		}else{
			if(input.style.display==''){
				p.style.display='';
				//隐藏input
				input.style.display='none';
				p.innerText=input.value;
				 //处理百分比
				editPercent();
			}
		}
	}
	function editPercent(){
		var p=percent.children[1],input=percent.children[0];
		//执行动画
		sin1.change=parseInt(p.innerText);
		sin2.change=parseInt(p.innerText);
	}
	//控制文本输入
	function doInput(obj){
		obj.value=obj.value.replace(/[^\d]/g,'');
		if(obj.value=='')obj.value=0;
		var value = parseInt(obj.value);
		if(value>100){
			obj.value=100;
		}else if(value<=0){
			obj.value=0;
		}
	}
	//百分比点击事件
	percent.addEventListener('click',doClick);
	document.addEventListener('click',doClick);
	
	

看下效果

 加多一条曲线、百分比可以编辑就完成了

换其他图形试试

1.三角形

2.长方形

3.心形

全部代码:

<!DOCTYPE html>
<html>
	<head lang="en">
		<meta charset="GBK">
		<title></title>
		<style>
*{
    margin: 0;
    padding: 0;
}
canvas{
	left:30px;
	position: absolute;
	border:1px solid ;
}
#percent{
	width: 90px;
    height: 90px;
    position: absolute;
    left: 190px;
    top: 230px;
    font-size: 50px;
    cursor: pointer;
}
#percent input{
	width: 90px;
    height: 90px;
    border-radius: 10px;
    border: 1px solid #EEEEEE;
    text-align:center;
    font-size: 50px;
}
</style>
	</head>
	<body>
		<canvas id='canvas'></canvas>
		<div id='percent'>
			<input type='text' value=0 oninput="doInput(this)" style="display:none;" >
			<p style="text-align: center;color:orange;"></p>
		</div>
	<script type="text/javascript">
  var percent = document.getElementById('percent');
  var canvas = document.getElementById('canvas')
  var W = canvas.width = 400
  var H = canvas.height = 400
  var ctx = canvas.getContext('2d');
  var inputClick=false;//控制百分比内容是否可以被更新

  draw();
  function draw(){//画圆
  	ctx.strokeStyle='rgb(250,235,215)';
	ctx.lineWidth=10;
	ctx.beginPath();
	ctx.arc(W/2,H/2,160,0,Math.PI*2,true);
	ctx.stroke();
	ctx.clip();
  }
  //drawTriangle();
  function drawTriangle(){//画三角形
  	ctx.strokeStyle='rgb(250,235,215)';
	ctx.lineWidth=10;
	ctx.beginPath();
	ctx.moveTo(W/2,40);
	ctx.lineTo(100,360);
	ctx.lineTo(300,360);
	ctx.closePath();
	ctx.stroke();
	ctx.clip();
  }
  
  //drawRect();
  function drawRect(){//画方形
  	ctx.strokeStyle='rgb(250,235,215)';
	ctx.lineWidth=10;
	ctx.beginPath();
	ctx.rect(140,40,120,320);
	ctx.closePath();
	ctx.stroke();
	ctx.clip();
  }
  //drawHeart();
  function drawHeart(){//画心形
  	ctx.strokeStyle='rgb(250,235,215)';
	ctx.lineWidth=10;
	ctx.beginPath();
	ctx.lineCap='round';
   	ctx.moveTo(200, 100);
	ctx.bezierCurveTo(50,-120,-80,260, 200, 360);
	ctx.moveTo(200, 100);
	ctx.bezierCurveTo(350,-120,W+80,260, 200, 360);
	ctx.stroke();
	ctx.clip();
  }
 //sin曲线构造函数
 function drawSin(option){
	this.init(option);
 }
 //初始化
 drawSin.prototype.init=function(o){
 	this.A=6;//振幅
 	this.B=0.02;//周期
 	this.C=0;//水平位移
 	this.D=H/2;//垂直位移
 	this.color='orange';//填充颜色
 	this.speed=-0.2; //移动速度
 	this.percent=0;//百分比
 	this.offsetX=0;//开始X坐标
 	this.moveFlag=false;//页面加载时是否执行移动动画
 	this.move={//定义移动动画的相关参数
 		start:360,//开始位置
 		end:200,//结束位置
 		total:320,//总高度
 		dis:40,//距离画布底部的高度
 		speed:4//美移动动画速度
 	};
 	
 	for(var key in o){//循环new时候传入的参数,如果存在,则覆盖,没有传则使用默认
 		if(typeof this[key] !=='undefined'){
 		   this[key] = o[key];
 		}
 	}
 	if(this.moveFlag){//如果有移动标示,则sin曲线的Y位置更新为初始位置
 		this.D=this.move.start;
 	}else {//否则执行更新函数
 		this.update();
 	}
 }
  drawSin.prototype.update=function(){
 	this.C+=this.speed;//设定横向移动递增
 	
 	if(typeof this.change=='number'){//这个是修改百分比执行的更新块
 		var temp = this.change*this.move.total/100;//计算当前百分比应该占用总高度的实值
 		var changePos=this.move.start-temp;//计算应该处于的位置
 		if(changePos>this.move.end){//水波往下
 			this.D+=this.move.speed;
 			if(this.D>=changePos){//执行到位置后释放相关参数
 				this.change=undefined;
 				this.move.end=this.D;//设置结束位置
 				inputClick=false;
 			}
 		}else if(changePos<this.move.end){
 			this.D-=this.move.speed;
 			if(this.D<=changePos){
 				this.change=undefined;
 				this.move.end=this.D;
 				inputClick=false;
 			}
 		}else {
 			this.change=undefined;
 			inputClick=false;
 		}
 		//设定最终百分比
 		this.percent = this.change;
 	}else{
 		if(this.moveFlag && this.D>this.move.end){//如果没有执行到终点,就继续执行
	 		this.D-=this.move.speed;
	 	}
	 	//设定百分比
	 	this.percent =Math.round((this.move.total+this.move.dis-this.D)/this.move.total*100);
	 	//显示百分比
	 	text(this.percent);
 	}
 	
 }
 //绘制曲线
 drawSin.prototype.render=function(c){
 	c.save();
 	c.beginPath();
 	var y=0;
 	for(var x=this.offsetX;x<W+this.offsetX;x+=0.01){
	 	//正弦曲线公式:y = A sin(Bx + C) + D
	 	//振幅是 A,A 值越大,曲线更陡峭
	 	//B值越大 周期越短
	 	//C水平位移
	 	//垂直位移是 D,控制曲线上下移动
	 	 y = this.A*Math.sin(this.B*(x+this.offsetX) + this.C) + this.D;
 	     c.lineTo(x,y);
 	}
 	c.lineTo(W,H);
 	c.lineTo(0,H);
 	c.fillStyle = this.color;
 	c.fill();
 	c.closePath();
 	c.restore();
 	
 	return this;
 }
 //显示的百分比
 function text(val){
 	if(inputClick)return ;
 	percent.children[1].innerText=val;
	percent.children[0].value=val;
 }
 
 //创建sin曲线1
 var sin1 = new drawSin({
 	A:10,B:0.025,
 	C:0,D:H/2-6,
 	color:'#3399FF',
 	speed:-0.1,
 	moveFlag:true
 }).render(ctx);
 //创建sin曲线2
  var sin2 = new drawSin({
 	A:10,B:0.025,
 	C:0,D:H/2,
 	color:'#3366FF',
 	speed:-0.1,
 	offsetX:40,
 	moveFlag:true
 }).render(ctx);

 
 function move(){
 	//执行动画帧
 	window.requestAnimationFrame(move);
 	//清理画布
 	ctx.clearRect(0,0,W,H);
 	//更新 
 	sin1.update();
 	//绘制
 	sin1.render(ctx);
 	
 	sin2.update();
 	sin2.render(ctx);
 }
 window.requestAnimationFrame(move);

 function doClick(e){
		var p=percent.children[1],input=percent.children[0];
		var e=e||window.event;
		var target=e.currentTarget;
			e.stopPropagation();//阻止冒泡
		if(target.tagName&&target.tagName.toUpperCase()==='DIV'){
			if(input.style.display==''){
				return;
			}
			//显示input
			input.style.display='';
			p.style.display='none';
			input.value=p.innerText;
			input.focus();
			inputClick=true;
		}else{
			if(input.style.display==''){
				p.style.display='';
				//隐藏input
				input.style.display='none';
				p.innerText=input.value;
				 //处理百分比
				editPercent();
			}
		}
	}
	function editPercent(){
		var p=percent.children[1],input=percent.children[0];
		//执行动画
		sin1.change=parseInt(p.innerText);
		sin2.change=parseInt(p.innerText);
	}
	//控制文本输入
	function doInput(obj){
		obj.value=obj.value.replace(/[^\d]/g,'');
		if(obj.value=='')obj.value=0;
		var value = parseInt(obj.value);
		if(value>100){
			obj.value=100;
		}else if(value<=0){
			obj.value=0;
		}
	}
	//百分比点击事件
	percent.addEventListener('click',doClick);
	document.addEventListener('click',doClick);
	
	
	
</script>
	</body>
</html>

给个三连吧大佬们,谢谢!

猜你喜欢

转载自blog.csdn.net/dkm123456/article/details/113189108