南无月 发表于 2024-7-29 09:27
多回几贴帮翻 页
{:4_190:}
<style>
.artbox { position: relative; }
.artbox > p { position: relative; margin: 10px 0; font: normal 18px / 26px sans-serif; }
.artbox mark { color: black; background: lightblue; padding: 2px 4px; }
.textRed { color: red; }
</style>
<div class="artbox">
<h2 class="textMid">第八讲:联动控制函数如何管理众多子元素的动态变化</h2>
<p>第七讲我们在JS代码中创建了一个联动控制函数 mState(),它能有效管理拥有id标识的子元素,使这些子元素的变化能与音频的播放&暂停同步。我们知道,同一个页面元素的id好比人的身份证,是唯一的,当需要控制的子元素非常多,我们一一给它们标注id然后去控制它们会很繁琐、代码也会很冗长。为此,我们需要更好的途径来处理这个问题,这里假设我们的帖子用到两个视频、两张图片做播放器、三张图片做飞鹰,HTML代码如下:</p>
<div class="hE"><pre>
<!-- html 代码 -->
<div id="mydiv">
<video class="vid" src="视频地址1" autoplay loop muted></vid>
<video class="vid" src="视频地址1" autoplay loop muted></vid>
<img class="player" src="图片地址1" alt="" />
<img class="player" src="图片地址2" alt="" />
<img class="bird" src="图片地址3" alt="" />
<img class="bird" src="图片地址5" alt="" />
<img class="bird" src="图片地址4" alt="" />
</div>
</pre></div>
<p>视频与图片标签都是用了class替代了id,共有三类,vid、player、bird,它们对标的CSS选择器大概如下:</p>
<div class="hE"><pre>
/* CSS类选择器 */
.vid {
/* 视频类选择器代码略 */
}
.player {
/* 播放器类选择器代码略 */
}
.bird {
/* 飞鹰类选择器代码略 */
}
</pre></div>
<p>CSS代码可能还会更多一些,比如使用伪类选择器 <mark>:nth-of-type(序号)</mark> 来额外定义个别元素的具体样式如位置、大小等。这不是我们控制众多子元素的重点,重头戏是JS如何拿到它们的操作标识并管控它们。JS有能力拿到任意一个页面中的元素,它内置了很多这类方法,我个人最喜欢的是 <mark>querySelectorAll(<span class="textRed">参数</span>)</mark> 方法,它可以基于 document(文档),也可以基于元素(比如子元素的父元素),<span class="textRed">参数</span> 则可以使用CSS类选择器的完整名称(如 <span class="textRed">.bird</span>)。例如,针对前面的HTML代码,帖子容器元素 id="mydiv",那么我们可以基于 mydiv 分别查询并拿到到 class="vid/player/bird" 之类的子元素的操作标识:</p>
<div class="hE"><pre>
//JS代码 :拿到拥有 class 属性的子元素的操作标识
var vids = mydiv.querySelectorAll('.vid');
var players = mydiv.querySelectorAll('.player');
var birds = mydiv.querySelectorAll('.bird');
<pre></div>
<p><span class="textRed">var</span> 是 JS 的声明关键字,<mark>var vids</mark> 声明一个变量 <span class="textRed">vids</span>,vids 是我们定义的名字,用复数形式表示这是多个元素的集合,等号后面是给声明的变量 vids 赋值,取值方法是用基于父元素 <span class="textRed">mydiv</span> 的 <mark>querySelectorAll()</mark> 方法,参数是完整的元素对标的CSS选择器 <mark>.vid</mark>,因为这是一个字符串所以用引号包裹起来。其余两个声明与赋值道理与此同,无需赘述。</p>
<p>这样,以视频为例,vids 就是我们操纵所有视频子元素的依据。vids 是视频元素的集合,是多个的,它实际上是一个对象数组,数组就是一类东西的集合,我们要对这个集合进行操作,在JS里拥有多种方法,这里介绍最简洁的 <mark>数组.forEach()</mark> 方法,forEach() 说的是里面的每一个的意思:</p>
<div class="hE"><pre>
vids.forEach( vid => aud.paused ? vid.pause() : vid.play() );
</pre></div>
<p><mark>vids.forEach( vid => ... )</mark> 意思是,数组 vids(视频集合)里面的每一个 vid(视频个体)要咋样咋样,其中,vid 是我们自己命名的名称,该名称代表将要处理的元素个体标识。接着,我们用箭头函数符号 <mark>=></mark> 引出函数体,因为是单行所以不要花括号。函数体内容我们应该已经熟悉了,意思是,问:音频是不是处于暂停状态中?答,是的话,vid.pause(),意思是 vid 也暂停;不是的话,vid.play(),意思是,vid 播放。其他两个数组 players 和 birds 也是采用类似的处理方法,不同的是,要使用 setProperty() 方法动态设置CSS关键帧动画动画的运行与暂停状态,后面提供的实例代码会看到。</p>
<p>下面给一个帖子实例代码,按前面的预设,有两个播放器、两个视频、三只飞鹰,这些元素都在帖子中得到同步管控。代码可以在线运行。领会代码时,请特别留意一下伪类选择器 <mark>:nth-of-type</mark> 与相应HTML标签出现顺序的关系,它是基于 HTML 标签而非 CSS选择器:</p>
<div class="hE" id="hE3"><pre>
<!-- 第一部分 :css代码 -->
<style>
/* 帖子容器id选择器 */
#mydiv {
position: relative;
margin: 20px auto;
width: 800px;
height: 450px;
background: url('https://638183.freep.cn/638183/t22/webp/jyiu.webp') no-repeat center/cover;
overflow: hidden;
}
/* 小播class选择器 */
.player {
position: absolute;
bottom: 40px;
width: 120px;
height: 120px;
opacity: .7;
cursor: pointer;
animation: rot 8s linear infinite var(--state);
}
.player:nth-of-type(4) { left: 40px; } /* 对标的 img 标签排在帖子中第4位 */
.player:nth-of-type(5) { right: 40px; } /* 对标的 img 标签排在帖子中第5位 */
/* 飞鹰class选择器 */
.bird {
position: absolute;
left: -100px;
top: 10px;
animation: fly 6s linear infinite var(--state);
}
.bird:nth-of-type(2) { animation-delay: -2s; } /* 对标的 img 标签排在帖子中第2位 :提前2秒执行动画 */
.bird:nth-of-type(3) { animation-delay: -4s; } /* 对标的 img 标签排在帖子中第3位 :提前4秒执行动画 */
/* 视频class选择器 */
.vid {
position: absolute;
bottom: 0;
width: 200px;
height: 200px;
object-fit: cover;
border-radius: 50%;
pointer-events: none;
opacity: 1;
mix-blend-mode: screen;
}
.vid:nth-of-type(1) { left: 0; } /* 对标的 video 标签排在帖子中第1位 */
.vid:nth-of-type(2) { right: 0; } /* 对标的 video 标签排在帖子中第2位 */
@keyframes rot { to { transform: rotate(360deg); } }
@keyframes fly { to { left: 800px; } }
</style>
<!-- 第二部分 :html代码 父元素带8个子元素 -->
<div id="mydiv">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1844994989" autoplay loop></audio>
<video class="vid" src="https://img.tukuppt.com/video_show/2418175/00/02/20/5b51f631b0f2d.mp4" autoplay loop muted></video>
<video class="vid" src="https://img.tukuppt.com/video_show/2418175/00/02/20/5b51f631b0f2d.mp4" autoplay loop muted></video>
<img class="bird" alt="" src="https://638183.freep.cn/638183/t22/gif/ying1.gif" />
<img class="bird" alt="" src="https://638183.freep.cn/638183/t22/gif/ying1.gif" />
<img class="bird" alt="" src="https://638183.freep.cn/638183/t22/gif/ying1.gif" />
<img class="player" alt="" src="https://638183.freep.cn/638183/small/4yc.png" title="播放/暂停" />
<img class="player" alt="" src="https://638183.freep.cn/638183/small/4yc.png" title="播放/暂停" />
</div>
<!-- 第三部分 :JS代码 -->
<script>
//声明并获取待控制的元素集合变量 : vids 视频、players 小播、birds 飞鹰
var vids = mydiv.querySelectorAll('.vid'),
players = mydiv.querySelectorAll('.player'),
birds = mydiv.querySelectorAll('.bird');
//联动控制函数
var mState = () => {
mydiv.style.setProperty('--state', aud.paused ? 'paused' : 'running');
vids.forEach(vid => aud.paused ? vid.pause() : vid.play());
players.forEach(player => player.title = aud.paused ? '播放' : '暂停');
};
//audio空间三个监听事件
aud.oncanplay = aud.onplaying = aud.onpause = () => mState();
//小播点击事件
players.forEach(player => player.onclick = () => aud.paused ? aud.play() : aud.pause());
</script>
</pre></div>
<p><button id="btnRun3" type="button" value="btn3">点击这里运行代码</button></p>
<div id="mystage3"></div>
<p>帖子内容增多多代码量自然跟着增多,不过只要弄清代码结构、逻辑关系,理解起来不是太难的事情。帖子代码中出现的新知识点均有注释,应花点时间理解消化。帖子实例已属于复杂构成的帖子,但还不算特别复杂,试着想一想:如果需要添加成百上千的子元素,我们也得这样写CSS和HTML代码吗?</p>
<p><a href="https://www.huachaowang.com/forum.php?mod=viewthread&tid=77307&extra=page%3D1">返回目录</a></p>
</div>
<script>
var sc = document.createElement('script');
sc.chartset = 'utf-8';
sc.src = 'https://638183.freep.cn/638183/web/js2024/helight.js';
document.body.appendChild(sc);
var runCodes = (str,ele) => {
let reg = /(<script(.*?)>)(.|\n)*?(<\/script>)/g;
let js_str, html_str;
if(str.match(reg) !== null) {
js_str = str.match(reg);
html_str = str.replace(js_str, '').trim();
js_str = js_str.replace(/<[\/]{0,1}script[^>]*>/g,'').trim();
} else {
js_str = '';
html_str = str.trim();
}
ele.innerHTML = html_str;
let myfunc = new Function(js_str);
myfunc();
};
var codes = hE3.querySelector('pre').innerText;
btnRun3.onclick = () => {
runCodes(codes, mystage3);
btnRun3.disabled = true;
};
</script>
马黑黑 发表于 2024-7-28 22:53
这么厉害
是黑黑厉害,写了这么多讲义呢{:4_187:}
马黑黑 发表于 2024-7-28 22:54
温故而知新的感觉,这个帖子真好{:4_187:}
马黑黑 发表于 2024-7-29 13:43
.artbox { position: relative; }
.artbox > p { position: relative; margin: 10px 0; font: normal 18 ...
使用伪类选择器都需要class替代了id么?
“如果需要添加成百上千的子元素,我们也得这样写CSS和HTML代码吗?”
我觉得是直接用js给算出来了{:4_173:}
马黑黑 发表于 2024-7-29 13:43
.artbox { position: relative; }
.artbox > p { position: relative; margin: 10px 0; font: normal 18 ...
这个例子有意思,小播和视频位置是重叠的,让小播更漂亮了。而且不影响小播的点击。
竹溪 发表于 2024-7-29 09:38
小白来占位学习
竹溪跟着一起做着玩啊{:4_187:}
南无月 发表于 2024-7-29 09:27
多回几贴帮翻 页
谢谢月儿{:4_187:}
红影 发表于 2024-7-29 20:05
使用伪类选择器都需要class替代了id么?
伪类选择器中,:nth-of-type(N) 通常指同一类HTML标签(如 img, p, span)在一定层级范围内的顺序,所以并不在乎 class、id选择器,我们用class选择器是限定了范围:是img标签,同时class=“啥啥"
红影 发表于 2024-7-29 20:07
“如果需要添加成百上千的子元素,我们也得这样写CSS和HTML代码吗?”
我觉得是直接用js给算出来了{:4_173 ...
是酱紫的,批量生产
红影 发表于 2024-7-29 19:46
是黑黑厉害,写了这么多讲义呢
这些是举手之劳而已
红影 发表于 2024-7-29 20:17
竹溪跟着一起做着玩啊
热情不高呢,估计和基础还是有一定关系的
红影 发表于 2024-7-29 19:46
温故而知新的感觉,这个帖子真好
{:4_190:}
红影 发表于 2024-7-29 20:17
这个例子有意思,小播和视频位置是重叠的,让小播更漂亮了。而且不影响小播的点击。
视频总体上相对霸道。必须设置好 position,然后HTML代码顺序里面,视频写在前,img写在后。也可以用 z-index 提升 img 的层级。
马黑黑 发表于 2024-7-29 20:40
伪类选择器中,:nth-of-type(N) 通常指同一类HTML标签(如 img, p, span)在一定层级范围内的顺序,所以 ...
哦哦,id选择器也可以啊,这就好。
马黑黑 发表于 2024-7-29 20:41
是酱紫的,批量生产
批量生产的东东厉害,想要多少有多少。{:4_173:}
马黑黑 发表于 2024-7-29 20:42
热情不高呢,估计和基础还是有一定关系的
多理解就好,毕竟每个人的兴趣不一样的。
马黑黑 发表于 2024-7-29 20:43
谢大咖{:4_187:}
马黑黑 发表于 2024-7-29 20:44
视频总体上相对霸道。必须设置好 position,然后HTML代码顺序里面,视频写在前,img写在后。也可以用 z-i ...
嗯,想到是这样原因,写在前就自动在下,不需要z-index了。