• 命令模式-3.撤销与重做的实现


    <!DOCTYPE html>
    <html>
    <head>
        <title>撤销命令</title>
    </head>
    <body>
        <div id="ball" style="position:absolute;background:#000;50px;height:50px"></div>
        输入小球移动后的位置:<input id="pos"/>
        <button id="moveBtn">开始移动</button>
        <button id="cancelBtn">cancel</cancel> <!--增加取消按钮-->
    </body>
    <script type="text/javascript">
        //运动算法
            var tween = {
                    linear: function( t, b, c, d ){
                        return c*t/d + b;
                    },
                    easeIn: function( t, b, c, d ){
                        return c * ( t /= d ) * t + b;
                    },
                    strongEaseIn: function(t, b, c, d){
                        return c * ( t /= d ) * t * t * t * t + b;
                    },
                    strongEaseOut: function(t, b, c, d){
                        return c * ( ( t = t / d - 1) * t * t * t * t + 1 ) + b;
                    },
                    sineaseIn: function( t, b, c, d ){
                        return c * ( t /= d) * t * t + b;
                    },
                    sineaseOut: function(t,b,c,d){
                        return c * ( ( t = t / d - 1) * t * t + 1 ) + b;
                    }
                };
            var Animate = function (dom) {
                this.dom          = dom;//进行运行的dom节点
                this.startTime    = 0;//动画开始时间
                this.startPos     = 0;//dom的初始位置
                this.endPos       = 0;//dom的目标位置
                this.propertyName = null;//dom节点需要被改变的css属性名
                this.easing       = null;//缓动算法
                this.duration     = null;//动画持续时间
            }
            Animate.prototype.start = function (propertyName, endPos, duration, easing) {
                this.startTime    = +new Date;//动画启动时间
                this.startPos     = this.dom.getBoundingClientRect()[propertyName];//初始位置
                this.propertyName = propertyName;
                this.endPos       = endPos;
                this.duration     = duration;
                this.easing       = tween[ easing ]; // 缓动算法
    
                var _self  = this;
                var timeId = setInterval(function () {//启动定时器;开始动画
                    if (_self.step() === false) {//如果动画结束;停止计时器
                        clearInterval(timeId);
                    }
                },19)
            };
            Animate.prototype.step = function () {
                var t = +new Date;
                if (t>=this.startTime+this.duration) {
                    this.update(this.endPos);
                    return false;
                }
                //当前位置
                var pos = this.easing(t - this.startTime, this.startPos, this.endPos - this.startPos, this.duration);
                this.update(pos);
                console.log(pos);
            }
            Animate.prototype.update = function (pos) {
                this.dom.style[this.propertyName] = pos+'px';
            }
        //此处开始,上面引用
    
        /*
        var ball    = document.getElementById('ball'),
            pos     = document.getElementById('pos'),
            moveBtn = document.getElementById('moveBtn');
        moveBtn.onclick = function () {
            var animate = new Animate(ball);
            animate.start('left', pos.value, 1000, 'strongEaseOut');
        }
        */
    
        /*
        如果文本框输入 200,然后点击 moveBtn按钮,可以看到小球顺利地移动到水平方向 200px
    的位置。现在我们需要一个方法让小球还原到开始移动之前的位置。当然也可以在文本框中再次
    输入-200,并且点击 moveBtn 按钮,这也是一个办法,不过显得很笨拙。页面上最好有一个撤销
    按钮,点击撤销按钮之后,小球便能回到上一次的位置。
        */
    
        //改成命令模式
        var ball      = document.getElementById('ball'),
            pos       = document.getElementById('pos'),
            moveBtn   = document.getElementById('moveBtn'),
            cancelBtn = document.getElementById( 'cancelBtn' );
        var MoveCommond = function (receiver, pos) {
            this.receiver = receiver;
            this.pos = pos;
            this.oldPos = null;
        };
        MoveCommond.prototype.execute = function () {
            this.receiver.start('left', this.pos, 1000, 'strongEaseOut');
            //Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。
            /*
            返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合, 即:是与该元素相关的CSS 边框集合 。
    
            DOMRect 对象包含了一组用于描述边框的只读属性——left、top、right和bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。
            */
            //记录开始移动前的位置;
            this.oldPos = this.receiver.dom.getBoundingClientRect()[this.receiver.propertyName];
        }
    
        MoveCommond.prototype.undo = function () {
            //回到记录的位置
            this.receiver.start('left', this.oldPos, 1000, 'strongEaseOut');
        }
    
        var moveCommond;
    
        moveBtn.onclick = function () {
            var animate = new Animate(ball);
            moveCommond = new MoveCommond(animate, pos.value);
            moveCommond.execute();
        }
    
        cancelBtn.onclick = function () {
            moveCommond.undo();//撤销命令
        }
    </script>
    </html>
  • 相关阅读:
    js中使用EL表达式
    洛谷——RMQ
    模板——RMQ
    洛谷——图论
    洛谷——基础搜索
    洛谷——搜索
    搭桥
    简单dp
    Codevs 3194 基因变异
    cin、scanf、gets、getchar 用法介绍
  • 原文地址:https://www.cnblogs.com/hanhui66/p/7110813.html
Copyright © 2020-2023  润新知