這是一個練習的小案例,支持在線搜索,調用的是免費的音樂接口,html
主要用到了:彈性盒,3D效果,Ajax 等技術前端
效果以下:ajax
接口地址: https://api.apiopen.top/searchMusicjson
請求示例: https://api.apiopen.top/searchMusic?name=雅俗共賞後端
請求結果:api
{ "author": "許嵩", "link": "http://music.163.com/#/song?id=411214279", "pic": "http://p2.music.126.net/Wcs2dbukFx3TUWkRuxVCpw==/3431575794705764.jpg?param=300x300", "type": "netease", "title": "雅俗共賞", "lrc": "", "songid": 411214279, "url": "http://music.163.com/song/media/outer/url?id=411214279.mp3" }
總體採用三段式樣式,分爲左中右三塊,數組
左側爲裝飾性樣式沒有實際做用,計劃添加 點擊切換歌詞面板功能app
中間部分爲播放器主體,包括搜索框,搜索按鈕,歌曲封面,歌曲名,做者,以及audio播放器,ide
右側沒有進行功能添加,計劃添加喜歡收藏 下一首 上一首 分享 。函數
HTM代碼以下:
<body> <div id="box"> <!-- 搜索信息展現版塊 ==>默認display:none --> <div id="display"> <div class="close"><span>X</span></div> <h2>歌曲列表</h2> <div id="infoBox"> <!-- <p>歌曲名-Redbone <span>聽這首</span></p> --> </div> </div> <!-- 左側版塊 --> <div class="leftBg"> <!-- 滾動信息 --> <marquee behavior="scroll" direction="left">Current version of Baidu Music Interface</marquee> <!-- 文字 ==> THIS IS MUSIC --> <p class="p1">THIS <br>IS </p> <p class="p2">MUSIC</p> <!-- 白色裝飾條 --> <div></div> <div></div> </div> <!-- 中間板塊 --> <div class="centerBg"> <!-- 搜索框+搜索按鈕 --> <input type="text" value="" id="search"><span id="searchSpan">搜索</span> <div id="bfBox"> <!-- 歌曲圖片 --> <div class="imgBox"> <img src="http://p2.music.126.net/5i5SKVW_F1ub2BgDeyjI5A==/3225967119049341.jpg?param=300x300" alt=""> </div> <!-- 歌曲信息 --> <div class="info"> <p>Come and Get Your Love</p> <p>Redbone</p> <!-- 播放器 --> <audio src="http://music.163.com/song/media/outer/url?id=28864241.mp3" controls></audio> </div> </div> </div> <!-- 右側板塊 ==> 未開發 --> <div class="rightBg"> </div> </div> </body>
CSS代碼以下:
<style> body{ /* 開啓視距 */ perspective: 1400px; position: relative; } /* 主頁面 */ #box{ width: 800px; height:500px; background-color: rgb(255, 255, 255); margin: 80px auto; /* transition: 2s; */ /* 開啓3D空間 */ transform-style: preserve-3d; display: flex; justify-content: flex-start; box-shadow: 0 15px 35px -5px rgba(50,88,130,.32); } /* 左側版塊 */ #box .leftBg{ width: 190px; height: 440px; background-color: #222; padding: 30px; position: relative; } /* 中間板塊 */ #box .centerBg{ width: 500px; height: 500px; background-color: rgb(241, 241, 241); } /* 右側版塊 */ #box .rightBg{ width: 100px; height: 500px; background-color: #222; } /* 左側滾動信息 */ #box .leftBg marquee{ margin-top: 15px; color: #fff; font-size: 12px; } /* 左側文字 ==> THIS IS MUSIC */ #box .leftBg p{ transform: translateZ(100px) } #box .leftBg .p1{ color: rgb(253, 0, 0); font-size: 50px; margin: 0; padding-top:50px; } #box .leftBg .p2 { color: rgb(253, 0, 0); font-size: 75px; font-weight: bold; margin: 10px auto; } /* 左側裝飾條兩根 */ #box .leftBg div{ width: 100%; height: 5px; background-color: rgb(241, 241, 241); position: absolute; } #box .leftBg div:nth-child(4){ left: 0; bottom:60px; } #box .leftBg div:nth-child(5){ left: 0; bottom:45px; } /* 搜索框樣式 */ #box #search{ outline:none; border: none; width: 250px; height: 25px; border-top-left-radius: 30px; border-bottom-left-radius: 30px; background-color: #fff; margin-top: 20px; margin-left: 50px; padding: 5px 15px; } /* 搜索按鈕樣式 */ #box #searchSpan{ display: inline-block; padding: 5px 15px; width: 25px; height: 25px; text-align: center; line-height: 25px; background-color: #222; color: #fff; font-size: 12px; border-top-right-radius: 30px; border-bottom-right-radius: 30px; cursor: pointer; } /* 中間板塊 播放器盒子 */ #box .centerBg #bfBox{ width: 240px; height: 330px; border-radius: 10px; background-color: #eef3f7; margin-left:130px; margin-top: 20px; position: relative; box-shadow: 0 15px 35px -5px rgba(50,88,130,.32); display: flex; align-items: flex-end; padding: 30px; } /* 歌曲圖片樣式 */ #box .centerBg .imgBox{ width: 160px; height: 160px; border-radius: 10px; position: absolute; top: 30px; left: -30px; box-shadow: 0 10px 20px 0 rgba(76,70,124,.5); transform: translateZ(100px) } #box .centerBg .imgBox img{ width: 160px; height: 160px; border-radius: 5px; } /* 歌曲信息樣式 */ #box .centerBg #bfBox .info { width: 100%; height: 45%; } #box .centerBg #bfBox .info p{ margin: 0; color:#71829e; } #box .centerBg #bfBox .info p{ margin-top:15px; font-size: 20px; font-weight: bolder; } #box .centerBg #bfBox .info p:nth-of-type(2){ margin-top: 5px; font-size: 16px; } /* audio播放器樣式 */ #box .centerBg #bfBox .info audio{ width: 100%; padding-top: 10px; outline:none; } /* 搜索展現界面樣式 */ #display{ width: 400px; height: 500px; background-color: rgb(245, 238, 238); box-shadow: 0 10px 20px 0 rgba(76,70,124,.5); display: none; border-radius: 10px; position: absolute; top: 0; left: 25%; transform: translateZ(110px); padding: 30px; } /* 搜索展現界面 標題====>(歌曲列表) */ #display h2{ text-align: center; color: rgb(255, 0, 0); } #display p { color: #607391; font-size: 12px; margin: 5px; 0; padding:0 10px; height: 35px; line-height: 35px; } #display p:hover{ background-color: #fff; } #display p span { margin-top: 5px; float: right; width: 45px; height: 25px;; box-sizing: border-box; border-radius: 5px; background-color: rgb(55, 110, 214); box-shadow: inset 1px 1px 5px 0px rgba(50,88,130,.32); text-align: center; line-height: 25px; font-size: 12px; color: #ccc; cursor: pointer; } /* 展現版塊關閉按鈕樣式 */ #display .close{ position: relative; } #display .close span{ width: 30px; height: 30px; border-radius: 50%; position: absolute; top: 10px; right: 10px; background-color: lightblue; box-shadow: inset 1px 1px 5px 0px rgba(50,88,130,.32); text-align: center; line-height: 30px; cursor: pointer; } </style>
視差滾動(Parallax Scrolling)是指讓多層背景以不一樣的速度移動,造成立體的運動效果,帶來很是出色的視覺體驗。做爲網頁設計的熱點趨勢,愈來愈多的網站應用了這項技術。
這是借鑑了視差滾動的原理,使頁面產生實時改變的3D效果,具體實現以下:
1.思路:
將播放器開啓3D空間,
在鼠標橫向移動時,讓播放器沿Y軸旋轉,在鼠標縱向移動時,讓播放器沿X軸旋轉,
將視距增大至1400(此時的視距剛恰好)。
2.代碼實現:
//body{perspective: 1400px;} 開啓視距 // 鼠標在body上移動,將座標轉換成旋轉角度,造成視差 document.onmousemove = function (eve){ var e = eve || window.event; that.x = (e.clientX-that.ele.offsetWidth/2)*0.01; that.y = -(e.clientY-that.ele.offsetTop/2)*0.01;; that.display(); } //造成視差 display(){ this.box.style.transform = "rotateY(" + this.x + "deg) rotateX(" + this.y + "deg)"; }
控制檯信息:
ajax是前端向後端請求發送數據的重要手段,而且能夠實現無刷新加載數據。
該案例使用的接口返回的數據是json,使用ajax能夠正確的解析數據
1.思路:
當用戶點擊搜索按鈕時,獲取輸入框的數據,拼接到接口地址上
使用ajax請求拼接好的地址,拿到數據
2.實現以下:
//搜索框發生改變,生成搜索內容 this.searchBtn.onclick = function(){ var str = ""; that.url = "https://api.apiopen.top/searchMusic"; str = "?name="+that.text.value; that.url += str; that.load(); } // ajax請求數據 load(){ var that = this; ajax({ url:this.url, success:function(res){ that.res = JSON.parse(res); console.log(that.res.result); } }) }
這裏使用的是封裝好的ajax函數,函數以下
//ajax封裝函數 function ajax(options) { var { type, url, success, error, data, timeout } = options; type = type || "get"; data = data || {}; timeout = timeout || 2000; var str = ""; for (var i in data) { str += `${i}=${data[i]}&`; } if (type == "get") { var d = new Date(); url = url + "?" + str + "__qft=" + d.getTime(); } var xhr = new XMLHttpRequest(); xhr.open(type, url, true); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { success && success(xhr.responseText); error = null; } else if (xhr.readyState == 4 && xhr.status != 200) { error && error(xhr.status); success = null; error = null; } } setTimeout(() => { error && error("timeout"); success = null; }, timeout); if (type == "post") { xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.send(str) } else { xhr.send() } }
請求到的數據以下
這裏咱們須要的是result數組中的信息
因此console.log(that.res.result);獲得正確的數據
獲得數據以後下面要作的就是將請求到的數據展現出來
在頁面結構中,有展現頁面的結構,需求是點擊搜索按鈕,展現頁面將數據展現出來
展現格式爲:歌曲名-歌手 而且能夠選擇指定歌曲播放
1.思路:
點擊搜索按鈕後,展現頁面顯示(dispaly:「block」),
將數據拼接爲HTML代碼插入到展現頁面中,
給全部的信息綁定事件,點擊信息記錄當前信息的索引(可使用事件委託優化性能)。
2.代碼實現:
//生成搜索內容 //請求完成,得到數據,將數據展現到搜索頁面上 display2(){ this.displayPage.style.display = "block" var str = ""; // 若是搜索爲空,顯示搜索內容爲空 //不然,展現搜索內容 if(this.res.result.length == 0){ str = "<h3>搜索內容爲空</h3>" }else{ for(var i=0;i<this.res.result.length;i++){ str+=`<p>${this.res.result[i].title}-${this.res.result[i].author} <span>聽這首</span></p>` } } this.infoBox.innerHTML = str; this.change(); this.disClose(); } //點擊選中的歌曲,改變播放器頁面的信息 change(){ var that = this; this.span = document.querySelectorAll("#infoBox p span"); console.log(this.span); // 遍歷全部的歌曲span,找到點擊所在的索引,保存到num中 //同時:若是選中了歌曲,就關閉搜索展現頁面 for(var i=0;i<this.span.length;i++){ this.span[i].index = i; this.span[i].onclick = function (){ this.num = that.span[this.index].index that.reMove(); that.display3(this.num); // console.log(this.num); } } }
點擊關閉按鈕後,或者選擇完成歌曲後,咱們須要關閉展現頁面
1.思路:
點擊關閉很簡單實現,選擇關閉須要咱們調用點擊關閉的子方法
2.代碼實現:
// 關閉按鈕方法 ===> 點擊關閉按鈕(disPageClose) 執行關閉搜索頁面 disClose(){ var that = this; this.disPageClose.onclick = function(){ that.reMove(); } } //移除方法 ====> 執行該函數,清空搜索界面全部內容,並隱藏 reMove(){ this.displayPage.style.display = "none"; this.infoBox.innerHTML = ""; }
展現界面以下:
在選擇歌曲後,須要根據選擇的歌曲改變播放器的封面圖 歌曲名 歌手名 以及要播放的歌曲
1.思路:
查看請求的數據咱們知道(以搜索成都爲例),根據數據的鍵名能夠找到咱們須要的信息
{ author: "趙雷" link: "http://music.163.com/#/song?id=436514312" lrc: "" pic: "http://p1.music.126.net/34YW1QtKxJ_3YnX9ZzKhzw==/2946691234868155.jpg?param=300x300" songid: 436514312 title: "成都" type: "netease" url: "http://music.163.com/song/media/outer/url?id=436514312.mp3" }
故而須要將數據寫入播放器的html中
2.代碼實現:
//播放器音樂信息展現方法 ===> 將ajax請求到的數據,寫入到播放內容區(bfBox) display3(num){ var str = ""; for(var i=0;i<this.res.result.length;i++){ str = `<div class="imgBox"> <img src="${this.res.result[num].pic}" alt=""> </div> <div class="info"> <p>${this.res.result[num].title}</p> <p>${this.res.result[num].author}</p> <audio src="${this.res.result[num].url}" controls></audio> </div>` } this.bfBox.innerHTML = str; }
因爲使用的是H5的audio標籤,這時咱們就完成了,播放器的基本功能。
完整代碼以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> body{ /* 開啓視距 */ perspective: 1400px; position: relative; } /* 主頁面 */ #box{ width: 800px; height:500px; background-color: rgb(255, 255, 255); margin: 80px auto; /* transition: 2s; */ /* 開啓3D空間 */ transform-style: preserve-3d; display: flex; justify-content: flex-start; box-shadow: 0 15px 35px -5px rgba(50,88,130,.32); } /* 左側版塊 */ #box .leftBg{ width: 190px; height: 440px; background-color: #222; padding: 30px; position: relative; } /* 中間板塊 */ #box .centerBg{ width: 500px; height: 500px; background-color: rgb(241, 241, 241); } /* 右側版塊 */ #box .rightBg{ width: 100px; height: 500px; background-color: #222; } /* 左側滾動信息 */ #box .leftBg marquee{ margin-top: 15px; color: #fff; font-size: 12px; } /* 左側文字 ==> THIS IS MUSIC */ #box .leftBg p{ transform: translateZ(100px) } #box .leftBg .p1{ color: rgb(253, 0, 0); font-size: 50px; margin: 0; padding-top:50px; } #box .leftBg .p2 { color: rgb(253, 0, 0); font-size: 75px; font-weight: bold; margin: 10px auto; } /* 左側裝飾條兩根 */ #box .leftBg div{ width: 100%; height: 5px; background-color: rgb(241, 241, 241); position: absolute; } #box .leftBg div:nth-child(4){ left: 0; bottom:60px; } #box .leftBg div:nth-child(5){ left: 0; bottom:45px; } /* 搜索框樣式 */ #box #search{ outline:none; border: none; width: 250px; height: 25px; border-top-left-radius: 30px; border-bottom-left-radius: 30px; background-color: #fff; margin-top: 20px; margin-left: 50px; padding: 5px 15px; } /* 搜索按鈕樣式 */ #box #searchSpan{ display: inline-block; padding: 5px 15px; width: 25px; height: 25px; text-align: center; line-height: 25px; background-color: #222; color: #fff; font-size: 12px; border-top-right-radius: 30px; border-bottom-right-radius: 30px; cursor: pointer; } /* 中間板塊 播放器盒子 */ #box .centerBg #bfBox{ width: 240px; height: 330px; border-radius: 10px; background-color: #eef3f7; margin-left:130px; margin-top: 20px; position: relative; box-shadow: 0 15px 35px -5px rgba(50,88,130,.32); display: flex; align-items: flex-end; padding: 30px; } /* 歌曲圖片樣式 */ #box .centerBg .imgBox{ width: 160px; height: 160px; border-radius: 10px; position: absolute; top: 30px; left: -30px; box-shadow: 0 10px 20px 0 rgba(76,70,124,.5); transform: translateZ(100px) } #box .centerBg .imgBox img{ width: 160px; height: 160px; border-radius: 5px; } /* 歌曲信息樣式 */ #box .centerBg #bfBox .info { width: 100%; height: 45%; } #box .centerBg #bfBox .info p{ margin: 0; color:#71829e; } #box .centerBg #bfBox .info p{ margin-top:15px; font-size: 20px; font-weight: bolder; } #box .centerBg #bfBox .info p:nth-of-type(2){ margin-top: 5px; font-size: 16px; } /* audio播放器樣式 */ #box .centerBg #bfBox .info audio{ width: 100%; padding-top: 10px; outline:none; } /* 搜索展現界面樣式 */ #display{ width: 400px; height: 500px; background-color: rgb(245, 238, 238); box-shadow: 0 10px 20px 0 rgba(76,70,124,.5); display: none; border-radius: 10px; position: absolute; top: 0; left: 25%; transform: translateZ(110px); padding: 30px; } /* 搜索展現界面 標題====>(歌曲列表) */ #display h2{ text-align: center; color: rgb(255, 0, 0); } #display p { color: #607391; font-size: 12px; margin: 5px; 0; padding:0 10px; height: 35px; line-height: 35px; } #display p:hover{ background-color: #fff; } #display p span { margin-top: 5px; float: right; width: 45px; height: 25px;; box-sizing: border-box; border-radius: 5px; background-color: rgb(55, 110, 214); box-shadow: inset 1px 1px 5px 0px rgba(50,88,130,.32); text-align: center; line-height: 25px; font-size: 12px; color: #ccc; cursor: pointer; } /* 展現版塊關閉按鈕樣式 */ #display .close{ position: relative; } #display .close span{ width: 30px; height: 30px; border-radius: 50%; position: absolute; top: 10px; right: 10px; background-color: lightblue; box-shadow: inset 1px 1px 5px 0px rgba(50,88,130,.32); text-align: center; line-height: 30px; cursor: pointer; } </style> </head> <body> <div id="box"> <!-- 搜索信息展現版塊 ==>默認display:none --> <div id="display"> <div class="close"><span>X</span></div> <h2>歌曲列表</h2> <div id="infoBox"> <!-- <p>歌曲名-Redbone <span>聽這首</span></p> --> </div> </div> <!-- 左側版塊 --> <div class="leftBg"> <!-- 滾動信息 --> <marquee behavior="scroll" direction="left">Current version of Baidu Music Interface</marquee> <!-- 文字 ==> THIS IS MUSIC --> <p class="p1">THIS <br>IS </p> <p class="p2">MUSIC</p> <!-- 白色裝飾條 --> <div></div> <div></div> </div> <!-- 中間板塊 --> <div class="centerBg"> <!-- 搜索框+搜索按鈕 --> <input type="text" value="" id="search"><span id="searchSpan">搜索</span> <div id="bfBox"> <!-- 歌曲圖片 --> <div class="imgBox"> <img src="http://p2.music.126.net/5i5SKVW_F1ub2BgDeyjI5A==/3225967119049341.jpg?param=300x300" alt=""> </div> <!-- 歌曲信息 --> <div class="info"> <p>Come and Get Your Love</p> <p>Redbone</p> <!-- 播放器 --> <audio src="http://music.163.com/song/media/outer/url?id=28864241.mp3" controls></audio> </div> </div> </div> <!-- 右側板塊 ==> 未開發 --> <div class="rightBg"> </div> </div> </body> <!-- <script src="./js/ajax.js"></script> --> <script> class Music{ constructor(ele){ this.ele = ele; this.box = document.getElementById("box"); this.text = document.getElementById("search"); this.bfBox = document.getElementById("bfBox"); this.url = "https://api.apiopen.top/searchMusic"; this.infoBox = document.getElementById("infoBox"); this.displayPage = document.getElementById("display"); this.disPageClose = document.querySelector("#display .close span"); this.searchBtn = document.getElementById("searchSpan"); this.addEvent(); } // 綁定事件函數 addEvent(){ var that = this; // 鼠標在body上移動,將座標轉換成旋轉角度,造成視差 document.onmousemove = function (eve){ var e = eve || window.event; that.x = (e.clientX-that.ele.offsetWidth/2)*0.01; that.y = -(e.clientY-that.ele.offsetTop/2)*0.01;; that.display(); } //搜索框發生改變,生成搜索內容 this.searchBtn.onclick = function(){ var str = ""; that.url = "https://api.apiopen.top/searchMusic"; str = "?name="+that.text.value; that.url += str; that.load(); } } // ajax請求數據 load(){ var that = this; ajax({ url:this.url, success:function(res){ that.res = JSON.parse(res); console.log(that.res.result); that.display2(); } }) } //造成視差 display(){ this.box.style.transform = "rotateY(" + this.x + "deg) rotateX(" + this.y + "deg)"; } //生成搜索內容 //請求完成,得到數據,將數據展現到搜索頁面上 display2(){ this.displayPage.style.display = "block" var str = ""; // 若是搜索爲空,顯示搜索內容爲空 //不然,展現搜索內容 if(this.res.result.length == 0){ str = "<h3>搜索內容爲空</h3>" }else{ for(var i=0;i<this.res.result.length;i++){ str+=`<p>${this.res.result[i].title}-${this.res.result[i].author} <span>聽這首</span></p>` } } this.infoBox.innerHTML = str; this.change(); this.disClose(); } //點擊選中的歌曲,改變播放器頁面的信息 change(){ var that = this; this.span = document.querySelectorAll("#infoBox p span"); console.log(this.span); // 遍歷全部的歌曲span,找到點擊所在的索引,保存到num中 //同時:若是選中了歌曲,就關閉搜索展現頁面 for(var i=0;i<this.span.length;i++){ this.span[i].index = i; this.span[i].onclick = function (){ this.num = that.span[this.index].index that.reMove(); that.display3(this.num); // console.log(this.num); } } } // 關閉按鈕方法 ===> 點擊關閉按鈕(disPageClose) 執行關閉搜索頁面 disClose(){ var that = this; this.disPageClose.onclick = function(){ that.reMove(); } } //移除方法 ====> 執行該函數,清空搜索界面全部內容,並隱藏 reMove(){ this.displayPage.style.display = "none"; this.infoBox.innerHTML = ""; } //播放器音樂信息展現方法 ===> 將ajax請求到的數據,寫入到播放內容區(bfBox) display3(num){ var str = ""; for(var i=0;i<this.res.result.length;i++){ str = `<div class="imgBox"> <img src="${this.res.result[num].pic}" alt=""> </div> <div class="info"> <p>${this.res.result[num].title}</p> <p>${this.res.result[num].author}</p> <audio src="${this.res.result[num].url}" controls></audio> </div>` } this.bfBox.innerHTML = str; } } //ajax封裝函數 function ajax(options) { var { type, url, success, error, data, timeout } = options; type = type || "get"; data = data || {}; timeout = timeout || 2000; var str = ""; for (var i in data) { str += `${i}=${data[i]}&`; } if (type == "get") { var d = new Date(); url = url + "?" + str + "__qft=" + d.getTime(); } var xhr = new XMLHttpRequest(); xhr.open(type, url, true); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { success && success(xhr.responseText); error = null; } else if (xhr.readyState == 4 && xhr.status != 200) { error && error(xhr.status); success = null; error = null; } } setTimeout(() => { error && error("timeout"); success = null; }, timeout); if (type == "post") { xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.send(str) } else { xhr.send() } } var body = document.body; new Music(body); </script> </html>