命令模式
var button1 = document.getElementById("button1"); var button2 = document.getElementById("button2"); var button3 = document.getElementById("button3"); var setCommand = function (button, command) { button.onclick = function () { command.execute(); }; }; var MenuBar = { refresh: function () { console.log("刷新菜单目录"); }, }; var SubMenu = { add: function () { console.log("增加子菜单"); }, del: function () { console.log("删除子菜单"); }, }; class RefreshMenuBarCommand { constructor(receiver) { this.receiver = receiver; } execute() { this.receiver.refresh(); } } class DelSubMenuCommand { constructor(receiver) { this.receiver = receiver; } execute() { console.log("删除子菜单"); } } class AddSubMenuCommand { constructor(receiver) { this.receiver = receiver; } execute() { this.receiver.add(); } } var refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar); var addSubMenuCommand = new AddSubMenuCommand(SubMenu); var delSubMenuCommand = new DelSubMenuCommand(SubMenu); setCommand(button1, refreshMenuBarCommand); setCommand(button2, addSubMenuCommand); setCommand(button3, delSubMenuCommand);
简化:
var bindClick = function( button, func ){ button.onclick = func; }; var MenuBar = { refresh: function(){ console.log( '刷新菜单界面' ); } }; var SubMenu = { add: function(){ console.log( '增加子菜单' ); }, del: function(){ console.log( '删除子菜单' ); } }; bindClick( button1, MenuBar.refresh ); bindClick( button2, SubMenu.add ); bindClick( button3, SubMenu.del );
动画的
<body> <div id="ball" style="position: absolute; background: #000; width: 50px; height: 50px;" ></div> 输入小球移动后的位置:<input id="pos" /> <button id="moveBtn">开始移动</button> <button id="cancelBtn">cancel</cancel> <script> var ball = document.getElementById("ball"); var pos = document.getElementById("pos"); var moveBtn = document.getElementById("moveBtn"); var cancelBtn = document.getElementById( 'cancelBtn' ); // moveBtn.onclick = function () { // var animate = new Animate(ball); // animate.start("left", pos.value, 1000, "strongEaseOut"); // }; var MoveCommand = function( receiver, pos ){ this.receiver = receiver; this.pos = pos; this.oldPos = null; } MoveCommand.prototype.execute = function () { this.receiver.start("left", this.pos, 1000, "strongEaseOut"); }; MoveCommand.prototype.undo = function () { this.receiver.start( 'left', this.oldPos, 1000, 'strongEaseOut' ); }; var moveCommand; moveBtn.onclick = function () { var animate = new Animate(ball); moveCommand = new MoveCommand(animate, pos.value); moveCommand.execute(); }; cancelBtn.onclick = function () { if(moveCommand){ moveCommand.undo(); } }; // 类 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 ) { 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); } }, 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"; };
另外一个案例
<button id="replay">播放录像</button> <script> var Ryu = { attack: function () { console.log("攻击"); }, defense: function () { console.log("防御"); }, jump: function () { console.log("跳跃"); }, crouch: function () { console.log("蹲下"); }, }; var makeCommand = function (receiver, state) { // 创建命令 return function () { receiver[state](); }; }; var commands = { "119": "jump", // W "115": "crouch", // S "97": "defense", // A "100": "attack", // D }; var commandStack = []; // 保存命令的堆栈 document.onkeypress = function (ev) { var keyCode = ev.keyCode, command = makeCommand(Ryu, commands[keyCode]); if (command) { command(); // 执行命令 commandStack.push(command); // 将刚刚执行过的命令保存进堆栈 } }; document.getElementById("replay").onclick = function () { // 点击播放录像 var command; while ((command = commandStack.shift())) { // 从堆栈里依次取出命令并执行 command(); } };