马黑黑 发表于 2023-7-5 22:54

用JS类封装粒子特效(一)

JavaScript的类,即 class,是特殊的函数,它基于对象,是面向对象的抽象封装。封装的内容有对象的属性与方法等。比如粒子,它有大小、形状、颜色,这些是属性,还有粒子的生成、粒子的运动,这些是方法。现在,我们就开始用 JS 的 class 来封装粒子,封装前,有必要了解 JS class 的语句结构与规范:

class Lizi {
        //...相关代码
}

class 关键字用于创建一个对象,这里我们创建了一个名为 Lizi 的对象。请注意,所创建的类的名称,要求首字母大写。

类可以有很多参数,用以描述对象的属性等。参数由 constructor 关键字创建,术语称为构造函数:

class Lizi {
        constructor(pa,size) {
                this.pa = pa;
                this.size = size;
        }
        //...相关代码
}

上面的代码,构造函数 constructor 构建了一个带两个参数的函数,pa 参数是本系列讲义要创建的粒子的宿主,即粒子赖以生存的父元素;size 是粒子的尺寸(我们的粒子宽高一致)。constructor构造函数里的代码,this.pa = pa,this 是 JS 关键字,这里指 Lizi 这个对象,this.pa 说的是 Lizi 这个对象 的 pa 属性,它等于参数 pa 传递过来的值,例如 id="mydiv" 的 mydiv 就是;this.size = size 同理,说的是 Lizi 对象的尺寸等于构造函数接收到的参数 size 的值,例如 20。

this.xx = xx 属于抽象封装属性,class 的 constructor 函数里,也可以具象封装所需属性,并且还可以借此扩展不需要传递但也可以传递的参数。试看:

class Lizi {
        constructor(pa,size = 20) {
                this.pa = pa;
                this.size = size;
                this.bg = 'purple';
                this.left = 10;
                this.top = 10;
        }
        //...相关代码
}

上例的代码是前例代码的升级,这里,constructor 构造函数里的 size 参数我们给它赋值了,size = 20,这意味着这个 size 参数有缺省值,调用 Lizi 对象实例若没有传递此参数,则默认粒子的大小为 20;此外,我们扩展了其他几个属性,其中,this.bg 用于设置粒子的颜色(背景色),它是具象的,其值为 purple(紫色),其他的属性也能容易看出其作用。

一般而言,类可以拥有无限多的参数,但是,好习惯是尽可能减少 constructor() 小括号里的参数,其余参数可以用扩展方式给出,为确保扩展的参数在类被实例化调用时参数缺失的情况下也能正常工作,聪明的做法是具象化这些扩展参数,即给它赋值。

参数即为类的属性。下面讲讲类的方法。看下面代码:

class Lizi {
        constructor(pa,size = 20) {
                this.pa = pa;
                this.size = size;
                this.bg = 'purple';
                this.left = 10;
                this.top = 10;
                this.ele = document.createElement('li-zi');
        }
        creating() {
                this.ele.style.cssText = `
                        width: ${this.size}px;
                        height: ${this.size}px;
                        left: ${this.left}px;
                        top: ${this.top}px;
                        background: ${this.bg};
                `;
                this.pa.appendChild(this.ele);
        }
}

上面的代码,构造函数里,我们扩展了一个属性 this.ele,它的值的意思是创建粒子标签(li-zi为自定义HTML标签)。我们还设计了一个方法,creating 是自定义名称,创造的意思,其作用是,粒子的宿主 this.pa 追加 this.ele 即 li-zi 元素,追加前我们设置了粒子的宽度、高度、左边值、上边值与背景颜色。

至此,Lizi 这个类的封装已经完成,它有若干个属性(pa,size,bg,ele),有一个 creating 方法。

最后,实例化调用这个 Lizi 类,粒子就可以生成——当然,它现在还不是粒子,而是一个矩形。实例化调用JS定义的类,要用 new 关键字:

let lz = new Lizi(mydiv,100);
lz.creating();

lz 是我们定义的变量,它的值是 new Lizi(papa,100),表达的是创建一个新的 Lizi 实例,参数一为 mydiv(即 id="mydiv")的元素,参数二是粒子尺寸,不设置的话就用 Lizi 类里定义的 20,我们这里定义为 100。

lz创建实例化之后,就可以使用 Lizi 类里封装的方法 creating() ,lz.creating() 就是做这个事。

效果请看下楼,完整代码请查看三楼。

南无月 发表于 2023-7-6 08:07

本帖最后由 南无月 于 2023-7-6 08:46 编辑

第一遍,先认几个函数单词,有个模糊的认识。。{:4_173:}

马黑黑 发表于 2023-7-5 22:54

本帖最后由 马黑黑 于 2023-7-5 22:56 编辑 <br /><br /><style>
#mydiv {
        marin: 20px auto;
        width: 600px;
        height: 300px;
        border: 1px solid purple;
        position: relative;
}
li-zi {
        position: absolute;
}
</style>

<p>效果:<br><br></p>
<div id="mydiv"></div>

<script>

class Lizi {
        constructor(pa,size = 20) {
                this.pa = pa;
                this.size = size;
                this.bg = 'purple';
                this.left = 10;
                this.top = 10;
                this.ele = document.createElement('li-zi');
        }
        creating() {
                this.ele.style.cssText = `
                        width: ${this.size}px;
                        height: ${this.size}px;
                        left: ${this.left}px;
                        top: ${this.top}px;
                        background: ${this.bg};
                `;
                this.pa.appendChild(this.ele);
        }
}

let lz = new Lizi(mydiv,100);
lz.creating();

</script>

马黑黑 发表于 2023-7-5 22:55

本帖最后由 马黑黑 于 2023-7-5 22:56 编辑

二楼代码<style>
#mydiv {
        marin: 20px auto;
        width: 600px;
        height: 300px;
        border: 1px solid purple;
        position: relative;
}
li-zi {
        position: absolute;
}
</style>

<div id="mydiv"></div>

<script>

class Lizi {
        constructor(pa,size = 20) {
                this.pa = pa;
                this.size = size;
                this.bg = 'purple';
                this.left = 10;
                this.top = 10;
                this.ele = document.createElement('li-zi');
        }
        creating() {
                this.ele.style.cssText = `
                        width: ${this.size}px;
                        height: ${this.size}px;
                        left: ${this.left}px;
                        top: ${this.top}px;
                        background: ${this.bg};
                `;
                this.pa.appendChild(this.ele);
        }
}

let lz = new Lizi(mydiv,100);
lz.creating();

</script>

马黑黑 发表于 2023-7-5 22:55

本帖最后由 马黑黑 于 2023-7-6 07:37 编辑

二楼代码,关于CSS,需要说明的是:

① 父元素选择器,#mydiv 要设置 position属性,可以是 relative,也可以根据需要是其他的定位方式。同时,该选择器应设置宽高尺寸;

② li-zi 选择器基于 JS 创建的 Lizi 类,position 属性设置为绝对定位。本选择器可以不用再CSS中设置,如果不设置,则需要在 JS 类里的 creating() 函数里加入绝对定位属性。

樵歌 发表于 2023-7-6 06:37

就是这个紫色小正方形,可变化 万千是吗,等瞅南无月高足表演{:4_189:}

马黑黑 发表于 2023-7-6 07:45

樵歌 发表于 2023-7-6 06:37
就是这个紫色小正方形,可变化 万千是吗,等瞅南无月高足表演

现在它还没有变化,这个正方形,仅是通过类生产了出来。这个讲义要一步一步来,希望不是难以理解和接受。

或许这是保姆式的教程,但它涉及的知识是高深、抽象的,也是属于JS里的高端应用的知识范畴。若能消化我这个教程,即便此前没有什么JS基础,也将能在消化过程中对JS的认识与理解有所提升。

南无月 发表于 2023-7-6 08:28

本帖最后由 南无月 于 2023-7-6 08:45 编辑

刚才想了想,你的上一个贴子,是先演示怎么写一群散装粒子。。
这个贴子是演示如何造个盒子
下一个贴子是不是该 演示如何把散装粒子装入盒子。。

这样以后看到封装好的东东就不会懵了。。。

南无月 发表于 2023-7-6 08:35

马黑黑 发表于 2023-7-6 07:45
现在它还没有变化,这个正方形,仅是通过类生产了出来。这个讲义要一步一步来,希望不是难以理解和接受。 ...

一步一步来慢慢学,反正近期有的是时间{:4_170:}

红影 发表于 2023-7-6 10:49

到底哪些必须是 constructor() 小括号里的参数呢?
扩展方式给出的参数还有多少?比如opacity: ,border-radius: 等可以作为扩展参数么?

红影 发表于 2023-7-6 11:10

感觉这个类很麻烦的,好像要来回折腾,暂时还没感受到这样折腾的好处:)
要先建立构造函数,还要弄个标签,这个标签里追加宿主的设置。
调用的时候只要创建这个类的新实例并把构造函数 constructor括号里的参数换成需要的参数就行了吧。

两个地方没看明白css里的li-zi { position: absolute; }有什么用,必须有这个标签么?
Lizi(mydiv,100);是和constructor(pa,size)对应的么?

樵歌 发表于 2023-7-6 12:23

马黑黑 发表于 2023-7-6 07:45
现在它还没有变化,这个正方形,仅是通过类生产了出来。这个讲义要一步一步来,希望不是难以理解和接受。 ...

我我我是牛哈{:4_170:}

马黑黑 发表于 2023-7-6 12:26

红影 发表于 2023-7-6 11:10
感觉这个类很麻烦的,好像要来回折腾,暂时还没感受到这样折腾的好处:)
要先建立构造函数,还要弄个标签 ...
为什么用类:首先,用类将来容易扩展对象的属性和方法,一切在在类里,想加加想减减;其次,类赋予对象属性和方法,可以语义化命名,一目了然,比如说,this.top 这个类的属性,一看就知道它是用来记录上边值的,而用数组记录,一般是酱紫,[], ], ... ],不直观,直观的维护与修改容易,不直观的麻烦;第三,类的语句组织简单明了,结构是固定的,就那么几个规范,定义什么类都酱紫,而实例化类的对象可以有更多的作为,自由度极高,这些,学会了没什么麻烦。

为什么有 li-zi 标签:这是自定义标签,我再说明里说过,可以不用再CSS中定义,看情况而定。这个粒子标签,必须绝对定位,否则它在宿主标签中的表现就难以控制。换言之,li-zi 是一个和 div 一样的标签,作为子元素,它需要在父元素的约束下布排。这个道理应该能明白。

实例化类的对象:使用 new 创建实例化类的对象,lz = new Lizi(mydiv, 100); 语句中,对应构造函数 constructor() 小括号里的参数,不过,该构造函数 size 设定为 size = 20,表明它有默认值,如果不想改变这个默认值,则可以:

lz = new Lizi(mydiv);

只有 pa 这个参数,必须参数;size 参数,可选参数。

小辣椒 发表于 2023-7-6 12:42

运用类,以前在玩swf播放器的时候有玩过,主要想增加的许多效果要在类文件里面,但现在黑黑这个我还一头雾水。。。。

马黑黑 发表于 2023-7-6 12:49

小辣椒 发表于 2023-7-6 12:42
运用类,以前在玩swf播放器的时候有玩过,主要想增加的许多效果要在类文件里面,但现在黑黑这个我还一头雾 ...

道理是一样的,只是不同的语言,对类的封装方式不同而已

马黑黑 发表于 2023-7-6 12:50

樵歌 发表于 2023-7-6 12:23
我我我是牛哈

你没仰睡吧{:4_170:}

马黑黑 发表于 2023-7-6 12:51

南无月 发表于 2023-7-6 08:35
一步一步来慢慢学,反正近期有的是时间

理解并掌握,就会突飞猛进

马黑黑 发表于 2023-7-6 12:52

南无月 发表于 2023-7-6 08:28
刚才想了想,你的上一个贴子,是先演示怎么写一群散装粒子。。
这个贴子是演示如何造个盒子
下一个贴子是 ...

这个是为了一步一步演示粒子是怎么来的,而且使用的做粒子的方法也不同。

小辣椒 发表于 2023-7-6 12:53

马黑黑 发表于 2023-7-6 12:49
道理是一样的,只是不同的语言,对类的封装方式不同而已

还得学习一下的,现在都老了,记性差了{:4_170:}

马黑黑 发表于 2023-7-6 12:58

红影 发表于 2023-7-6 10:49
到底哪些必须是 constructor() 小括号里的参数呢?
扩展方式给出的参数还有多少?比如opacity: ,border-r ...
constructor() 是构造函数,除非有必要,小括号里的参数越少越好。constructor() 作为类的构造函数,它和别的函数是一样的,小括号里的参数,不带值的参数是必选参数,带值的参数是可选参数。必选参数在调用时必须给出合法的参数值,可选参数根据需要决定给不给,默认值合适的就不用给,不合适的就给。

扩展参数是类最诱人的地方,凡需要的,就加进去,这将为程序后续的进一步功能扩展有好处,不必将函数推倒重来,而是适当添加几个属性和方法即可。
页: [1] 2 3 4 5
查看完整版本: 用JS类封装粒子特效(一)