持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
也不知道是因为坚持了跑步,还是因为和她的相遇,自己的状态🤣也愈发的更好了,就像陶立夏书中所说的--“遇见你,生命转弯,像平缓的河流奔向下未知的悬崖。”
这篇呢,是读书笔记啦,希望通过自己的理解输出,增加记忆和理解,也希望能够帮到在读文章的你。
1.策略模式:
定义:策略模式是指通过一系列算法,把他们一个个封装起来,并且使他们可以相互替换。
下面来看个例子:
很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的。绩效为S级
的年终奖可能是12倍
工资,绩效为A级
的人年终奖有3倍
工资,而绩效为B的人年终奖是2倍
工资,如何通过一段代码来计算员工的年终奖呢?
//设置各个级别的类 以及相应的级别算法
var levelS = function(){};
performanceS.prototype.calculate = function( salary ){
return salary * 4;
};
var levelA = function(){};
performanceA.prototype.calculate = function( salary ){
return salary * 3;
};
var levelB = function(){};
performanceB.prototype.calculate = function( salary ){
return salary * 2;
};
- 设置各个评级级别的类,并将相应级别的算法挂在原型上
//接下来定义奖金类Bonus:
var Bonus = function(){
this.salary = null; // 原始工资
this.strategy = null; // 绩效等级对应的策略对象
};
Bonus.prototype.setSalary = function( salary ){
this.salary = salary; // 设置员工的原始工资
};
Bonus.prototype.setStrategy = function( strategy ){
this.strategy = strategy; // 设置员工绩效等级对应的策略对象
};
Bonus.prototype.getBonus = function(){ // 取得奖金数额
return this.strategy.calculate( this.salary ); // 把计算奖金的操作委托给对应的策略对象
};
- 设置一个
Bouns
的构造函数,主要还是处理组合业务逻辑;该函数中中初始化了两个属性,salary(基础工资)
和strategy(用于后续赋值绩效评级)
// 使用
var bonus = new Bonus();
bonus.setSalary( 10000 );
bonus.setStrategy( new performanceS() ); // 设置策略对象
console.log( bonus.getBonus() ); // 输出:40000
bonus.setStrategy( new performanceA() ); // 设置策略对象
console.log( bonus.getBonus() ); // 输出:30000
- 通过构造函数实例化一个
Bouns
的实例 - 通过
setSalavy
设置基础薪资 - 通过
setStrategy
设置绩效评级 - 通过
getBonus()
来获取最后的奖金数额
通过多个评级构造函数,和奖金构造函数实现了简单的策略模式
实际上,在js
中,函数也是对象,故而上述的代码也可以简化成下面:
var strategies = {
"S": function( salary ){
return salary * 4;
},
"A": function( salary ){
return salary * 3;
},
"B": function( salary ){
return salary * 2;
}
};
var calculateBonus = function( level, salary ){
return strategies[ level ]( salary );
};
console.log( calculateBonus( 'S', 20000 ) ); // 输出:80000
console.log( calculateBonus( 'A', 10000 ) ); // 输出:30000
- 通过为
strategies
对象的不同属性,设置不同的绩效评级算法 - 通过函数另外一个函数,根据参数
level
和salary
从而得出最后的绩效工资
2.使用策略模式实现缓动动画:
JavaScript
实现动画原理:通过连续改变元素的某个CSS
属性,比如left,top,background-position
来实现动画效果。
🚀需求:希望能够编写一个动画类和一些缓动算法,让🏀以各种各样的缓动效果在页面中运动。
思路:
- 动画开始时,🏀所在的原始位置;
- 🏀移动的目标位置;
- 动画开始时间的准确时间点;
- 🏀运动持续的时间;
首先是缓动算法,这些算法都接收4
个参数:
-
t
:动画已消耗的时间 -
b
·:🏀原始位置 -
c
:🏀目标位置 -
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;
}
};
html
部分:
<body>
<div style="position:absolute;background:blue" id="div">我是div</div>
</body>
接着来看下Animate
类
Animate
初始化:
// Animate构造函数
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
开启动画的方法:propertyName
:节点需要被改变的CSS
属性名endPos
:节点目标位置duration
:动画持续时间easing
:缓动算法
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 );
};
-
这里通过
setInterval
去持续的执行setp
函数,直到动画结束为止,清理定时器。 -
Animate
动画每一帧要做的事情:
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
动画负责修改css
样式的部分:pos
为移动位置
Animate.prototype.update = function( pos ){
this.dom.style[ this.propertyName ] = pos + 'px';
};
让🏀动起来:
var div = document.getElementById( 'div' );
var animate = new Animate( div );
animate.start( 'left', 500, 1000, 'strongEaseOut' );
更多的还是要去思考,充分的思考让看到的成为理解的,才可能在实际项目中有所应用。