可控动画

Posted 喜欢的事用心去做

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可控动画相关的知识,希望对你有一定的参考价值。

<!DOCTYPE html>
<html>
    <!--
    简述:做一个可控动画,能够根据用户输入判断是逐帧播放还是完全播放,同时也能够根据输入前进或者后退。
    要点分析:
        监听交互:单击,触摸,滚动等等
        识别临界值:位移等。临界值内逐帧并且放弃交互时回退到交互前的状态;临界值外则动画完全播放。
        动画:可在前进和后退之间切换(可通过传参);可逐帧播放(帧可以是小动画)
        优化效率
    相关交互:
        下拉时:逐帧退和整节退
        上拉时:逐帧前进和整节前进
        放弃操作:超过临界值(动画完成)和未超过临界值(动画回退)。
    动画关键点:帧和节都可进退,同时进退皆可控。
-->

    <head>
        <meta charset="UTF-8">
        <title>可控动画</title>
    </head>
    <style>
        ul,
        li {
            list-style: none;
            padding: 0;
            margin: 0;
        }
        
        ul {
            font-size: 0;
        }
        .btn-wrap{
            text-align: center;
            margin-top: 20px;
        }
        .window {
            width: 300px;
            height: 200px;
            overflow: hidden;
            margin: 60px auto;
            border: 1px solid red;
        }
        
        .canvas {
            width: 1200px;
            height: 200px;
        }
        
        .canvas img {
            height: 200px;
            width: 300px;
        }
        
        ul li {
            display: inline-block;
            width: 300px;
            text-align: center;
            background-color: greenyellow;
        }
    </style>
    <body>
        <div>
            <div class="btn-wrap">
                <button id="move">逐帧前进</button>
                <button id="single-reverse">逐帧后退</button>
                <button id="play">整节前进</button>
                <button id="reverse">整节后退</button>
            </div>
            <div class="window">
                <div class="canvas" id="main">
                    <ul>
                        <li class="item"><img draggable="false" src="img/img1.jpg"></li>
                        <li class="item"><img draggable="false" src="img/img2.jpg"></li>
                        <li class="item"><img draggable="false" src="img/img3.jpg"></li>
                    </ul>
                </div>
            </div>
        </div>
    </body>
    <script>
//变量定义
        var canvas = document.getElementsByClassName(canvas)[0],
            main=document.getElementById("main"),//画布元素,也就是移动主体。
            items=document.getElementsByClassName(item),
            item_len=items.length,
            value = false,//是否在临界值之外,true为在临界值之外,false为临界值之内。
            key=false,//鼠标是否按下
            index=0,//当前是第几节动画
            reverse = false,//节动画是否反方向播放
            single_reverse=false,//帧动画是否反方向播放
            frameTime = 13,//帧与帧之间播放间隔
            stepDistance = (300 / (3000 / 30)), //每次移动的小距离,也就是每帧位移,单位为像素。
            stepDistanceSum = 0; //移动的总距离
//交互
        //顺序播放
        document.getElementById(play).onclick = function() {
            index++;//每单击一次播放一节
            if(index>item_len){
                index=0;//如果节动画完全播放完毕,从头开始播放
            };
            reverse = false;
            value = true;
            littleMove(index);
        };
        //倒叙播放
        document.getElementById(reverse).onclick = function() {
            index--;//每单击一次后退一节
            if(index<0){
                index=0;
            };
            value = true;
            reverse = true;
            littleMove(index);
        };
        //正向移动帧,没有实际意义,用于临界值之内的帧移动
        document.getElementById(move).onclick = function() {
            value = false;
            reverse = false;
            single_reverse=false;
            littleMove(index);
        };
        //反向移动帧,没有实际意义,用于临界值之内的帧后退
        document.getElementById(single-reverse).onclick = function() {
            value = false;
            reverse = false;
            single_reverse=true;
            littleMove(index);
        };
        main.onmousedown=function(e){
            var e = e || event;
            key=true;
        };
        main.onmouseup=function(){
            key=false;
        };
        main.addEventListener(mousemove,function(e){
            var e = e || event;
            if(key){
                //鼠标被按下
                if(stepDistanceSum<50){
                    //并且小于临界值,一帧一帧播放动画
                    value = false;
                    reverse = false;
                    single_reverse=false;
                    littleMove(index);
                }else{
                    //临界值之外,播放完整节动画
                    reverse = false;
                    value = true;
                    littleMove(index);
                }
            }
        });
//动画函数
        function littleMove(index) {
//            console.log(‘进入littleMove函数‘);
            if(!value) {
                if(stepDistanceSum<=300*(item_len-1)){
                    //临界值之内,每次交互移动一次
                    if((stepDistanceSum-(300*index))<300) {//如果小于300则一直可以帧移动
                        if(single_reverse){
                            stepDistanceSum -= stepDistance;
                            canvas.style.marginLeft = -stepDistanceSum + px;
                        }else{
                            stepDistanceSum += stepDistance;
                            canvas.style.marginLeft = -stepDistanceSum + px;
                        }
                    } else {
                    }
                }else{
                    clearInterval(interval);
                }
                
            } else {
                //临界值外,小节动画一次性播放完毕
                var interval = setInterval(function() {
                    if(stepDistanceSum<=300*(item_len-1)){//未超过边界
//                        console.log(‘边界之内‘);
                        if(stepDistanceSum%300==0){
                            clearInterval(interval);
                        };
                        if(reverse) {
                            if(stepDistanceSum<0){
                                clearInterval(interval);
                            }else{
                                canvas.style.marginLeft =  +stepDistanceSum + px;
                                console.log(stepDistanceSum);
                                stepDistanceSum -= stepDistance;
                                console.log(stepDistanceSum);
                            }
                            
                        } else {
                            canvas.style.marginLeft = -stepDistanceSum + px;
                            stepDistanceSum += stepDistance;
                        }
                    }else{//超过边界,从头开始
                        clearInterval(interval);
                        stepDistanceSum=0;
                    }
                }, frameTime)
            }
        };
    </script>
</html>

 

以上是关于可控动画的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段7——CSS动画

可控动画

流畅的 KineticJS 动画,可控的速度

使用嵌套片段和动画对象

Android:将“ViewPager”动画从片段更改为片段

Android 动画嵌套片段