封装形变类例子

来源: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回答

好帮手慕星星

2019-10-21

同学你好,

后面理解的是对的:translate方法调用了一次,switch匹配执行一遍,再调用scale方法,switch匹配执行一遍,以此类推。

因为调用translate等方法的时候,将动画放进了数组中:

http://img.mukewang.com/climg/5dad0d16090b404e00000000.jpg

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

http://img.mukewang.com/climg/5dad0da709d930e207590853.jpg

定时器控制着每个动画的匹配执行。

自己可以再理解下,祝学习愉快!

0

好帮手慕星星

2019-10-20

同学你好,

http://img.mukewang.com/climg/5dabd02f09a9722a06210054.jpg

理解的是有问题的,switch匹配只会执行一遍,和for循环不一样,不会遍历的。

并且Switch case 使用严格比较(===),值必须与要匹配的类型相同。所以传入的不能是数组,数组是引用类型,两个内容一样的数组是不相等的:

http://img.mukewang.com/climg/5dabd15a09b369d801680059.jpg

指向不同的地址,所以不相等。其他引用类型也是如此。

自己可以测试理解下,祝学习愉快!


0
heixin_慕的地5241954
h 那switch匹配只会执行一遍,case 'translate': _tsf.translate = `translate(${value})`; break;跳出循环,后面的scale怎么匹配到呢?不是要执行第二次吗?还是说translate方法调用了一次,switch匹配执行一遍,再调用scale方法,switch匹配执行一遍,以此类推?
h019-10-21
共1条回复

好帮手慕码

2019-10-19

同学你好!
1.注释大致是正确的。

2.关于${},这个叫占位符字符串,例如:

http://img.mukewang.com/climg/5daa774c09edd6a902960078.jpg

打印结果:

http://img.mukewang.com/climg/5daa7757098952ac01720046.jpg

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

http://img.mukewang.com/climg/5daa78de09a19e9d02040210.jpg

break的作用:跳出当前循环后,会继续执行该循环之后的代码。例如如下代码:

这是在有break的情况下,当我输入3:

http://img.mukewang.com/climg/5daa79530981f3ea03550338.jpg

http://img.mukewang.com/climg/5daa797f099de0c400910084.jpg

打印结果:

http://img.mukewang.com/climg/5daa7984092e82e901320064.jpg

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

http://img.mukewang.com/climg/5daa79b4091abe6903200323.jpg

http://img.mukewang.com/climg/5daa79bb09d26bba00960085.jpg

打印结果:

http://img.mukewang.com/climg/5daa79cb09166f9402220213.jpg

结论:如果有break,从匹配项开始往下依次执行,直到遇见break跳出switch;没有break则从匹配项开始往下全部执行;

如果帮到了你,欢迎采纳,祝学习愉快~

0
heixin_慕的地5241954
h 明白了,那这个switch语句性能很差啊,像案例中的例子,比如我要传一个数组[1,2,3,4,5],那匹配到1,跳出,又要对2执行第二次判断,以此类推,对吗?
h019-10-19
共1条回复

0 学习 · 10739 问题

查看课程