菜鸟学完之后,总是感觉学了也还是不会,主要就是因为没有实践,不知道自己到底哪里有问题!虽然说我还没复习完,前端很大一部分都处于模糊阶段,但是感觉还是应该先尽力做一个简单的东西,把这几天学的都用进去,遇到困难,才知道自己的不足!而菜鸟感觉自己的天赋可能就在于,学习完之后,可以马上想一个运用到学习完了的知识点的项目φ(゜▽゜*)♪
文章目录
概要
菜鸟大致要做的就是这样的:
可以拖动左侧的小乐谱(下拉图)到中间变成大乐谱,然后右边有演示视频,按键通过按键盘上的字母发出对应的音阶!
第一部分(左侧下拉)
一开始,菜鸟的代码是这样的
HTML:
<ul style="list-style: none;" class="head_left_ul">
<li>
<div class="head_music_name">
<img onclick="show1()" src="img/尖括号右.png">
<p>两只老虎</p>
</div>
<div class="head_music" id="twotiger_music">
<img style="width: 140px;height: 100px;" src="img/twotiger.jpg">
</div>
</li>
<li>
<div class="head_music_name">
<img onclick="show2()" src="img/尖括号右.png">
<p>小星星</p>
</div>
<div class="head_music" id="star_music">
<img style="width: 140px;height: 100px;" src="img/star.jpg">
</div>
</li>
<li>
<div class="head_music_name">
<img onclick="show3()" src="img/尖括号右.png">
<p>虫儿飞</p>
</div>
<div class="head_music" id="worm_music">
<img style="width: 140px;height: 100px;" src="img/worm.jpg">
</div>
</li>
</ul>
css:
.head_left_ul li{
background-color: rgba(128, 128, 128,0.7);
color: white;
width: 140px;
}
.head_music_name P{
display: inline-block;
margin: 0 0 0 30px;
vertical-align: bottom;
}
.head_music {
display: none;
}
js:
function show1() {
let a = document.querySelector("#twotiger_music");
console.log(a);
console.log(a.style.display);
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
} else {
a.style.display = "none";
}
}
function show2() {
let a = document.querySelector("#star_music");
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
} else {
a.style.display = "none";
}
}
function show3() {
let a = document.querySelector("#worm_music");
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
} else {
a.style.display = "none";
}
}
代码解析
vertical-align
这里之前的讲过,但是有点不一样,先讲的是文字在前面,图片在后面,现在这种情况正好反过来,不过在浏览器中进行调试,可以很清楚的知道该用什么,记下来不如会调试。如果想看的话 ,见 重学前端 p多大 / 浏览器最小文字 / 详解img / object-fit和object-posit / 详解map / 空白区域 / 文字与图片对齐 / vertical-align(第一天)
document.querySelector
querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。
注意:
querySelector() 方法仅仅返回匹配指定选择器的第一个元素,如果你需要返回所有的元素,请使用 querySelectorAll() 方法替代。
资料:
HTML DOM querySelector() 方法
js改变css样式的5种方式
第一种:使用 cssText 全属性
*.style.cssText = "width: 666px; color: red";
第二种:使用 setProperty(属性名,属性值) 方法
*.style.setProperty("width", "666px");
第三种:直接使用单属性
*.style.width="666px";
第四种:直接修改名字
function changeStyle3() {
var obj = document.getElementById( "btnB" );
obj.className = "style2";
//或者
obj.setAttribute( "class" , "style2" );
}
setAttribute() 方法添加指定的属性,并为其赋指定的值。
如果这个指定的属性已存在,则仅 设置/更改 值。
第五种:修改外联样式
<link href= "css1.css" rel= "stylesheet" type= "text/css" id= "css" />
function changeStyle4() {
var obj = document.getElementById( "css" );
obj.setAttribute( "href" , "css2.css" );
}
菜鸟思路
一·、这里菜鸟打印a.style.display,就是想看第一次点击的时候,浏览器会默认display:none为什么东西,结果就是空白,也就是“”
二、菜鸟之所以会用三个show函数,是因为,如果使用querySelector() 方法仅仅返回匹配指定选择器的第一个元素,那样菜鸟不知道怎么区分三个li
第一次修改
然后,菜鸟感觉不行,应该把箭头也变一下,不能一直都是向右的箭头,点击之后应该向下!
于是代码变成了这样(css写好了就无变化了,后面不再列举)。
HTML:
<ul style="list-style: none;" class="head_left_ul">
<li>
<div class="head_music_name">
<img id="head_arrows" onclick="show1(this)" src="img/尖括号右.png">
<p>两只老虎</p>
</div>
<div class="head_music" id="twotiger_music">
<img style="width: 140px;height: 100px;" src="img/twotiger.jpg">
</div>
</li>
<li>
<div class="head_music_name">
<img id="head_arrows" onclick="show2(this)" src="img/尖括号右.png">
<p>小星星</p>
</div>
<div class="head_music" id="star_music">
<img style="width: 140px;height: 100px;" src="img/star.jpg">
</div>
</li>
<li>
<div class="head_music_name">
<img id="head_arrows" onclick="show3(this)" src="img/尖括号右.png">
<p>虫儿飞</p>
</div>
<div class="head_music" id="worm_music">
<img style="width: 140px;height: 100px;" src="img/worm.jpg">
</div>
</li>
</ul>
js:
function show1(element) {
let a = document.querySelector("#twotiger_music");
console.log(element);
console.log(a);
console.log(a.style.display);
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
element.src = "img/尖括号下.png";
} else {
a.style.display = "none";
element.src = "img/尖括号右.png";
}
}
function show2(element) {
let a = document.querySelector("#star_music");
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
element.src = "img/尖括号下.png";
} else {
a.style.display = "none";
element.src = "img/尖括号右.png";
}
}
function show3(element) {
let a = document.querySelector("#worm_music");
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
element.src = "img/尖括号下.png";
} else {
a.style.display = "none";
element.src = "img/尖括号右.png";
}
}
菜鸟思路
菜鸟这里想到了用this,是因为,感觉如果通过document.querySelector的方式获取,那么又得像show函数那样,写三次了!这里的id = ”head-arrows" 是可以去掉的!
οnclick=xxx(this)表示一个单击事件,来进行调用xxx(this)这个JavaScript函数,而xxx(this)函数中的this表示你要进行单击对象的本身。
第二次修改
菜鸟感觉重复代码过多,所以必须得提出一个函数,然后在其它函数里面调用。
代码如下(这里html并未改变,所以这里只列举js)
js:
function show1(element) {
let a = document.querySelector("#twotiger_music");
console.log(element);
console.log(a);
console.log(a.style.display);
this.change(a,element);
}
function show2(element) {
let a = document.querySelector("#star_music");
this.change(a,element);
}
function show3(element) {
let a = document.querySelector("#worm_music");
this.change(a,element);
}
function change(a, element) {
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
element.src = "img/尖括号下.png";
} else {
a.style.display = "none";
element.src = "img/尖括号右.png";
}
}
第三次修改
菜鸟突然记起来data-*,是可以传递参数的,而document.querySelectorAll得到的又是数组,那么是不是可以直接靠传参实现一个show函数呢?
代码如下
HTML:
<ul style="list-style: none;" class="head_left_ul">
<li>
<div class="head_music_name">
<img data-index="0" onclick="show1(this)" src="img/尖括号右.png">
<p>两只老虎</p>
</div>
<div class="head_music">
<img style="width: 140px;height: 100px;" src="img/twotiger.jpg">
</div>
</li>
<li>
<div class="head_music_name">
<img data-index="1" onclick="show1(this)" src="img/尖括号右.png">
<p>小星星</p>
</div>
<div class="head_music">
<img style="width: 140px;height: 100px;" src="img/star.jpg">
</div>
</li>
<li>
<div class="head_music_name">
<img data-index="2" onclick="show1(this)" src="img/尖括号右.png">
<p>虫儿飞</p>
</div>
<div class="head_music">
<img style="width: 140px;height: 100px;" src="img/worm.jpg">
</div>
</li>
</ul>
js:
function show1(element) {
console.log(element.dataset.index);
let index = element.dataset.index;
let b = document.querySelectorAll(".head_music");
let a = b[index];
this.change(a, element);
}
function change(a, element) {
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
element.src = "img/尖括号下.png";
} else {
a.style.display = "none";
element.src = "img/尖括号右.png";
}
}
菜鸟突然发现越是简洁的代码,其实就暗示着思路越发清晰,运用越发熟练,菜鸟得向简洁的代码奋斗!
总代码
(2020/8/2,今天已经是准备写这篇文章的第三天了,前面的倒是慢慢的写的,还能说出条理,后面的完全就是自己在写代码,然后想写的这个博客的时候却发现,忘记先写的代码了,咳咳咳,这里直接把成品展示出来就好)
这就是效果,然后代码已经上传到GitHub上去了,有兴趣的读者可以直接克隆一份
$git clone git@github.com:pbw-langwang/Git_warehouse.git
$ git switch -c dev origin/dev
代码都有注释的!
直接访问连接:https://github.com/pbw-langwang/Git_warehouse
如果不想下,下面就是代码,请慢慢欣赏🤭
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>weekwork</title>
<link rel="stylesheet" href="style.css">
<script src="dom.js"></script>
<noscript>
<div
style="width: 1000px;height:500px;background-color: aqua;display: flex;justify-content: center;align-items: center;">
<div style="width: 500px;height: 300px;background-color: pink;">
<h1>抱歉,你的浏览器不支持 JavaScript!</h1>
<p>难受≧ ﹏ ≦</p>
</div>
</div>
</noscript>
</head>
<body onkeydown="playaudio(event)">
<div
style="background-image: url(img/light.jpg);background-repeat:no-repeat;background-size:100% 100%;width: 100%;height: 100%;">
<!-- head begin -->
<div class="head" style="display: flex;justify-content: space-around;">
<!-- head left -->
<div class="head_lelf">
<ul class="head_left_ul">
<li>
<div class="head_music_name">
<img data-index="0" onclick="show1(this)" src="img/尖括号右.png">
<p>两只老虎</p>
</div>
<div class="head_music" data-id="twotiger" style="width: 200px;height: 100px"
ondrop="drop2(event)" ondragover="allowDrop(event)">
<img id="twotiger" style="width: 100%;height: 100%;" ondragstart="move(event)"
src="img/twotiger.jpg">
</div>
</li>
<li>
<div class="head_music_name">
<img data-index="1" onclick="show1(this)" src="img/尖括号右.png">
<p>小星星</p>
</div>
<div class="head_music" data-id="star" style="width: 200px;height: 100px" ondrop="drop2(event)"
ondragover="allowDrop(event)">
<img id="star" style="width: 100%;height: 100%;" src="img/star.jpg"
ondragstart="move(event)">
</div>
</li>
<li>
<div class=" head_music_name">
<img data-index="2" onclick="show1(this)" src="img/尖括号右.png">
<p>虫儿飞</p>
</div>
<div class="head_music" data-id="worm" style="width: 200px;height: 100px" ondrop="drop2(event)"
ondragover="allowDrop(event)">
<img id="worm" style="width: 100%;height: 100%" src="img/worm.jpg"
ondragstart="move(event)">
</div>
</li>
</ul>
</div>
<!-- head center -->
<div class=" head_center"
style="width: 600px;height: 400px;position: relative;background-color: rgba(0, 89, 255,0.8);border: solid 3px blue;margin: auto 0;">
<div style="width: 600px;height: 350px;" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>
<p style="
position: absolute;
bottom: 0;
color: white;
font-size: 30px;
font-weight: 500;
width: 100%;
height: 50px;
text-align: center;
margin: 0;
background-color: aqua;">
乐谱
</p>
</div>
<!-- head end -->
<div class="head_end">
<ul class="head_end_ul">
<li>
<div class="head_end_musicname" data-index2="0" onclick="show2(this)">
<p>两只老虎</p>
<img src="img/尖括号左.png">
</div>
<div data-id="twotiger2" style="width: 200px;height: 100px" class="head_end_video"
ondrop="drop2(event)" ondragover="allowDrop(event)">
<video id="twotiger2" draggable="true" style="width: 100%;height: 100%;" controls="controls"
src="video/twotiger.mp4" ondragstart="move(event)"></video>
</div>
</li>
<li>
<div class="head_end_musicname" data-index2="1" onclick="show2(this)">
<p>小星星</p>
<img src="img/尖括号左.png">
</div>
<div data-id="star2" style="width: 200px;height: 100px" class="head_end_video"
ondrop="drop2(event)" ondragover="allowDrop(event)">
<video id="star2" draggable="true" style="width: 100%;height: 100%;" src="video/star.mp4"
controls="controls" ondragstart="move(event)"></video>
</div>
</li>
<li>
<div class="head_end_musicname" data-index2="2" onclick="show2(this)">
<p>虫儿飞</p>
<img src="img/尖括号左.png">
</div>
<div data-id="worm2" style="width: 200px;height: 100px" class="head_end_video"
ondrop="drop2(event)" ondragover="allowDrop(event)">
<video id="worm2" draggable="true" style="width: 100%;height: 100%;" src="video/worm.mp4"
controls="controls" ondragstart="move(event)"></video>
</div>
</li>
</ul>
</div>
</div>
<!-- end begin -->
<div class="end_div">
<ul style="display: flex;justify-content: space-around;align-items: center;">
<li>
<p>1</p>
<p>.</p>
<p>.</p>
<p>C+</p>
<p class="key">Q</p>
<audio data-keynub="81" src="audio/C+.mp3"></audio>
</li>
<li>
<p>2</p>
<p>.</p>
<p>.</p>
<p>D+</p>
<p class="key">W</p>
<audio data-keynub="87" src="audio/D+.mp3"></audio>
</li>
<li>
<p>3</p>
<p>.</p>
<p>.</p>
<p>E+</p>
<p class="key">E</p>
<audio data-keynub="69" src="audio/E+.mp3"></audio>
</li>
<li>
<p>4</p>
<p>.</p>
<p>.</p>
<p>F+</p>
<p class="key">R</p>
<audio data-keynub="82" src="audio/F+.mp3"></audio>
</li>
<li>
<p>5</p>
<p>.</p>
<p>.</p>
<p>G+</p>
<p class="key">T</p>
<audio data-keynub="84" src="audio/G+.mp3"></audio>
</li>
<li>
<p>6</p>
<p>.</p>
<p>.</p>
<p>A+</p>
<p class="key">Y</p>
<audio data-keynub="89" src="audio/A+.mp3"></audio>
</li>
<li>
<p>7</p>
<p>.</p>
<p>.</p>
<p>B+</p>
<p class="key">U</p>
<audio data-keynub="85" src="audio/B+.mp3"></audio>
</li>
<li>
<p>1</p>
<p>C</p>
<p class="key">A</p>
<audio data-keynub="65" src="audio/C.mp3"></audio>
</li>
<li>
<p>2</p>
<p>D</p>
<p class="key">S</p>
<audio data-keynub="83" src="audio/D.mp3"></audio>
</li>
<li>
<p>3</p>
<p>E</p>
<p class="key">D</p>
<audio data-keynub="68" src="audio/E.mp3"></audio>
</li>
<li>
<p>4</p>
<p>F</p>
<p class="key">F</p>
<audio data-keynub="70" src="audio/F.mp3"></audio>
</li>
<li>
<p>5</p>
<p>G</p>
<p class="key">G</p>
<audio data-keynub="71" src="audio/G.mp3"></audio>
</li>
<li>
<p>6</p>
<p>A</p>
<p class="key">H</p>
<audio data-keynub="72" src="audio/A.mp3"></audio>
</li>
<li>
<p>7</p>
<p>B</p>
<p class="key">J</p>
<audio data-keynub="74" src="audio/B.mp3"></audio>
</li>
<li>
<p>1</p>
<p>.</p>
<p>C-</p>
<p class="key">Z</p>
<audio data-keynub="90" src="audio/C-.mp3"></audio>
</li>
<li>
<p>2</p>
<p>.</p>
<p>D-</p>
<p class="key">X</p>
<audio data-keynub="88" src="audio/D-.mp3"></audio>
</li>
<li>
<p>3</p>
<p>.</p>
<p>E-</p>
<p class="key">C</p>
<audio data-keynub="67" src="audio/E-.mp3"></audio>
</li>
<li>
<p>4</p>
<p>.</p>
<p>F-</p>
<p class="key">V</p>
<audio data-keynub="86" src="audio/F-.mp3"></audio>
</li>
<li>
<p>5</p>
<p>.</p>
<p>G-</p>
<p class="key">B</p>
<audio data-keynub="66" src="audio/G-.mp3"></audio>
</li>
<li>
<p>6</p>
<p>.</p>
<p>A-</p>
<p class="key">N</p>
<audio data-keynub="78" src="audio/A-.mp3"></audio>
</li>
<li>
<p>7</p>
<p>.</p>
<p>B-</p>
<p class="key">M</p>
<audio data-keynub="77" src="audio/B-.mp3"></audio>
</li>
</ul>
</div>
</div>c
</body>
</html>
css:
body{
margin: 0;
}
.head_left_ul , .head_end_ul , .end_div ul{
padding-inline-start: 0;
list-style: none;
}
.head_left_ul li , .head_end_ul li{
background-color: rgba(128, 128, 128,0.7);
color: white;
width: 200px;
}
.head_music_name p , .head_end_musicname p {
display: inline-block;
margin: 0 0 0 30px;
vertical-align: bottom;
}
.head_music , .head_end_video {
display: none;
}
.head_end_musicname {
display: flex;
align-items: center;
justify-content: flex-end;
}
.head_end_musicname p {
margin: 0 30px 0 0;
}
.end_div {
height: 210px;
}
.end_div ul {
width: 100%;
height: 100%;
margin: 5px 0;
padding: 5px 0;
background-color: rgba(128, 128, 128,0.7);
}
.end_div ul li {
width: 4%;
height: 100%;
background-color: white;
}
.end_div ul li p{
text-align: center;
margin: 0;
}
.key {
font-size: 30px;
font-weight: 500px;
}
js:(运用到了es6命名空间、栈的思想、data-传参、拖动)
let variable = {
bool: true,
pli: '',//不能只写一个pli,必须赋值,即使是空
array: [],
}
//es6的命名空间
function show1(element) {
let index = element.dataset.index;
let b = document.querySelectorAll(".head_music");
let a = b[index];
// 通过data-index来知道点击的是哪一个
this.change(a, element);
}
function change(a, element) {
if (a.style.display === "none" || a.style.display === "") {
a.style.display = "inline-block";
element.src = "img/尖括号下.png";
} else {
a.style.display = "none";
element.src = "img/尖括号右.png";
}
}
function move(event) {
event.dataTransfer.setData("Text", event.target.id);
}
function allowDrop(ev) {
ev.preventDefault();
ev.stopPropagation();
}
function drop(ev) {
ev.preventDefault();
ev.stopPropagation();
// 阻止浏览器对拖动的默认处理,但是firefox有点小bug
// 加上ev.stopPropagation();已解决firefox的bug
var data = ev.dataTransfer.getData("Text");
if (variable.bool) {
ev.target.appendChild(document.getElementById(data));
variable.bool = false;
// 添加元素后,设置互斥变量,防止其它再次拖入造成bug
}
}
function drop2(ev) {
ev.preventDefault();
ev.stopPropagation();
var data = ev.dataTransfer.getData("Text");
let data_id = ev.target.dataset.id;
if (!variable.bool && data === data_id) {
// 通过id 和 data-id的对应关系,来确定是否可以移入
ev.target.appendChild(document.getElementById(data));
variable.bool = true;
}
}
// 设置一个全局互斥变量,以防止多次拖动的bug
function show2(element) {
let index2 = element.dataset.index2;
let b = document.querySelectorAll(".head_end_video");
let a = b[index2];
let c = a.parentElement.children[0].children[1];
// c是获取到video父元素中的img
this.change2(a, c);
}
function change2(a, element) {
if (a.style.display === "none" || a.style.display === "") {
// 第一次a.style.display是空值
a.style.display = "inline-block";
element.src = "img/尖括号下.png";
} else {
a.style.display = "none";
element.src = "img/尖括号左.png";
}
}
function playaudio(event) {
let arr = document.querySelectorAll("audio");
if (variable.pli) {//把variable换成this也可以
// 如果有变了颜色的,就改回其颜色
variable.pli.style.setProperty("background-color", "white");
}
for (i = 0; i < variable.array.length; i++) {
// 判断最近5个中有没有按到的和正在按的相同,如果有就暂停并归零
if (variable.array[i] === event.keyCode) {
for (j = 0; j < arr.length; j++) {
if (parseInt(arr[j].dataset.keynub) === event.keyCode) {
arr[j].currentTime = 0;//设置时间为0,并暂停全部
arr[i].pause();
}
}
}
}
for (i = 0; i < arr.length; i++) {
if (parseInt(arr[i].dataset.keynub) === event.keyCode) {
//通过keynub和keyCode的对应关系,判断哪一个播哦
arr[i].play();
// 保存最近按的5个,如果超过就删除前一个在末尾加上新来的
if (variable.array.length < 6) {
variable.array.push(parseInt(arr[i].dataset.keynub));
} else {
variable.array.shift();
variable.array.push(parseInt(arr[i].dataset.keynub));
};
// console.log(variable.array);
variable.pli = arr[i].parentElement;
variable.pli.style.setProperty("background-color", "rgb(128, 128, 128)");
}
}
}