刷头条的时候看到头条的刷新进度条不错,就自己做了一个,看一下效果:
看到这个就会想到怎么去实现呢?
- 绘制方形(用4条线段的方式来绘制),不直接绘制方形。
- 控制右上角往下运动,同时右下角往上运动(改变Y左边即可)。
- 右边的运动完以后,停止右边,让左上角往下,左下角也往上运动。
- 左边运动完成后,停止左边,启动右边,重复此过程。
先来写好绘制方形的函数
//构造函数
function DynamicRectangle(o){
this.x=0,//原点坐标X
this.y=0,//原点坐标Y
this.x1=0,//X1坐标
this.y1=0,//Y1坐标
this.x2=0,//X2坐标
this.y2=0,//Y2坐标
this.x3=0,//X3坐标
this.y3=0,//Y3坐标
this.x4=0,//X4坐标
this.y4=0,//Y4坐标
this.init(o);
}
//初始化
DynamicRectangle.prototype.init=function(o){
for(var key in o){
this[key]=o[key];
}
}
//绘制线条
DynamicRectangle.prototype.drawLine=function(ctx,startX,startY,endX,endY){
ctx.save();
ctx.beginPath();
ctx.translate(this.x,this.y);//设定原点坐标
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
if(this.lineWidth){//线宽
ctx.lineWidth=this.lineWidth;
}
if(this.lineCap){
ctx.lineCap=this.lineCap;//线帽
}
if(this.stroke){//描边
this.strokeStyle?(ctx.strokeStyle=this.strokeStyle):null;
ctx.stroke();
}
ctx.restore();
}
//绘制
DynamicRectangle.prototype.render=function(context){
var ctx=context;
//绘制好4条线段
this.drawLine(ctx,this.x1,this.y1,this.x2,this.y2);//上边线
this.drawLine(ctx,this.x2,this.y2,this.x3,this.y3);//右边线
this.drawLine(ctx,this.x3,this.y3,this.x4,this.y4);//下边线
this.drawLine(ctx,this.x4,this.y4,this.x1,this.y1);//左边线
return this;
}
来生成一个方形
//创建方形
var rect = new DynamicRectangle({
x:7,//原点坐标x
y:2,//原点坐标y
x1:0,//方形左上角坐标x
y1:0,//方形左上角坐标y
x2:100,//方形右上角坐标x
y2:0,//方形右上角坐标y
x3:100,//方形右下角坐标x
y3:60,//方形右下角坐标y
x4:0,//方形左下角坐标x
y4:60,//方形左下角坐标y
lineWidth:1.5,//线宽
lineCap:'square',//线帽
stroke:true,//描边
strokeStyle:'palevioletred',//线的颜色
}).render(ctx);
效果如下:
如何动起来呢,先来看右边,要做到右上角往下运动,只要使右上角的Y坐标增加就可以,加入定时函数,重复的去增加右上角的Y坐标,再重新绘制出来
var dir=1;//方向
var dis=2;//X轴移动初始值
move=function(){
//清理画布
ctx.clearRect(0,0,W,H);
rect.y2+=dis*dir;
rect.render(ctx);
}
timmer=setInterval(move,10);//开始任务
此时的效果是这样的
但是会一直往下走,所以要限定方向,到达底部后折返往上,并且回到顶部后再次调整方向往下,在move函数里面调整一下即可:
move=function(){
//清理画布
ctx.clearRect(0,0,W,H);
rect.y2+=dis*dir;
rect.render(ctx);
if(rect.y2>=60||rect.y2<=0){
dir=-dir;//改变方向
}
}
加入右下角的运动
move=function(){
//清理画布
ctx.clearRect(0,0,W,H);
rect.y2+=dis*dir;
rect.y3+=-dis*dir;
rect.render(ctx);
if(rect.y2>=60||rect.y2<=0||rect.y3>=60||rect.y3<=0){
dir=-dir;//改变方向
}
}
再把左边加入运动,因为右边运动完后切换到左边,左边运动完停止,右边再运动,需要加入一个参数来控制。
move=function(){
//清理画布
ctx.clearRect(0,0,W,H);
if(animateDir=='right'){//长方形的右边在运动
rect.y2+=dis*dir;
rect.y3+=-dis*dir;
}else{//长方形的左边在运动
rect.y1+=dis*dir2;
rect.y4+=-dis*dir2;
}
rect.render(ctx);
if(animateDir=='right'){
if(rect.y2>=60||rect.y2<=0||rect.y3>=60||rect.y3<=0){
dir=-dir;
animateDir='left';//切换为左边运动
}
}else{
if(rect.y1>=60||rect.y1<=0||rect.y4>=60||rect.y4<=0){
dir2=-dir2;
animateDir='right';//切换为右边运动
}
}
}
此时效果如下:
加快一下速度,timmer=setInterval(move,10);
把这些都封装一下,再看一下效果
完整代码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="GBK">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<button onclick='start()'>开始</button>
<button onclick='stop()'>结束</button>
<div id='process'>
</div>
<script type="text/javascript">
var timmer=null;
function start(){
if(timmer) return ;//防止重复点击
var process = document.getElementById('canvasDiv');
process.style.display="block";
timmer=setInterval(move,10);//开始任务
}
function stop(){
var process = document.getElementById('canvasDiv');
process.style.display="none";
clearInterval(timmer); //结束任务
timmer=null;
}
//构造函数
function DynamicRectangle(o){
this.x=0,//原点坐标X
this.y=0,//原点坐标Y
this.x1=0,//X1坐标
this.y1=0,//Y1坐标
this.x2=0,//X2坐标
this.y2=0,//Y2坐标
this.x3=0,//X3坐标
this.y3=0,//Y3坐标
this.x4=0,//X4坐标
this.y4=0,//Y4坐标
this.order=0,
this.init(o);
}
//初始化
DynamicRectangle.prototype.init=function(o){
for(var key in o){
this[key]=o[key];
}
}
//绘制线条
DynamicRectangle.prototype.drawLine=function(ctx,startX,startY,endX,endY){
ctx.save();
ctx.beginPath();
ctx.translate(this.x,this.y);//设定原点坐标
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
if(this.lineWidth){//线宽
ctx.lineWidth=this.lineWidth;
}
if(this.lineCap){
ctx.lineCap=this.lineCap;//线帽
}
if(this.stroke){//描边
this.strokeStyle?(ctx.strokeStyle=this.strokeStyle):null;
ctx.stroke();
}
ctx.restore();
}
//绘制
DynamicRectangle.prototype.render=function(context){
var ctx=context;
//绘制好4条线段
this.drawLine(ctx,this.x2,this.y2,this.x3,this.y3);//右边线
this.drawLine(ctx,this.x4,this.y4,this.x1,this.y1);//左边线
if(this.order>0){//先绘制上面那条边
this.drawLine(ctx,this.x1,this.y1,this.x2,this.y2);//上边线
this.drawLine(ctx,this.x3,this.y3,this.x4,this.y4);//下边线
}else{先绘制下面那条边
this.drawLine(ctx,this.x3,this.y3,this.x4,this.y4);//下边线
this.drawLine(ctx,this.x1,this.y1,this.x2,this.y2);//上边线
}
return this;
}
createCanvas();
var move;
function createCanvas(){
var process = document.getElementById('process');
var div = document.createElement('div');
div.id="canvasDiv";
div.style.cssText="position:absolute;top:50px;left:30px;display:none;";
var canvas = document.createElement('canvas');
var W = canvas.width = 114;
var H = canvas.height = 64;
div.appendChild(canvas);
process.appendChild(div);
var ctx = canvas.getContext('2d');
//创建方形
var rect = new DynamicRectangle({
x:7,//原点坐标x
y:2,//原点坐标y
x1:0,//方形左上角坐标x
y1:0,//方形左上角坐标y
x2:100,//方形右上角坐标x
y2:0,//方形右上角坐标y
x3:100,//方形右下角坐标x
y3:60,//方形右下角坐标y
x4:0,//方形左下角坐标x
y4:60,//方形左下角坐标y
lineWidth:1.5,//线宽
lineCap:'square',//线帽
stroke:true,//描边
strokeStyle:'palevioletred',//线的颜色
order:1//绘制顺序
}).render(ctx);
var dir=1;//方向
var dir2=1;//方向2
var dis=2;//X轴移动初始值
var animateDir='right';
move=function(){
//清理画布
ctx.clearRect(0,0,W,H);
if(animateDir=='right'){
rect.y2+=dis*dir;
rect.y3+=-dis*dir;
}else{
rect.y1+=dis*dir2;
rect.y4+=-dis*dir2;
}
rect.render(ctx);
if(animateDir=='right'){
if(rect.y2>=60||rect.y2<=0||rect.y3>=60||rect.y3<=0){
dir=-dir;
animateDir='left';
if(dir<0){
rect.order=-1;
}else{
rect.order=1;
}
}
}else{
if(rect.y1>=60||rect.y1<=0||rect.y4>=60||rect.y4<=0){
dir2=-dir2;
animateDir='right';
if(dir2<0){
rect.order=-1;
}else{
rect.order=1;
}
}
}
}
}
</script>
</body>
</html>