封装形变类例子
来源:6-4 封装形变类(4)
weixin_慕的地5241954
2019-10-19 01:03:55
class Transform {
constructor(selector) {
this.el = document.querySelector(selector);
// this.el指的是div.ball这个DOM元素,这句话的意思是每个实例化的对象上都有el这个属性,el属性是用来存储获取的DOM元素的
this._transform = {
translate: '',
scale: '',
rotate: ''
}
this.defaultTime = Transform.config.defaultTime;
this._queue = [];
this.el.style.transition = `all ${.3}s`;
}
// 总结:this.方法() 只能在类的内部调用,this指向实例化对象。
//位移
translate(value, time){
// console.log(this === tf)
// 这里的this指tf这个实例化对象
// 第一个return是把this._add方法整个返回,然后才能把this._add方法中的return this;返回,第二个return是把tf对象返回,否则translate的调用只是把函数执行了一遍,translate生效,但是scale不会生效,因为只有tf对象上有scale方法,下面同理
return this._add('translate', value, time);
}
// 缩放
scale(value, time){
return this._add('scale', value, time)
}
// 旋转
rotate(value, time){
return this._add('rotate', value, time)
}
// 添加动画
_add(type, value, time = this.defaultTime){
// console.log(this)
this._queue.push({ type, value, time })
return this;
}
// 动画准备好了,可以开始动了
done(){
this._start();
}
// 动画准备开始 从队列中把动画一个个拿出来,先进先出
_start(){
setTimeout( () =>{
if(!this._queue.length) return; //队列为空,结束动画
const info = this._queue.shift(); //取出数组第一项
// console.log(info)
// console.log(`all ${info.time/1000}s`)
this.el.style.transition = `all ${info.time/1000}s`
this.el.style.transform = this._getTransform(info);
// 接收数组第一项,执行_getTransform方法,并返回css属性
setTimeout(() =>{
this._start(); // 这里是递归操作,上一项动画执行完后执行下一步操作。
}, info.time)
}, 0)
}
_getTransform({type, value}){
const _tsf = this._transform;
switch (type) {
case 'translate':
// ${value}什么意思?
_tsf.translate = `translate(${value})`;
break;
case 'scale':
_tsf.scale = `scale(${value})`;
break;
case 'rotate':
_tsf.rotate = `rotate(${value}deg)`;
break;
}
// console.log(_tsf.translate)
return `${ _tsf.translate } ${ _tsf.scale } ${ _tsf.rotate }`;
}
}
// 静态属性,初始化用的
Transform.config = {
defaultTime: 500
}
Transform.config.defaultTime = 1000;
// 继承
class MultiTransform extends Transform {
multi(value ,time){
return this._add('multi', value, time);
}
sleep(value, time){
return this._add('sleep', value, time);
}
_getTransform({type, value}){
const _tsf = this._transform;
switch (type) {
case 'translate':
_tsf.translate = `translate(${value})`;
break;
case 'scale':
_tsf.scale = `scale(${value})`;
break;
case 'rotate':
_tsf.rotate = `rotate(${value}deg)`;
break;
case 'multi':
value.forEach(item => {
this._getTransform(item);
});
// value.forEach(function(item) {
// console.log(item)
// tf._getTransform(item);
// });这里不是箭头函数,this不能指向tf,所以只能用tf
break;
case 'sleep':
break;
}
return `${ _tsf.translate } ${ _tsf.scale } ${ _tsf.rotate }`;
}
}
const tf = new MultiTransform('.ball');
tf
.translate('100px, 100px')
.scale(2)
.sleep(null, 5000)
.rotate(180, 2000)
.multi([
{
type:'translate',
value: '0, 0'
},
{
type:'scale',
value: 1.5
}
])
.done();
// console.log(tf)1、帮我看看注释的地方对不对。
2、break的作用以及含义,我不加好像也没事,请结合代码举例说详细点,谢谢。
3回答
同学你好,
后面理解的是对的:translate方法调用了一次,switch匹配执行一遍,再调用scale方法,switch匹配执行一遍,以此类推。
因为调用translate等方法的时候,将动画放进了数组中:

最后调用done方法的时候,开始执行_start方法:

定时器控制着每个动画的匹配执行。
自己可以再理解下,祝学习愉快!
好帮手慕星星
2019-10-20
同学你好,

理解的是有问题的,switch匹配只会执行一遍,和for循环不一样,不会遍历的。
并且Switch case 使用严格比较(===),值必须与要匹配的类型相同。所以传入的不能是数组,数组是引用类型,两个内容一样的数组是不相等的:

指向不同的地址,所以不相等。其他引用类型也是如此。
自己可以测试理解下,祝学习愉快!
好帮手慕码
2019-10-19
同学你好!
1.注释大致是正确的。
2.关于${},这个叫占位符字符串,例如:

打印结果:

3.break是指switch中的break吧?需要回忆下switch的用法:switch语句用于基于不同条件执行不同动作,语法:

break的作用:跳出当前循环后,会继续执行该循环之后的代码。例如如下代码:
这是在有break的情况下,当我输入3:


打印结果:

当没有break的时候,输入1:


打印结果:

结论:如果有break,从匹配项开始往下依次执行,直到遇见break跳出switch;没有break则从匹配项开始往下全部执行;
如果帮到了你,欢迎采纳,祝学习愉快~
相似问题