链式运动效果,结合canvans与transition的动画实现-web


前言

最近在研究web端链式动画,多个元素按给的点位列表同时移动,并且可暂停或继续


一、动画的两种实现方式

1.JavaScript

setTimeOut(fn,time):经过time时间后执行回调fn,只执行一次。
setInterVal(fn,time):每过time时间执行回调fn,执行多次,直到执行清除函数cleanInterVal()。
requestAnimationFrame(): 执行时间是浏览器刷新频率决定的,一般遵循 W3C 标准,它在浏览器每次刷新页面之前执行。

2.CSS3

过渡效果:transition
动画:animation

还有canvans等其他的就不说了

二、运动效果

1.setInterVal+transition

需要canvans画出元素的移动轨迹,在test的css样式增加transition: all .5s,达到每改变一次位置的过渡效果:

<body>    
    <canvas id="myCanvas" width="500px" height="500px" style="position:absolute;left:0;top:0;z-index:-1">
    </canvas>
    <button id="btn1" >点击</button>
    <div id="test" style="height: 50px;width: 50px;background:pink;position:absolute;top:40px;left:0;"></div>
</body>

setInterVal的500ms交互时间与test元素的.5s过渡时间一样,js使元素每.5s改变一次位置:

//路线数据
var pointList = [{x:'50',y:'20'},{x:'100.9',y:'100.1'},{x:'250',y:'150'},{x:'200',y:'250'},{x:'180',y:'80'}];
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//画路线
context.beginPath();
context.moveTo(pointList[0].x, pointList[0].y);
for(var i = 1; i < pointList.length; i++){
    context.lineTo(pointList[i].x, pointList[i].y);
    console.log(pointList[i].x, pointList[i].y);
}
btn1.onclick = function(){
    var i = 0;
    var times = setInterval( function() {
       test.style['left'] = pointList[i].x + 'px';
       test.style['top'] = pointList[i].y + 'px';
       i++;
       if (i == pointList.length) {
           clearInterval(times);
       } 
    },500)//每500ms改变一次元素位置
    
}

2.setInterVal+js

如果想要canvans的画线跟元素运动同时进行,元素到哪就画到哪,move函数的两个点之间的动画函数,每隔16ms移动(x1到x2的距离/20),实现画线与元素同时前进一点点,由于浏览器刷新的间隔差不多为16ms所以每次移动1像素,就会有滑动的效果:

	function getCSS(obj,style){
        if(window.getComputedStyle){
            return getComputedStyle(obj)[style];
        }
        return obj.currentStyle[style];
    } 
    function move(obj,left,top,targetX,targetY,step,fn){
        //如果没有建立定时器对象,则在obj下建立定时器对象
        if(!obj.timers){obj.timers = {};}
        //清除定时器
        clearInterval(obj.timers[left]);
        //声明当前值变量cur
        var cur,cur2,times=0;
        //判断步长step的正负值
        //获取样式当前值并赋值给cur
        curX = parseFloat(getCSS(obj,left));
        curY = parseFloat(getCSS(obj,top));
        var stepX =  (targetX-curX) / 20;
        var stepY = (targetY-curY) / 20;
        console.log(stepX,stepY,"步长")
        //开启定时器
        obj.timers[left] = setInterval(function(){
            times++;
            //获取样式当前值并赋值给cur
            curX = parseFloat(getCSS(obj,left));
            curY = parseFloat(getCSS(obj,top));
            若步长设置值使得元素超过目标点时,将步长设置值更改为目标点值 - 当前值
            if((curX + stepX - targetX)*stepX > 0){
                stepX = targetX - curX;
                console.log(stepX,'超过')
            }
            //将合适的步长值赋值给元素的样式
            // console.log(times,"draw")
            obj.style[left] = curX + stepX + 'px';
            obj.style[top] = curY + stepY + 'px';
            createCanvasTracks(obj.offsetLeft,obj.offsetTop);
            //当元素到达目标点后,停止定时器
            if(times == 20){
                clearInterval(obj.timers[left]);
                obj.timers[left] = 0;
                times = 0;
                fn && fn.call(obj);    
            }       
        },16);        
    } 
    function createCanvasTracks(x,y){
        context.lineTo(x,y);
        context.stroke();        
    }//画图

每隔400ms运行move函数。

	btn1.onclick = async function(){
        var i = 0
        var timeBox = setInterval(() => {            
            move(test,'left','top',pointList[i].x,pointList[i].y,10)
            console.log(pointList[i].x,'pointIndex')
            if(i == pointList.length - 1 && pointList[i].x == pointList[0].x && pointList[i].y == pointList[0].y){
                i = 0;
                console.log('回到原点',pointList[i])
            }else{
                i++;  
            }           
            if(i == pointList.length ){
                if(pointList[i-1].x == pointList[0].x && pointList[i-1].y == pointList[0].y){
                    i = 0;
                }else{
                    clearInterval(timeBox)
                    console.log('end')
                }                
            }
            
        }, 400);
    } 

总结

以上都是自己搜索文章结合自己理解写出来的,还有一种是让元素暂停运动并且可以继续运动的代码实现,但是今天先写这些吧,如果有更好的实现方案欢迎你提出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值