设计模式之<策略模式>实现缓动动画

什么是策略模式?

说到设计模式, 一般人(像我一样的新鸟们)首先想到的是单例模式!. 哇, 单例模式又是什么? ....^&^%^

假设有个需求: 有A,B,C,D四种计算方法, y(输出) = x(输入) * n, 其中A(n=2),B(n=4),C(n=6),D(n=8).

使用单例模式如下:

var obj = (function() {
  var logA = function(x) {
    console.log(x * 2);
  };
  var logB = function(x) {
    console.log(x * 4);
  };
  var logC = function(x) {
    console.log(x * 6);
  };
  var logD = function(x) {
    console.log(x * 8);
  };

  return {
    logA: logA,
    logB: logB,
    logC: logC,
    logD: logD,
  }
})();

obj.logA(2); // 4
// 这么做的话, 会保证一个类仅有一个实例, 并提供一个访问它的全局访问点.

但是问题来了, 如果我有成百上千的方法, 会特别难维护.

正式介绍策略模式

定义: 定义一系列的算法, 把它们一个个封装起来, 并且使它们可以相互替换. 不太懂?没关系, 先上代码!

var logTypes = {
  A: function(x) {
    console.log(x * 2);
  },
  B: function(x) {
    console.log(x * 4);
  },
  C: function(x) {
    console.log(x * 6);
  },
  D: function(x) {
    console.log(x * 8);
  },
};
var log = function(type, x) {
  logTypes[type](x);
};

log('A', 20); // 40

有什么区别? 就只是多了个入口, 但是我们真正内部方法会被封装起来, 使用的时候交给log函数, 它就负责托管, 负责计算的逻辑放在顶部logTypes中. 所以策略模式的关键在于托管, 一个派发器, 分发给不同的算法.(类似redux)

基于策略模式实现缓动动画

让我们优雅地让div乱飞吧!

动画方法分析

  • 各种动画运动函数, tween对象
  • 初始化目标位置和信息, Animate类(假装是个类)
  • 因为基于策略模式, 需要有一个托管入口, start函数
  • 动画是一帧一帧组成的, 所以还需要一个step函数来计算每一帧
  • 最后进行dom操作, 需要update函数

代码来了~

/**
 * @desc 定义一系列算法, 均接收4个参数
 * @param t 动画已消耗的时间
 * @param b 小球原始的位置
 * @param c 小球的目标位置
 * @param d 动画持续的总时间
 */
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;
  },
}

/**
 * @desc Animate类
 */
var Animate = function(dom) {
  this.dom = dom;
  this.startTime = 0;
  this.startPos = 0; // 运动开始时候dom初始位置
  this.endPos = 0; // 目标位置
  this.propertyName = null; // dom节点需要被改变的css属性名
  this.easing = null; // 缓动算法
  this.duration = null; // 持续时间
};

/**
 * @desc 在Animate原型上添加start方法, 启动动画
 * @param propertyName 要改变的css属性名, 如: left
 * @param endPos 小球运动的目标位置
 * @param duration 动画持续时间
 * @param easing 缓动算法
 */
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);
};

/**
 * @desc 小球运动每一帧需要做的事情
 */
Animate.prototype.step = function() {
  var t = +new Date; // 取得当前时间
  if (t >= this.startTime + this.duration) {
    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);
}
/**
 * @desc 操作dom, 改变小球位置
 */
Animate.prototype.update = function(pos) {
  this.dom.style[this.propertyName] = pos + 'px';
}

部分代码参考 <<javascript设计模式与开发实践>> 源码地址: github

原文链接:segmentfault.com

上一篇:ES6中的Set数据结构
下一篇:【开发经验】使用Wepy与Bmob新sdk快速开发小程序

相关推荐

  • 默认值选项的JavaScript设计模式?

    默认值选项的JavaScript设计模式? ...

    3 年前
  • 设计模式: 从ES5 到 TypeScript ——单例模式

    Back in 1994, a book was authored by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides th...

    1 年前
  • 设计模式(五)创建型设计模式

    经典的设计模式一共有23种,分别是创建型,结构型,行为型。 创建型有四种,分别是,单例模式,工厂模式,建造者模式,原型模式。 单例模式 定义: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    4 个月前
  • 设计模式第二弹: 不知道怎么提高代码复用性?看看这几种设计模式吧!

    本文是设计模式的第二篇文章,第一篇文章是不知道怎么封装代码?看看这几种设计模式吧!,后面还会有提高扩展性,提高代码质量的设计模式,点个关注不迷路,哈哈~ 想必大家都听说过DRY原则,其实就是Don't...

    5 个月前
  • 设计模式应用举例

    纸上得来终觉浅,学习设计模式,看了很多书,但是始终还是觉得不如直接看例子来的更加客观具体,下面主要记录了js中的几个常见的设计模式举例,供自己以后复习的时候可以直接通过例子更快更好的理解设计模式。

    2 年前
  • 设计模式之观察者模式与发布订阅模式

    学习了一段时间设计模式,当学到观察者模式和发布订阅模式的时候遇到了很大的问题,这两个模式有点类似,有点傻傻分不清楚,博客起因如此,开始对观察者和发布订阅开始了Google之旅。

    1 年前
  • 设计模式之MVC,MVVM,MVP

    M: modelV: viewC: controlerP: presenterVM: view-model mvp 是mvc的演变,在mvp里,m和v不直接再有关联,他们的交互完全通过p层来管理m...

    5 个月前
  • 设计模式之-代理模式&amp;单例模式&amp;策略模式

    代理模式 目的 当调用方不方便直接操作某个对象,又或者希望在访问对象之前或之后做某些操作时,可以使用代理模式。 使用一个代理对象作为本体对象的替身; 调用方访问代理对象,代理对象做完某些操作后,按照...

    5 个月前
  • 设计模式8---------过滤器模式

    过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。

    1 年前
  • 设计模式-用JavaScript实现单例模式

    《JavaScript设计模式与开发实践》的学习笔记 设计模式-用JavaScript实现单例模式 说明 定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    1 年前

官方社区

扫码加入 JavaScript 社区