马黑黑 发表于 2023-7-10 21:11

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

本帖最后由 马黑黑 于 2023-7-10 22:02 编辑

本讲,主要讲在类里使用字面量对象来设计和设置类的属性。

面向对象编程是几乎所有编程语言的编程理念。对象是一个集合,集合里面的数据,以键值对的方式存储各类信息,比方说,我们要存储 HTML 元素的 left 和 top 值,通常的做法是分开使用 left 和 top 来记录,记录的数据略显繁琐,而使用对象,left 和 top 可以整合在一个定义好的集合里,假设该集合名称为 pos(位置position的缩写) :

let pos = {x: 10, y: 10};

pos 变量以 x 作为健名记录 10 即 键值,代表 left,y 则代表 top。注意:① 集合数据写在花括号里;② 健名和键值用小角冒号分开;③ 两个键值对之间用小角逗号隔开。

字面量对象用在类的构造函数里:

class Lizi {
      constructor(pa) {
                this.pa = pa;
                this.pos = {x: 10, y: 10};
      }
}

this.pos = {x: 10, y: 10} 等同于前面的讲义中的:

this.left = 10;
this.top = 10;

换成字面量对象之后,后续的使用中,this.left 我们要写成 this.pos.x,this.top 写成 this.pos.y,希望这个不难理解。

使用对象的好处在于,当归属于某一类的集合数据有很多构成元素时,健名: 键值 的记录方式会更为直观,把它们当做一个集合来存储,数据逻辑更清晰,读写更容易。本讲,为了不复杂化,我们将尺寸、位置、步幅作为三个集合来构建类的构造函数(constructor)里的相关属性。试看:

//Lizi 类
class Lizi {
      //构造函数 : 属性设计/设置(pa - 粒子宿主元素)
      constructor(pa) {
                this.pa = pa;
                this.size = {x: 20, y: 20}; //宽高尺寸
                this.pos = {x: 10, y: 10}; //位置
                this.step = {x: 1, y: 1}; //运动步幅
                this.ele = document.createElement('li-zi');
      }
      //类的方法代码暂略
}

上面,size 对象有两个键值对,分别是 x 和 y,它们记录元素的宽高(这意味着粒子的宽高可以不一样了);pos 对象记录 left 和 top 值;step 对象记录的是水平和垂直方向的行进步幅。

下面创建类的 creating 方法,即创建粒子元素的自定义函数:

//创建粒子函数
creating() {
      this.ele.style.cssText = `
                width: ${this.size.x}px;
                height: ${this.size.y}px;
                left: ${this.pos.x}px;
                top: ${this.pos.y}px;
      `;
      this.pa.appendChild(this.ele);
}

该方法首先设定粒子的 CSS 属性:宽、高、左边和上边等值,分别使用 this.属性名.x/y 获取对应的对象值;最后粒子宿主 this.pa 追加粒子元素作为自己的子元素。

以下代码是本讲完整示例源码,纸飞机自左向右飞行,同时由于重力的作用,它们会慢慢往下坠落:

<style>
#mydiv {
      margin: 20px auto;
      width: 740px;
         height: 500px;
      background: linear-gradient(to top right,olive,black);
      overflow: hidden;
      cursor: pointer;
      position: relative;
}
li-zi {
      position: absolute;
      clip-path: polygon(0% 0%, 100% 50%, 0% 100%, 15% 50%);
}
</style>

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

<script>

//粒子运动开关
let canMove = true;

//Lizi 类
class Lizi {
      //构造函数 : 属性设计/设置(pa - 粒子宿主元素)
      constructor(pa) {
                this.pa = pa;
                this.size = {x: 20, y: 20};
                this.pos = {x: 10, y: 10}
                this.step = {x: 1, y: 1};
                this.ele = document.createElement('li-zi');
      }
      //创建粒子
      creating() {
                this.ele.style.cssText = `
                        width: ${this.size.x}px;
                        height: ${this.size.y}px;
                        left: ${this.pos.x}px;
                        top: ${this.pos.y}px;
                `;
                this.pa.appendChild(this.ele);
                this.chgColor();
                this.moving();
      }
      //移动粒子
      moving() {
                if(canMove) {
                        this.pos.x += this.step.x;
                        this.pos.y += this.step.y;
                        if(this.pos.x >= this.pa.offsetWidth) {
                              this.pos.x = -this.size.x;
                              this.chgColor();
                        }
                        if(this.pos.y >= this.pa.offsetHeight) {
                              this.pos.y = -this.size.y;
                              this.chgColor();
                        }
                        this.ele.style.left = this.pos.x + 'px';
                        this.ele.style.top = this.pos.y + 'px';
                }
                requestAnimationFrame(this.moving.bind(this));
      }
      //变换颜色
      chgColor() {
                this.ele.style.background = '#' + Math.random().toString(16).substr(-6);
      }
}

//实例化类
Array.from({length: 20}).forEach((element) => {
      element = new Lizi(mydiv);
      element.size = {
                x: 40 + Math.random() * 40,
                y: 20 + Math.random() * 30
      }
      element.pos = {
                x: Math.floor(Math.random() * (mydiv.offsetWidth - element.size.x)),
                y: Math.floor(Math.random() * (mydiv.offsetHeight - element.size.y))
      }
      element.step = {
                x: 0.5 + Math.random(),
                y: 0.2 + Math.random() * 0.2
      };
      element.creating();
});

mydiv.onclick = () => canMove = !canMove;

</script>

效果请看下楼。

马黑黑 发表于 2023-7-10 21:11

<style>
#mydiv {
        margin: 20px auto;
        width: 740px;
        height: 500px;
        background: linear-gradient(to top right,olive,black);
        overflow: hidden;
        cursor: pointer;
        position: relative;
}
li-zi {
        position: absolute;
        clip-path: polygon(0% 0%, 100% 50%, 0% 100%, 15% 50%);
}
</style>

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

<script>

//粒子运动开关
let canMove = true;

//Lizi 类
class Lizi {
        //构造函数 : 属性设计/设置(pa - 粒子宿主元素)
        constructor(pa) {
                this.pa = pa;
                this.size = {x: 20, y: 20};
                this.pos = {x: 10, y: 10}
                this.step = {x: 1, y: 1};
                this.ele = document.createElement('li-zi');
        }
        //创建粒子
        creating() {
                this.ele.style.cssText = `
                        width: ${this.size.x}px;
                        height: ${this.size.y}px;
                        left: ${this.pos.x}px;
                        top: ${this.pos.y}px;
                `;
                this.pa.appendChild(this.ele);
                this.chgColor();
                this.moving();
        }
        //移动粒子
        moving() {
                if(canMove) {
                        this.pos.x += this.step.x;
                        this.pos.y += this.step.y;
                        if(this.pos.x >= this.pa.offsetWidth) {
                                this.pos.x = -this.size.x;
                                this.chgColor();
                        }
                        if(this.pos.y >= this.pa.offsetHeight) {
                                this.pos.y = -this.size.y;
                                this.chgColor();
                        }
                        this.ele.style.left = this.pos.x + 'px';
                        this.ele.style.top = this.pos.y + 'px';
                }
                requestAnimationFrame(this.moving.bind(this));
        }
        //变换颜色
        chgColor() {
                this.ele.style.background = '#' + Math.random().toString(16).substr(-6);
        }
}

//实例化类
Array.from({length: 20}).forEach((element) => {
        element = new Lizi(mydiv);
        element.size = {
                x: 40 + Math.random() * 40,
                y: 20 + Math.random() * 30
        }
        element.pos = {
                x: Math.floor(Math.random() * (mydiv.offsetWidth - element.size.x)),
                y: Math.floor(Math.random() * (mydiv.offsetHeight - element.size.y))
        }
        element.step = {
                x: 0.5 + Math.random(),
                y: 0.2 + Math.random() * 0.2
        };
        element.creating();
});

mydiv.onclick = () => canMove = !canMove;

</script>

马黑黑 发表于 2023-7-10 21:14

本帖最后由 马黑黑 于 2023-7-10 21:17 编辑

二楼的代码再发一次:

<style>
#mydiv {
      margin: 20px auto;
      width: 740px;
         height: 500px;
      background: linear-gradient(to top right,olive,black);
      overflow: hidden;
      cursor: pointer;
      position: relative;
}
li-zi {
      position: absolute;
      clip-path: polygon(0% 0%, 100% 50%, 0% 100%, 15% 50%);
}
</style>

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

<script>

//粒子运动开关
let canMove = true;

//Lizi 类
class Lizi {
      //构造函数 : 属性设计/设置(pa - 粒子宿主元素)
      constructor(pa) {
                this.pa = pa;
                this.size = {x: 20, y: 20};
                this.pos = {x: 10, y: 10}
                this.step = {x: 1, y: 1};
                this.ele = document.createElement('li-zi');
      };
      //创建粒子
      creating() {
                this.ele.style.cssText = `
                        width: ${this.size.x}px;
                        height: ${this.size.y}px;
                        left: ${this.pos.x}px;
                        top: ${this.pos.y}px;
                `;
                this.pa.appendChild(this.ele);
                this.chgColor();
                this.moving();
      };
      //移动粒子
      moving() {
                if(canMove) {
                        this.pos.x += this.step.x;
                        this.pos.y += this.step.y;
                        if(this.pos.x >= this.pa.offsetWidth) {
                              this.pos.x = -this.size.x;
                              this.chgColor();
                        }
                        if(this.pos.y >= this.pa.offsetHeight) {
                              this.pos.y = -this.size.y;
                              this.chgColor();
                        }
                        this.ele.style.left = this.pos.x + 'px';
                        this.ele.style.top = this.pos.y + 'px';
                }
                requestAnimationFrame(this.moving.bind(this));
      };
      //变换颜色
      chgColor() {
                this.ele.style.background = '#' + Math.random().toString(16).substr(-6);
      };
}

//实例化类
Array.from({length: 20}).forEach((element) => {
      element = new Lizi(mydiv);
      element.size = {
                x: 40 + Math.random() * 40,
                y: 20 + Math.random() * 30
      };
      element.pos = {
                x: Math.floor(Math.random() * (mydiv.offsetWidth - element.size.x)),
                y: Math.floor(Math.random() * (mydiv.offsetHeight - element.size.y))
      };
      element.step = {
                x: 0.5 + Math.random(),
                y: 0.2 + Math.random() * 0.2
      };
      element.creating();
});

mydiv.onclick = () => canMove = !canMove;

</script>

红影 发表于 2023-7-10 22:19

有意思,因为尺寸的变化,这些飞机有点胖有的瘦{:4_173:}

红影 发表于 2023-7-10 22:20

属性名必须是这些个么,还是可以自己随便命名?

醉美水芙蓉 发表于 2023-7-10 22:20

小文 发表于 2023-7-10 22:23

本帖最后由 小文 于 2023-7-10 22:25 编辑

很美很美,赶明我借来弄几张歼20上去。哈哈,问好!{:4_191:}

马黑黑 发表于 2023-7-10 22:40

小文 发表于 2023-7-10 22:23
很美很美,赶明我借来弄几张歼20上去。哈哈,问好!

{:4_172:}

马黑黑 发表于 2023-7-10 22:41

红影 发表于 2023-7-10 22:19
有意思,因为尺寸的变化,这些飞机有点胖有的瘦

全是手工折叠,非工厂模式生产{:4_170:}

马黑黑 发表于 2023-7-10 22:41

醉美水芙蓉 发表于 2023-7-10 22:20
欣赏学习老师教程!

晚上好

马黑黑 发表于 2023-7-10 22:42

红影 发表于 2023-7-10 22:20
属性名必须是这些个么,还是可以自己随便命名?

自定义,语义化的就好,各人按自己的习惯命名

红影 发表于 2023-7-10 23:15

马黑黑 发表于 2023-7-10 22:41
全是手工折叠,非工厂模式生产

就是啊各式各样的,挺好看的{:4_187:}

红影 发表于 2023-7-10 23:16

马黑黑 发表于 2023-7-10 22:42
自定义,语义化的就好,各人按自己的习惯命名

太好了,就不用管这些名字了,想用什么就用什么{:4_173:}

马黑黑 发表于 2023-7-10 23:38

红影 发表于 2023-7-10 23:16
太好了,就不用管这些名字了,想用什么就用什么

除了JS、CSS、HTML规定的函数、选择器、标签以及围绕它们的东东等只能用它的,其余凡自定义的,就是随自己的心意命名,当然需要顾及自己和别人能看懂,也有一定规范的。

马黑黑 发表于 2023-7-10 23:38

红影 发表于 2023-7-10 23:15
就是啊各式各样的,挺好看的

还可以进一步加工

南无月 发表于 2023-7-11 10:16

原来这个是下雨的原理课{:4_199:}

红影 发表于 2023-7-11 16:01

马黑黑 发表于 2023-7-10 23:38
除了JS、CSS、HTML规定的函数、选择器、标签以及围绕它们的东东等只能用它的,其余凡自定义的,就是随自 ...

太好了,我只是问问它们是不是固定的,不一定去换它们{:4_173:}

红影 发表于 2023-7-11 16:05

马黑黑 发表于 2023-7-10 23:38
还可以进一步加工

这个已经很好看了。

马黑黑 发表于 2023-7-11 19:11

红影 发表于 2023-7-11 16:05
这个已经很好看了。

那就好

马黑黑 发表于 2023-7-11 19:12

红影 发表于 2023-7-11 16:01
太好了,我只是问问它们是不是固定的,不一定去换它们

变量呀,自定义函数呀,都是自己命名的
页: [1] 2 3 4 5 6 7
查看完整版本: 用JS类封装粒子特效(五)