<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; }
.textMid { text-align: center; }
.showDiv { position: relative; }
</style>
<div class="artbox">
<h2 class="textMid">第二十八讲:帖子子元素布局技巧(一)</h2>
<p>多数音画帖不能只是一张背景图,得有其他诸如文本、粒子、媒体等内容的加入。子元素在帖子中如何布局是一门技巧,在这里我们不以美学的视角去审视这个问题,而是从前端技术角度出发讲讲怎样在帖子定位子元素。</p>
<p>之前的讲义有提到过父子元素的 <span class="textRed">position</span> 属性在帖子布局子元素的作用,这里再次强调:父元素的相对定位 <mark>position: relative;</mark> 配套子元素的绝对定位 <mark>position: absolute</mark> 可以令子元素严格受到父元素的约束,如此设置之后,子元素的 <mark>left: 0;</mark> 和 <mark>top: 0;</mark> 或缺省 left/top 设置恰好能让子元素定位在父元素的左上角,top和left所设定的子元素的具体定位坐标 {0,0} 以父元素的左上角坐标 {0,0} 为参照,即二者重合。试看下面的演示代码和效果:</p>
<div class="hE"><pre id="pre1">
<style>
.papa {
width: 600px;
height: 200px;
border: 1px solid;
position: relative; /* 父元素位置属性 : 相对定位 */
}
.son {
position: absolute; /* 子元素位置属性 :绝对定位 */
padding: 10px;
width: 100px;
height: 50px;
background-color: #ffcc66;
}
</style>
<!-- HTML代码 :父元素要将子元素包裹其中 -->
<div class="papa">
<div class="son">子元素</div>
</div>
</pre></div>
<p><button id="btn1" type="button" value="1">点击查看效果</button></p>
<div id="sbox1" class="showDiv"></div>
<p>演示效果中,灰色边框的大元素是父元素,其下有一个子元素,二者都是div标签。元素的父子关系是一种包含和被包含的关系,上例HTML代码中,<mark>class="papa"</mark> 的div标签包含有一个 <mark>class="son"</mark> 的div标签,papa 为父、son 为子;子元素没有设置 left 和 top 具体定位属性,使用了缺省值 {0,0}。一个父元素可以拥有一个或多个子标签,音画帖就是利用这一点在帖子容器即父元素中安排若干个子元素,这会涉及到子元素的具体定位问题,不处理这个问题,所有的子元素都会重叠在帖子容器的左上角或像文本流一样按自左而右、自上而下的次序布排各种元素,一切取决于position的设置。看以下例子,刚打开时子元素堆叠在父元素的左上角,点击其下按钮后它们会各就各位:</p>
<div class="hE"><pre id="pre2">
<style>
#papa1 {
width: 600px;
height: 200px;
border: 1px solid;
position: relative; /* 父元素位置属性 : 相对定位 */
}
.sons {
position: absolute; /* 子元素位置属性 :绝对定位 */
padding: 10px;
width: 100px;
height: 50px;
background-color: #ffcc66;
}
</style>
<div id="papa1">
<div class="sons">子元素一</div>
<div class="sons">子元素二</div>
<div class="sons">子元素三</div>
<div class="sons">子元素四</div>
</div>
<p><button id="btnSet" type="button" value="set">戳我调整子元素位置</button>
<script>
setPos = (elms) => {
let datas = [
{ x: 20, y: 20 },
{ x: 400, y: 30 },
{ x: 90, y: 100 },
{ x: 360, y: 120 },
];
elms.forEach((elm, idx) => {
elm.style.cssText += `
left: ${datas.x}px;
top: ${datas.y}px;
`;
});
};
var elements = papa1.querySelectorAll('.sons');
btnSet.onclick = () => setPos(elements);
</script>
</script>
</pre></div>
<p><button id="btn2" type="button" value="2">点击查看效果</button></p>
<div id="sbox2" class="showDiv"></div>
<p>这个示例父子元素的position设定是 relative+absolute,在CSS代码中子元素没有使用left和top给子元素进行具体定位,它们按缺省left和top值即0定位自己,只有设置了每一个子元素的 left 和 top 属性值,或 right 和 bottom 属性值,它们才会各就各位,例中的JS代码就是做这个工作,不过只是演示,实际上,绝大多数情况下,我们应该在CSS代码中具体定位好所有子元素的具体位置。具体位置就是通过 left 或 right 定位横向位置、top 或 bottom 定位纵向位置,需要注意的是,特定元素若使用了 left 和 top 属性进行定位,则,如果将来会动态改变其位置,就一直得使用 left 和 top,不能改用 right 和 bottom;同时,一次性的定位不能四个属性都用,只能一横一纵配套使用,否则可能会出现意想不到的结果。以下例子可以拿去 <a href="http://mhh.52qingyin.cn/api/pcode/" target="_blank">pencil code</a> 或存为本地文档进行测试以查看上述描述的不可预知效果:</p>
<div class="hE"><pre>
<style>
.papa {
width: 600px;
height: 300px;
border: 1px solid;
position: relative;
}
.son {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
/* 以上四个属性等同于 inset: 0;
若设置了 width 和 height属性,则
后两个即right和bottom设置自动失效
width: 100px;
height: 50px;
*/
background-color: #ffcc66;
padding: 10px;
}
</style>
<div class="papa">
<div class="son">子元素</div>
</div>
</pre></div>
<p>当子元素不太多,建议每一个子元素建立自己的ID选择器或class选择器;若较多,可以考虑归类管理,即,同一个类属标签的子元素建立统一的class选择器,然后再使用伪类选择器来具体定义每一个子元素的其他如left、top等具体属性。举例说明如下:</p>
<div class="hE"><pre id="pre3">
<style>
#mama {
width: 600px;
height: 300px;
border: 1px solid;
position: relative;
}
#mama > img { position: absolute; width: 160px; }
.girl {
position: absolute;
width: 100px;
height: 50px;
background-color: #445566;
color: yellow;
padding: 10px;
opacity: .75;
}
.girl:nth-of-type(1) { left: 130px; top: 20px; }
.girl:nth-of-type(2) { right: 20px; top: 20px; }
.girl:nth-of-type(3) { left: calc(50% - 50px); bottom: 20px; }
</style>
<div id="mama">
<div class="girl">子元素1</div>
<img src="https://638183.freep.cn/638183/2-0.gif" alt="" />
<div class="girl">子元素2</div>
<div class="girl">子元素3</div>
</div>
</pre></div>
<p><button id="btn3" type="button" value="3">点击查看效果</button></p>
<div id="sbox3" class="showDiv"></div>
<p>仔细阅读上述代码并特别注意,mama下的所有子元素,包括img和三个div元素,都用了 <mark>position: absolute;</mark> 定位类型设置(position),这样除了能够更好地用方向属性具体定位,还存在一个层级问题。请观察演示效果图片和子元素的位置关系,它们部分重叠,图片在上层,子元素1在下层,这是为什么?原因是,两个或更多元素有位置重叠时,依据HTML代码流中谁先出现谁后出现,先出现的在下层、后出现的在上层。如果想让先出现的元素不被覆盖,可以给该元素的CSS选择器加入 z-index 属性并赋予一个合适的值,它就会在较为顶层的层级,例如可以这样:<mark>z-index: 9;</mark>。此外,注意一下代码中的伪类选择器 <mark>*:nth-of-type(n)</mark>,它可以用来具体设定特定类属的选择器(如例中的 <mark>.girl</mark> 第n个元素的其他具体属性,上例就是这样设置了 <mark>class="girl"</mark> 三个div子元素的具体位置。</p>
<p>如果子元素更多,例如做粒子特效是会用到几十甚至上百个子元素,这种情况一个一个粒子去写CSS样式就不现实了,这得用CSS+JS的方式动态生成粒子:先制定通用的粒子CSS样式,再在JS代码中动态创建元素并给出各异的样式,这个前面的讲义有提及到,这里再给一个动态生成粒子的示例,该粒子代码来源于 <a href="http://mhh.52qingyin.cn/api/pcode/tiezi/" target="_blank">《帖子在线制作》</a> 程序。</p>
<div class="hE"><pre id="pre4">
<style>
#papa2 {
margin: auto;
width: 600px;
height: 300px;
background: linear-gradient(skyblue, black);
overflow: hidden;
position: relative;
}
li-zi {
position: absolute;
width: 10px;
height: 10px;
border-radius: 50%;
background: snow;
}
/* 关键帧动画使用 --x0 和 --y0 两个变量存储translate平移的{x,y}坐标 */
@keyframes moving {
from { opacity: 0; transform: translate(0,0); }
to { opacity: 1; transform: translate(var(--x0),var(--y0)); }
}
</style>
<div id="papa2"></div>
<script>
//用for循环语句创建80个粒子
for(let i = 0, all = 80; i < all; i++) {
let lz = document.createElement('li-zi'); //创建粒子 li-zi 为自定义元素
let hudu = Math.PI / 180 * 360 / all * i; //计算弧度
let xx = 600 * Math.cos(hudu), yy = 300 * Math.sin(hudu); //计算平移目的地xy坐标值
//粒子其他各异的CSS属性
lz.style.cssText += `
--x0: ${xx}px; /* 平移目的地X坐标 */
--y0: ${yy}px; /* 平移目的地Y坐标 */
left: calc(50% - 10px); /* 粒子元素初始位置 :水平居中 */
top: calc(50% - 10px); /* 粒子元素初始位置 :垂直居中 */
/* 运行动画 :动画时长随机、延时运行加负号随机提前 */
animation: moving ${Math.random() * 20 + 20}s -${Math.random() * 20}s infinite;
`;
papa2.prepend(lz); //父元素追加粒子子元素
}
</script>
</pre></div>
<p><button id="btn4" type="button" value="4">点击查看效果</button></p>
<div id="sbox4" class="showDiv"></div>
<p>本讲是帖子子元素布局的第一讲,讲义中的示例代码量偏多,需要细细领会、尝试。本讲的<span class="textRed">作业</span>:参照最后的示例做一个帖子,帖子背景和音频以及音频控制元素(img或div都行)需要额外加入,并在JS中实现能随音频的播放、暂停进行联动控制粒子的运动。</p>
<p><a href="https://www.huachaowang.com/forum.php?mod=viewthread&tid=77307">返回目录</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();
};
.forEach((btn,key) => {
var pres = ,
outs = ;
btn.onclick = () => {
runCodes(pres.innerText, outs);
btn.disabled = true;
}
});
</script>
马黑黑 发表于 2024-9-3 18:22
本帖最后由 马黑黑 于 2024-9-3 19:49 编辑
.artbox { position: relative; }
.artbox > p { position: ...
这个二十七讲歌词的作业到是常做。。
挑一个还没跟过的老唱机
只是改了颜色,别的没有动。。配置里一直说背景可用图片。。试了几次也没成功。{:4_173:}
<style>
#mhh {
margin: 30px 0 30px calc(50% - 831px);
width: 1500px;
height: 640px;
background: url('https://pic.imgdb.cn/item/66d81253d9c307b7e9d09572.webp') no-repeat center/cover;
box-shadow: 0 0 8px rgba(0,0,0,.65);
overflow: hidden;
z-index: 1;
position: relative;
}
#mhh > video {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
mix-blend-mode: screen;
-webkit-mask: linear-gradient(to right top, red 10%, transparent 90%, transparent);
pointer-events: none;
}
</style>
<div id="mhh" class="mhh">
<audio src="https://music.163.com/song/media/outer/url?id=1471039808" autoplay loop></audio>
<video src="https://img.tukuppt.com/video_show/2418175/00/02/06/5b503d6c75c2a.mp4" autoplay loop muted></video>
</div>
<script>
var sf = document.createElement('script');
sf.charset = 'utf-8';
sf.src = 'https://638183.freep.cn/638183/web/js2024/plater_yslrc.js';
document.body.appendChild(sf);
sf.onload = () => {
HCPlayer({
papa: '#mhh',
geci: geci,
skip: 0,
average: 0,
player_css: 'left: 20px; bottom: 20px; --color2: #a0869a; --color1: #2953e1; --bg: repeating-radial-gradient(gray 0px, Beige 1px, #525e54 3.5px); --border: RoyalBlue;',
lrc_css: 'left: 50%; transform: translate(-50%);bottom:30px; --bg: linear-gradient(lightblue, teal); color: lightblue;',
fs_css: 'left: 20px; top: 20px; --bg: transparent; --color: #eee;',
});
};
var geci = `
单曲:迟迟
歌手:银临
所属专辑:琉璃
作词 : 冉语优
作曲 : 银临
你在人间,几时可曾见到他
他是心上,不是天上月皎然
吴天映雪光流转,教人不敢看
又不住偷眼看
长情的人,想少年的梦做完
滚滚的川,把梦中的人倾翻
醒来却枕着细雨,茫茫对书案
周遭不觉春寒
合窗之前风一瓣瓣,如花雪般浓灿
吹来纷纷然坠在衣衫
露出那段轮廓温软,似少年的手腕
写心事多少词总写不完
只如初见,人间该太过美满
美人难免,总要悲一悲画扇
可意难平到后来,若真是堪堪
那又该多不堪
我的少年那样朗然,那样温柔果敢
纵容我一生天真烂漫
想来井边巷间俗谈,困不住他眉弯
那双眼,澄明得,尘事不谙
请告诉他别再遗憾,雾来出入行船
流连于水中捞影的空幻
掀起红妆那一瞬间,他莞然笑的脸
在梦里我已吻了千万遍
在梦里我已吻了千万遍
`;
</script>
换个背景作业写得比较快{:4_170:}
马黑黑 发表于 2024-8-9 07:46
最近写的教程多,有工作上的,有副业方面的,外加这里的,还得加班捡瓶子,东西写好多数都没仔细推敲
{:4_173:}今天的拖曳到是很是新奇,稀罕得很
<style>
.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); box-shadow: 2px 2px 4px gray; border: thick groove lightblue; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }
</style>
<div class='mum'>
<cl-cd data-idx="1"><<span class="tDarkRed">style</span>></cl-cd>
<cl-cd data-idx="2">#mhh {</cl-cd>
<cl-cd data-idx="3"> <span class="tBlue">margin:</span> 30px 0 30px calc(50% - 831px);</cl-cd>
<cl-cd data-idx="4"> <span class="tBlue">width:</span> 1500px;</cl-cd>
<cl-cd data-idx="5"> <span class="tBlue">height:</span> 640px;</cl-cd>
<cl-cd data-idx="6"> <span class="tBlue">background:</span> url(<span class="tMagenta">'https://pic.imgdb.cn/item/66d81253d9c307b7e9d09572.webp'</span>) no-repeat center/cover;</cl-cd>
<cl-cd data-idx="7"> <span class="tBlue">box-shadow:</span> 0 0 8px rgba(0,0,0,.65);</cl-cd>
<cl-cd data-idx="8"> <span class="tBlue">overflow:</span> hidden;</cl-cd>
<cl-cd data-idx="9"> <span class="tBlue">z-index:</span> 1;</cl-cd>
<cl-cd data-idx="10"> <span class="tBlue">position:</span> relative;</cl-cd>
<cl-cd data-idx="11">}</cl-cd>
<cl-cd data-idx="12">#mhh > video {</cl-cd>
<cl-cd data-idx="13"> <span class="tBlue">position:</span> absolute;</cl-cd>
<cl-cd data-idx="14"> <span class="tBlue">width:</span> 100%;</cl-cd>
<cl-cd data-idx="15"> <span class="tBlue">height:</span> 100%;</cl-cd>
<cl-cd data-idx="16"> <span class="tBlue">object-fit:</span> cover;</cl-cd>
<cl-cd data-idx="17"> <span class="tBlue">mix-blend-mode:</span> screen;</cl-cd>
<cl-cd data-idx="18"> <span class="tBlue">-webkit-mask:</span> linear-gradient(to right top, red 10%, transparent 90%, transparent);</cl-cd>
<cl-cd data-idx="19"> <span class="tBlue">pointer-events:</span> none;</cl-cd>
<cl-cd data-idx="20">}</cl-cd>
<cl-cd data-idx="21"><<span class="tDarkRed">/style</span>></cl-cd>
<cl-cd data-idx="22"> </cl-cd>
<cl-cd data-idx="23"><<span class="tDarkRed">div</span> <span class="tRed">id</span>=<span class="tMagenta">"mhh"</span> class=<span class="tMagenta">"mhh"</span>></cl-cd>
<cl-cd data-idx="24"> <<span class="tDarkRed">audio</span> src=<span class="tMagenta">"https://music.163.com/song/media/outer/url?<span class="tRed">id</span>=1471039808"</span> autoplay loop><<span class="tDarkRed">/audio</span>></cl-cd>
<cl-cd data-idx="25"> <<span class="tDarkRed">video</span> src=<span class="tMagenta">"https://img.tukuppt.com/video_show/2418175/00/02/06/5b503d6c75c2a.mp4"</span> autoplay loop muted><<span class="tDarkRed">/video</span>></cl-cd>
<cl-cd data-idx="26"><<span class="tDarkRed">/div</span>></cl-cd>
<cl-cd data-idx="27"> </cl-cd>
<cl-cd data-idx="28"><<span class="tDarkRed">script</span>></cl-cd>
<cl-cd data-idx="29"><span class="tBlue">var</span> sf = <span class="tRed">document</span>.createElement(<span class="tMagenta">'script'</span>);</cl-cd>
<cl-cd data-idx="30">sf.charset = <span class="tMagenta">'utf-8'</span>;</cl-cd>
<cl-cd data-idx="31">sf.src = <span class="tMagenta">'https://638183.freep.cn/638183/web/js2024/plater_yslrc.js'</span>;</cl-cd>
<cl-cd data-idx="32"><span class="tRed">document</span>.body.appendChild(sf);</cl-cd>
<cl-cd data-idx="33"> </cl-cd>
<cl-cd data-idx="34">sf.onload = () => {</cl-cd>
<cl-cd data-idx="35"> HCPlayer({</cl-cd>
<cl-cd data-idx="36"> <span class="tBlue">papa:</span> <span class="tMagenta">'#mhh'</span>,</cl-cd>
<cl-cd data-idx="37"> <span class="tBlue">geci:</span> geci,</cl-cd>
<cl-cd data-idx="38"> <span class="tBlue">skip:</span> 0,</cl-cd>
<cl-cd data-idx="39"> <span class="tBlue">average:</span> 0,</cl-cd>
<cl-cd data-idx="40"> player_<span class="tBlue">css:</span> <span class="tMagenta">'<span class="tBlue">left:</span> 20px; <span class="tBlue">bottom:</span> 20px; --color2: #a0869a; --color1: #2953e1; <span class="tBlue">--bg:</span> repeating-radial-gradient(gray 0px, Beige 1px, #525e54 3.5px); <span class="tBlue">--border:</span> RoyalBlue;'</span>,</cl-cd>
<cl-cd data-idx="41"> lrc_<span class="tBlue">css:</span> <span class="tMagenta">'<span class="tBlue">left:</span> 50%; <span class="tBlue">transform:</span> translate(-50%);<span class="tBlue">bottom:</span>30px; <span class="tBlue">--bg:</span> linear-gradient(lightblue, teal); <span class="tBlue">color:</span> lightblue;'</span>,</cl-cd>
<cl-cd data-idx="42"> fs_<span class="tBlue">css:</span> <span class="tMagenta">'<span class="tBlue">left:</span> 20px; <span class="tBlue">top:</span> 20px; <span class="tBlue">--bg:</span> transparent; <span class="tBlue">--color:</span> #eee;'</span>,</cl-cd>
<cl-cd data-idx="43"> });</cl-cd>
<cl-cd data-idx="44">};</cl-cd>
<cl-cd data-idx="45"> </cl-cd>
<cl-cd data-idx="46"><span class="tBlue">var</span> geci = `</cl-cd>
<cl-cd data-idx="47"> 单曲:迟迟</cl-cd>
<cl-cd data-idx="48"> 歌手:银临</cl-cd>
<cl-cd data-idx="49"> 所属专辑:琉璃</cl-cd>
<cl-cd data-idx="50"> 作词 : 冉语优</cl-cd>
<cl-cd data-idx="51"> 作曲 : 银临</cl-cd>
<cl-cd data-idx="52"> </cl-cd>
<cl-cd data-idx="53"> 你在人间,几时可曾见到他</cl-cd>
<cl-cd data-idx="54"> 他是心上,不是天上月皎然</cl-cd>
<cl-cd data-idx="55"> 吴天映雪光流转,教人不敢看</cl-cd>
<cl-cd data-idx="56"> 又不住偷眼看</cl-cd>
<cl-cd data-idx="57"> 长情的人,想少年的梦做完</cl-cd>
<cl-cd data-idx="58"> 滚滚的川,把梦中的人倾翻</cl-cd>
<cl-cd data-idx="59"> 醒来却枕着细雨,茫茫对书案</cl-cd>
<cl-cd data-idx="60"> 周遭不觉春寒</cl-cd>
<cl-cd data-idx="61"> </cl-cd>
<cl-cd data-idx="62"> 合窗之前风一瓣瓣,如花雪般浓灿</cl-cd>
<cl-cd data-idx="63"> 吹来纷纷然坠在衣衫</cl-cd>
<cl-cd data-idx="64"> 露出那段轮廓温软,似少年的手腕</cl-cd>
<cl-cd data-idx="65"> 写心事多少词总写不完</cl-cd>
<cl-cd data-idx="66"> </cl-cd>
<cl-cd data-idx="67"> 只如初见,人间该太过美满</cl-cd>
<cl-cd data-idx="68"> 美人难免,总要悲一悲画扇</cl-cd>
<cl-cd data-idx="69"> 可意难平到后来,若真是堪堪</cl-cd>
<cl-cd data-idx="70"> 那又该多不堪</cl-cd>
<cl-cd data-idx="71"> 我的少年那样朗然,那样温柔果敢</cl-cd>
<cl-cd data-idx="72"> 纵容我一生天真烂漫</cl-cd>
<cl-cd data-idx="73"> 想来井边巷间俗谈,困不住他眉弯</cl-cd>
<cl-cd data-idx="74"> 那双眼,澄明得,尘事不谙</cl-cd>
<cl-cd data-idx="75"> </cl-cd>
<cl-cd data-idx="76"> 请告诉他别再遗憾,雾来出入行船</cl-cd>
<cl-cd data-idx="77"> 流连于水中捞影的空幻</cl-cd>
<cl-cd data-idx="78"> 掀起红妆那一瞬间,他莞然笑的脸</cl-cd>
<cl-cd data-idx="79"> 在梦里我已吻了千万遍</cl-cd>
<cl-cd data-idx="80"> </cl-cd>
<cl-cd data-idx="81"> 在梦里我已吻了千万遍</cl-cd>
<cl-cd data-idx="82">`;</cl-cd>
<cl-cd data-idx="83"><<span class="tDarkRed">/script</span>></cl-cd>
</div>
{:4_173:}
{:4_170:}
{:4_199:}
{:4_198:}
{:4_187:}
{:4_188:}
{:4_428:}
{:4_196:}
{:4_191:}
{:4_190:}
{:4_181:}
{:4_204:}