javascript留痕的命令模式模擬


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" charset="utf-8" src="common.js"></script>
    <script type="text/javascript" charset="utf-8" src="../jquery.js"></script>
    <script>
        //基於上一個demo做一個命令歷史留痕的效果
        /**
         * N次命令:up up up left left down down
         * 把這7次命令存到命令集合裏面
         * 【up up up left left】
         * 當你點擊回退按鈕的時候 原命令集合.pop();
         * 就是從原始位置開始執行命令集合
         * 這次畫的不是圖形,畫的是數顯
         * html: lineTo 劃線
         * fillStyle: 給一個圖形填充顏色的
         * strockStyle: 給一個線去填充顏色的
         * 現在是有歷史路徑的了
         * 開始路徑的方法beginPath
         * 確定位置:moveTo  移動的位置
         * 畫線的方法(描邊:strock方法)
         * */

        //有一個命令接口 兩個方法 一個是執行命令  還有一個是回退命
        //接口中需要undo的方法,因爲現在是重畫集合的命令
        var ReversibleCommandInterface = new BH.Interface('ReversibleCommandInterface',['execute']);
        //命令對象的類  參數傳遞的是接受者(cursor)
        //把命令對象叫做調用者
        var MoveUp = function (cursor) {
            this.cursor = cursor;
        }
        MoveUp.prototype = {
            constructor:MoveUp,
            execute:function () {
                //真正的接收者調用自己的move方法(x軸,y軸)
                this.cursor.move(0,-10);
            },
        }
        var MoveDown= function (cursor) {
            this.cursor = cursor;
        }
        MoveDown.prototype = {
            constructor:MoveDown,
            execute:function () {
                //真正的接收者調用自己的move方法(x軸,y軸)
                this.cursor.move(0,10);
            },

        }
        var MoveLeft = function (cursor) {
            this.cursor = cursor;
        }
        MoveLeft.prototype = {
            constructor:MoveLeft,
            execute:function () {
                //真正的接收者調用自己的move方法(x軸,y軸)
                this.cursor.move(-10,0);
            },
        }
        var MoveRight = function (cursor) {
            this.cursor = cursor;
        }
        MoveRight.prototype = {
            constructor:MoveRight,
            execute:function () {
                //真正的接收者調用自己的move方法(x軸,y軸)
                this.cursor.move(10,0);
            },
        }
        //當前接受者(也就是操作的方法的對象)
        //Cursor
        //主要修改接受者對象
        var Cursor = function (width,height,parent) {
            //寬高代表外層div(canvas畫布)
            this.width = width;
            this.height = height;
            this.commandStack = [];
            //HTML5新特性 canvas(畫布的意義)
            //創建一個畫布,定義畫布的寬高
            this.canvas = document.createElement('canvas');
            this.canvas.width = this.width;
            this.canvas.height = this.height;
            parent.appendChild(this.canvas);
            //canvas 上下文元素(畫布的核心對象)
            this.ctx = this.canvas.getContext('2d');
            //這個是描繪線的時候用的屬性
            this.ctx.strokeStyle = 'red';//填充紅色
            this.move(0,0);
        }
        Cursor.prototype = {
            constructor:Cursor,
            //只需要把當前的對象命令放到命令集合即可
            move:function (x,y) {
               var me = this;
                this.commandStack.push(function () {
                    me.lineTo(x,y);
                });
                this.executeCommands();
            },
            lineTo:function (x,y) {
                this.position.x += x;
                this.position.y += y;
                this.ctx.lineTo(this.position.x,this.position.y);
            },
            executeCommands:function () {
                //確定當前的原始位置
                this.position = {
                    x:this.width/2,
                    y:this.height/2
                };
                //清空當前的畫布
                this.ctx.clearRect(0,0,this.width,this.height);
                //開始執行路徑的方法
                this.ctx.beginPath();
                //確定當前畫筆的位置
                this.ctx.moveTo(this.position.x , this.position.y);
                //循環遍歷commandStack,每一個元素都是一個函數,都可以執行
                for(var i=0;i<this.commandStack.length;i++){
                    this.commandStack[i]();//執行以前的命令
                }
                this.ctx.stroke();

            },
            undo:function () {
                //移除最後一次命令函數即可
              this.commandStack.pop();
                this.executeCommands();
            }
        };

        //完善一下html元素即可(四個按鈕(命令按鈕),回退按鈕)
        var CommandButton = function(label,command,parent){
            BH.Interface.ensureImplements(command,ReversibleCommandInterface);
            //實例化按鈕  並放到父元素上
            this.element = document.createElement('button');
            this.element.innerHTML = label;
            parent.appendChild(this.element);
            //添加事件
            BH.EventUtil.addHandler(this.element,'click',function () {
                command.execute();
            })
        };
        //回退按鈕
        var UndoButton = function (label , parent ,cursor) {
            this.element = document.createElement('button');
            this.element.innerHTML = label;
            parent.appendChild(this.element);
            //添加事件
            BH.EventUtil.addHandler(this.element,'click',function () {
              cursor.undo();
            })
        };
        window.onload = function () {

            var body = document.getElementsByTagName('body')[0];
            var cursor = new Cursor(400,400,body);//接受者對象實例化出來了
            //客戶創建命令
            var upCommand = new MoveUp(cursor);
            var downCommand = new MoveDown(cursor);
            var leftCommand = new MoveLeft(cursor);
            var rightCommand = new MoveRight(cursor);

            //創建按鈕
            var upButton = new CommandButton('up',upCommand,body);
            var downButton = new CommandButton('down',downCommand,body);
            var leftButton = new CommandButton('left',leftCommand,body);
            var rightButton = new CommandButton('right',rightCommand,body);
            var undoButton = new UndoButton('undo',body,cursor);
        }
    </script>
</head>
<body>
</body>
</html>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章