zoukankan      html  css  js  c++  java
  • 命令模式

    /**
     * Created by shangkuikui on 2017/4/26.
     */
    
    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 节点的位置,即dom 的初始位置
        this.endPos = 0; // 动画结束时,dom 节点的位置,即dom 的目标位置
        this.propertyName = null; // dom 节点需要被改变的css 属性名
        this.easing = null; // 缓动算法
        this.duration = null; // 动画持续时间
    };
    
    Animate.prototype.start = function (propertyName, endPos, duration, easing, cb) {
        this.startTime = +new Date; // 动画启动时间
        this.startPos = this.dom.getBoundingClientRect()[propertyName]; // dom 节点初始位置
        this.propertyName = propertyName; // dom 节点需要被改变的CSS 属性名
        this.endPos = endPos; // dom 节点目标位置
        this.duration = duration; // 动画持续事件
        this.easing = tween[easing]; // 缓动算法
        var self = this;
        var timeId = setInterval(function () { // 启动定时器,开始执行动画
            if (self.step() === false) { // 如果动画已结束,则清除定时器
                clearInterval(timeId);
                Event.trigger('finish');
                if(cb && typeof cb === "function" ){
                    cb();
                }
            }
        }, 19);
    };
    
    Animate.prototype.step = function () {
        var t = +new Date; // 取得当前时间
        if (t >= this.startTime + this.duration) { // (1)
            this.update(this.endPos); // 更新小球的CSS 属性值
            return false;
        }
        var pos = this.easing(t - this.startTime, this.startPos, this.endPos - this.startPos, this.duration);
    // pos 为小球当前位置
        this.update(pos); // 更新小球的CSS 属性值
    };
    
    Animate.prototype.update = function( pos ){
        this.dom.style[ this.propertyName ] = pos + 'px';
    };
    View Code
    var Event = (function () {
        var global = this,
            Event,
            _default = 'default';
        Event = function () {
            var _listen,
                _trigger,
                _remove,
                _slice = Array.prototype.slice,
                _shift = Array.prototype.shift,
                _unshift = Array.prototype.unshift,
                namespaceCache = {},
                _create,
                find,
                each = function (ary, fn) {
                    var ret;
                    for (var i = 0, l = ary.length; i < l; i++) {
                        var n = ary[i];
                        ret = fn.call(n, i, n);
                    }
                    return ret;
                };
            _listen = function (key, fn, cache) {
                if (!cache[key]) {
                    cache[key] = [];
                }
                cache[key].push(fn);
            };
            _remove = function (key, cache, fn) {
                if (cache[key]) {
                    if (fn) {
                        for (var i = cache[key].length; i >= 0; i--) {
                            if (cache[key][i] === fn) {
                                cache[key].splice(i, 1);
                            }
                        }
                    } else {
                        cache[key] = [];
                    }
                }
            };
            _trigger = function () {
                var cache = _shift.call(arguments),
                    key = _shift.call(arguments),
                    args = arguments,
                    _self = this,
                    ret,
                    stack = cache[key];
                if (!stack || !stack.length) {
                    return;
                }
                return each(stack, function () {
                    return this.apply(_self, args);
                });
            };
            _create = function (namespace) {
                var namespace = namespace || _default;
                var cache = {},
                    offlineStack = [], // 离线事件
                    ret = {
                        listen: function (key, fn, last) {
                            _listen(key, fn, cache);
                            if (offlineStack === null) {
                                return;
                            }
                            if (last === 'last') {
                                offlineStack.length && offlineStack.pop()();
                            } else {
                                each(offlineStack, function () {
                                    this();
                                });
                            }
                            offlineStack = null;
                        },
                        one: function (key, fn, last) {
                            _remove(key, cache);
                            this.listen(key, fn, last);
                        },
                        remove: function (key, fn) {
                            _remove(key, cache, fn);
                        },
                        trigger: function () {
                            var fn,
                                args,
                                _self = this;
                            _unshift.call(arguments, cache);
                            args = arguments;
                            fn = function () {
                                return _trigger.apply(_self, args);
                            };
                            if (offlineStack) {
                                return offlineStack.push(fn);
                            }
                            return fn();
                        }
                    };
                return namespace ?
                    ( namespaceCache[namespace] ? namespaceCache[namespace] :
                        namespaceCache[namespace] = ret )
                    : ret;
            };
            return {
                create: _create,
                one: function (key, fn, last) {
                    var event = this.create();
                    event.one(key, fn, last);
                },
                remove: function (key, fn) {
                    var event = this.create();
                    event.remove(key, fn);
                },
                listen: function (key, fn, last) {
                    var event = this.create();
                    event.listen(key, fn, last);
                },
                trigger: function () {
                    var event = this.create();
                    event.trigger.apply(this, arguments);
                }
            };
        }();
        return Event;
    })();
    View Code

    以上是文章中用到的两个js文件,event.js  和  animate.js

    1普通青年版(初级命令模式)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <button id="bt1">按钮1</button>
    <button id="bt2">按钮2</button>
    <button id="bt3">按钮3</button>
    <div style="position:absolute;background:blue" id="div">我是div</div>
    </body>
    <script src="animate.js"></script>
    <script>
        const bt1  = document.querySelector('#bt1');
        const bt2  = document.querySelector('#bt2');
        const bt3  = document.querySelector('#bt3');
        const func= {
            fn1:function () {
                var div = document.getElementById( 'div' );
                var animate = new Animate( div );
                animate.start( 'left', 500, 1000, 'sineaseIn' );
                console.log('fn1')
            },
            fn2:function () {
                console.log('fn2')
            },
            fn3:function () {
                console.log('fn3')
            }
        };
        let Acommond = function (recevier) {
            return{
                execute () {
                    recevier.fn1()
                }
            }
        }
        let Bcommond = function (recevier) {
            return{
                execute () {
                    recevier.fn2()
                }
            }
        }
        let acommond = new Acommond(func);
        let bcommond = new Bcommond(func);
        const  setCommand= function (bt,commond) {
            bt.onclick= function () {
                commond.execute();
            }
        }
        setCommand(bt1,acommond);
        setCommand(bt2,bcommond);
    
    
    
    </script>
    </html>
    View Code

    2文艺青年版(+撤销功能)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <button id="moveBtn">移动</button>
        <button id="cancelBtn">撤销</button>
        <input type="text" id="pos">
        <div id="ball" style="position:absolute;background:#000;50px;height:50px"></div>
    </body>
    
    <script src="animate.js"></script>
    <script>
        const ball = document.getElementById( 'ball' );
        const pos = document.getElementById( 'pos' );
        const moveBtn = document.getElementById( 'moveBtn' );
        const cancelBtn = document.getElementById( 'cancelBtn' );
    
    
        /*moveBtn.onclick = function(){
            var animate = new Animate( ball );
            animate.start( 'left', pos.value, 1000, 'strongEaseOut' );
        };*/
    
        const  setCommand= function (tar,commond) {
            tar.onclick= function () {
                commond.execute();
            }
        }
    
    
        const MoveCommand = function( receiver, pos ){
            this.receiver = receiver;
            this.pos = pos;
            this.oldpos = null;
        };
        MoveCommand.prototype.execute = function(){
            //let that  = this;
            this.receiver.start( 'left', this.pos, 1000, 'strongEaseOut' );
            this.oldPos = this.receiver.dom.getBoundingClientRect()[ this.receiver.propertyName ];
        };
    
        MoveCommand.prototype.undo = function(){
            this.receiver.start( 'left', this.oldPos, 1000, 'strongEaseOut' );
        // 回到小球移动前记录的位置
        };
    
        //setCommand(moveBtn,moveCommand);
        let moveCommand;
        moveBtn.onclick =function () {
            const animate = new Animate(ball);
            moveCommand = new MoveCommand(animate , pos.value);
            moveCommand.execute();
        }
        cancelBtn.onclick =function () {
            moveCommand.undo();
        }
    </script>
    </html>
    View Code

    3文艺青年豪华版(+回放(队列功能)模式,使用回调方式通知)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <button id="moveBtn">移动</button>
    <button id="cancelBtn">撤销</button>
    <button id="reply">播放</button>
    <input type="text" id="pos">
    <div id="ball" style="position:absolute;background:#000;50px;height:50px"></div>
    </body>
    <script src="animate.js"></script>
    <script>
        const ball = document.getElementById('ball');
        const pos = document.getElementById('pos');
        const moveBtn = document.getElementById('moveBtn');
        const cancelBtn = document.getElementById('cancelBtn');
        const replyBtn = document.getElementById('reply');
    
    
        const MoveCommand = function (receiver, pos) {
            this.receiver = receiver;
            this.pos = pos;
            this.oldpos = null;
        };
        MoveCommand.prototype.execute = function (cb) {
            //let that  = this;
            this.receiver.start('left', this.pos, 1000, 'strongEaseOut', cb);
            this.oldPos = this.receiver.dom.getBoundingClientRect()[this.receiver.propertyName];
        };
    
        let commandStack = []; // 保存命令的堆栈
    
        MoveCommand.prototype.undo = function () {
            this.receiver.start('left', this.oldPos, 1000, 'strongEaseOut');
            // 回到小球移动前记录的位置
        };
    
    
        let moveCommand;
        moveBtn.onclick = function () {
            const animate = new Animate(ball);
            moveCommand = new MoveCommand(animate, pos.value);
            moveCommand.execute();
            commandStack.push(moveCommand);
            //console.log(commandStack);
        }
        cancelBtn.onclick = function () {
            moveCommand.undo();
        }
    
        //目前作为演示 只是做了三个函数回放的演示
        replyBtn.onclick = function () {
            let commond;
            commond = commandStack.shift();
            commond.execute(function () {
                commond = commandStack.shift();
                commond.execute(function () {
                    commond = commandStack.shift();
                    commond.execute(function () {
    
                    })
                })
            });
        }
    </script>
    </html>
    View Code

    4文艺青年豪华加长版(+回放(队列功能)模式,使用广播方式通知)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <button id="moveBtn">移动</button>
    <button id="cancelBtn">撤销</button>
    <button id="reply">播放</button>
    <input type="text" id="pos">
    <div id="ball" style="position:absolute;background:#000;50px;height:50px"></div>
    </body>
    <script src="Event.js"></script>
    <script src="animate.js"></script>
    <script>
        const ball = document.getElementById('ball');
        const pos = document.getElementById('pos');
        const moveBtn = document.getElementById('moveBtn');
        const cancelBtn = document.getElementById('cancelBtn');
        const replyBtn = document.getElementById('reply');
    
    
        const MoveCommand = function (receiver, pos) {
            this.receiver = receiver;
            this.pos = pos;
            this.oldpos = null;
        };
        MoveCommand.prototype.execute = function (cb) {
            //let that  = this;
            this.receiver.start('left', this.pos, 1000, 'strongEaseOut', cb);
            this.oldPos = this.receiver.dom.getBoundingClientRect()[this.receiver.propertyName];
        };
    
        let commandStack = []; // 保存命令的堆栈
        let historyStack = []; // 保存命令的历史堆栈
    
        MoveCommand.prototype.undo = function () {
            this.receiver.start('left', this.oldPos, 1000, 'strongEaseOut');
            // 回到小球移动前记录的位置
        };
    
    
        let moveCommand;
        moveBtn.onclick = function () {
            const animate = new Animate(ball);
            moveCommand = new MoveCommand(animate, pos.value);
    
            commandStack.push(moveCommand);
            historyStack.push(moveCommand);
        }
        cancelBtn.onclick = function () {
            moveCommand.undo();
        }
    
        replyBtn.onclick = function () {
            historyloop(historyStack);
        }
    
        /**
         *  用于时刻从命令队列里取出命令执行
         * @param Stack  命令队列
         */
        function eventloop(Stack) {
            let continued = true;
            setInterval(function () {
                if (continued) {
                    let tempcommond = Stack.shift();
                    tempcommond && tempcommond.execute();
                    tempcommond && (continued = false);
                }
    
            }, 10);
            Event.listen('finish', function () {
                continued = true;
                console.log('finish')
            })
        };
        eventloop(commandStack);
    
    
        /**
         *  用于播放历史命令队列
         * @param Stack  命令队列
         */
        function historyloop(Stack) {
            let continued = true;
            let timer = setInterval(function () {
                if (continued) {
                    let tempcommond = Stack.shift();
                    tempcommond && tempcommond.execute();
                    tempcommond && (continued = false);
                    if(!tempcommond){
                        clearInterval(timer);
                    }
                }
            }, 100);
            Event.listen('finish', function () {
                continued = true;
                console.log('finish')
            })
        }
    </script>
    </html>
    View Code
  • 相关阅读:
    ZXing 生成、解析二维码图片的小示例
    OpenLDAP 2.4.x源码安装配置
    Elasticsearch & Kibana with Shield
    Kibana SSL
    Kibana 官方示例
    ELK 处理分析日志(nginx,syslog)
    Elasticsearch 负载均衡集群
    Elasticsearch REST API小记
    ELK 安装配置
    ELK 安装配置
  • 原文地址:https://www.cnblogs.com/WhiteHorseIsNotHorse/p/6780482.html
Copyright © 2011-2022 走看看