【黑师音画帖小白教程】第九讲:在帖子中添加大批量的子元素
第九讲:在帖子中添加大批量的子元素
上一讲我们留下的思考题是如何更简洁地添加成百上千的子元素。这不是一个异想天开的问题,它有实用的场景需求,例如给帖子或帖子的播放器添加粒子。本讲,我们将给播放器元素添加粒子。先看看播放器的代码和运行效果:
<style> .player { position: absolute; width: 200px; height: 200px; border: 12px solid lightblue; border-style: double dotted; border-radius: 50%; } </style> <div class="player"></div>
现在,我们要往里面安置100个 10*10 的小球充当粒子,这些粒子随机放在圈圈里面。如果使用CSS+HTML来完成,我们要写大量的 :nth-of-type(N) 和100个粒子标签,这也太多了,所以,我们改用JS来批量完成。在使用JS批量添加粒子之前,我们需要做一些简单的准备工作,设计一个小球专属的class选择器,加在 CSS代码里:
.ball { position: absolute; width: 10px; height: 10px; border-radius: 50%; }
这是基本的小球样式,有了这个JS就可以干活了:
var total = 100; //声明小球总数变量并赋值 Array.from({length: total}).forEach(b => { b = document.createElement('div'); b.className = 'ball'; b.style.cssText += ` left: ${Math.random() * 200}px; top: ${Math.random() * 200}px; background: #{Math.random().toString(16).substring(2,8)}; `; player.appendChild(b); });
解释一下上述代码:
第1行:典型的变量声明与负值,total 是我们命名的变量名。
第3和12行:这两行结构为 数组.forEach(数组元素 => { 咋样咋样 });,数组是临时构建的,使用关键字 Array.from({length: total}) 方法,Array 数组,from 来自,length 长度,total 是我们前面声明并赋值的变量,也可以直接写一个数字。遍历这个临时创建的数组,用 forEach() 方法,前面介绍过,b是自定义的名称,这里指代遍历到的每一个数组元素。然后是一组花括号,里面就是函数体具体代码,即遍历这个数组元素要做什么。
第5行:数组元素变量 b 转为一个元素变量,因为 b 本身只是指向数组元素,这个我们临时创建的数组是空的,b并没有什么实际意义,所以借用它来充当元素变量即标签变量,免得重新声明一个变量。这里,我们用 document.createElement('元素名') 方法创建一个 div 并赋值给 b 变量,b 从空数组元素摇身一变成了一个div元素。
第5行:给div元素 b 指明类名,className 类名,指向先前定义的CSS选择器 .ball,这样,所创建的div元素实际上是这样子:<div class="ball"></div>。
第6~10行:设置 b 这个div的新样式。我们使用 style.cssText 属性,将多个样式设置以添加的方式(+=)追加给具体的 b 这个 div 元素,用反引号 `` 将各行内容包裹起来。反引号的打法:英文输入状态下按键盘左上角自上而下的第二个键,就是哪儿标有~和`的那个键位。然后,分别设置新增的属性———
第7、8行:设置 left 和 top 定位置,给 b 定位。这里使用了JS随机数生成方法 Math.random() 生成一个 0~0.999... 的随机数,乘以 200 是设置 left 和 top 的范围,这样会得到 0~199.999... 之间的数值,b 元素就在这个范围内安身,这个范围以 b 的父元素做参照。反引号里的 ${...} 是一种特殊的表达方式,用来表明花括号里的内容是JS变量或计算式子。
第9行:设置背景色。这里,先生成一个随机数,然后将其变为16进制,再从16进制的长字串中截取一段文本,构成一个16进制颜色值,结果长类似酱紫,#fc33e6。
第11行:使用JS内置方法 appendChild 将已经设置好的元素 b 追加给 player 元素。appendChild 是追加孩子的意思,现在不是主张生二宝三宝四宝吗,用这个JS方法会很高效,可惜上面没人知道这个东东。
OK,酱紫,100个 class="ball" 的div元素就创建好了,并及时过继给了 id="player" 的元素做儿子(子元素)。我们来整合一下代码,感受一下一下子就能拥有100个儿子的喜悦:
<style> .player { position: absolute; width: 200px; height: 200px; border: 12px solid lightblue; border-style: double dotted; border-radius: 50%; } .ball { position: absolute; width: 10px; height: 10px; border-radius: 50%; } </style> <!-- id="player" 是JS操作标识,class="player" 是挂钩 .player选择器 --> <div id="player" class="player"></div> <script> var total = 100; Array.from({length: total}).forEach(b => { b = document.createElement('div'); b.className = 'ball'; b.style.cssText += ` left: ${Math.random() * 200}px; top: ${Math.random() * 200}px; background: #${Math.random().toString(16).substring(2,8)}; `; player.appendChild(b); }); </script>
嗯,貌似有一些粒子长外面去了。这没关系,都是自己的屋檐下,暂时不用去精准调整,我们主要是看看添加100个小球球的效果。可以根据需要添加更多,不过提示一下,过多的子元素是消耗资源的,道理非常简单:人口多了消耗的粮食也多,所以加多少自己拿捏好,300之内一般不为过。
这些追加的子元素可以是非静止状态的,我们可以让它们做CSS关键帧动画,这只需设计一个 @keyframes 关键帧动画并在对应的CSS选择器中使用animation属性调用动画即可,当然还需要在JS代码中给每一个子元素加上动画延时令其提前运行以营造错落有致的运动秩序。以下实例,我们给 id="player1" 的小播添加80个粒子,并让粒子向上飞行,飞行的同时还变化透明度以便让过程看起来不那么生硬。这次,我们使用自定义HTML标签,li-zi 来取代 div 标签,li-zi 是自命名的标签名称:
<style> #player1 { position: absolute; width: 200px; height: 200px; border: 12px solid lightgreen; border-style: dotted double solid; border-radius: 50%; } li-zi { position: absolute; width: 10px; height: 10px; border-radius: 50%; animation: fly 6s linear infinite; } @keyframes fly { 0% { transform: translateY(0); opacity: 0; } 15% { transform: translateY(-60px); opacity: 1; } 100% { transform: translateY(-240px); opacity: 0; } } </style> <!-- id="player1" 既是JS操作依据又是挂钩 #player1选择器 --> <div id="player1"></div> <script> Array.from({length: 80}).forEach(lz => { lz = document.createElement('li-zi'); lz.style.cssText += ` left: ${30 + Math.random() * 130}px; top: ${30 + Math.random() * 130}px; background: #${Math.random().toString(16).substring(2,8)}; animation-delay: -${Math.random() * 6}s; `; player1.appendChild(lz); }); </script>
效果看上去还不错。关于动画设计,除了以前提到的关键字 from 和 to 还可以使用百分比设计更细致的运动方案,大家可以细细体会,可以尝试添加更多的百分比和运动描述。
本讲主要介绍如何使用JS动态生成元素,并将生成的元素作为子元素添加到已有的容器元素中。所生成的元素使用 JS 内置的 document.createElement('元素名') 方法创建,createElement 就是创建元素的意思。创建的元素可以设置新的CSS属性样式,使用 style.cssText 逐一设置,和写CSS代码差不多,重点是它可以使用特殊的方式 ${ js代码 }带入JS代码给CSS相关属性赋值。准备就绪后,将子元素追加给父元素,使用 appendChild() 方法。JS所创建的元素可以是div、p、span等等任何一个有效的HTML标签,甚至可以使用自定义的标签。
作业:改造本讲最后的实例代码,使得小播的“口”往右开、粒子向右飞行。提示:@keyframes 关键帧动画设计中,平移转换原例使用的是 translateY,它是向上或向下平移,这取决与平移的距离是正数还是负数,正数的话在原位置基础上继续加大距离所以往下,反之,负数的话是在原位置基础上减去距离所以往上移动。水平方向的平移使用 translateX,请自行尝试使用什么样的数值去实现并分析原由。
前一篇: 【黑师音画帖小白教程】第八讲:联动控制函数如何管理众多子元素的动态变化
下一篇: 【黑师音画帖小白教程】第十讲:元素边框
评论列表 [0条]