【前端html页面练习】还原英雄联盟客户端
對本文內容的說明:
由于該練習文章其實是筆者剛學習完 Vue 就來寫的小項目,所以該文章的實現方式在現在看來,是十分復雜且繁瑣的,而且代碼寫的也十分混亂,頁面無法實現兼容性,使用了 HTML、CSS、JavaScript、jQuery、Vue ,因此源碼肯定對各位幫助不大。文章內容主要就是記錄了當時遇到的一些問題和樣式上的內容。因此該文章主要就是個練習和總結文,方便之后遇到相關問題后能迅速找到解決方案。由于大家還是想要源碼和相關資源,所以最后還是決定給大家貼出來。
但是重要的事情說三遍,該源碼真的僅供各位參考,僅供參考!僅供參考!僅供參考!寫的真的很差。所以推薦大家用 Vue項目 + ElementUI 去寫。
文中的靜態資源,各位如有需要可去評論區自行下載(除了在游戲安裝路徑下的圖之外,都是自己在游戲上截圖的)。
本文免費源代碼點擊👉鏈接👈即可進入下載頁面 (再次說明:該源碼寫的真的很差,僅供參考,到各位的瀏覽器上不一定能正常顯示)。
歡迎大家前往 我的 Vue 專欄 了解更多關于 Vue 的內容。
在仿寫客戶端的過程中,我使用了 HTML、CSS、JavaScript、jQuery、Vue
其中JS和jQuery用來實現DOM操作(主要還是用jQuery)
由于在寫本文章的時候,筆者還處于學習狀態,模仿客戶端界面是一時興起,想著做點什么練練手,看看各種復雜的功能該如何實現,也沒有接觸過項目,不知道規范,因此才混合起來使用這些技術。但從目前來看,確實是太稚嫩了。所以推薦大家不要像源碼中那樣寫(多去學習使用 Vue 或者 React + 各種組件)。
而且在編寫代碼前,我對Vue的理解是很片面的,認為Vue最大的用處就是編寫單頁面應用,而我在思考的過程中覺得仿寫客戶端需要多頁面的跳轉,因此最終沒有選擇采用Vue項目的形式。后來查詢了一下,Vue項目應該也能實現多頁面應用,不過這方面的問題只能以后嘗試了。
因此我沒有搭建Vue項目,那么做DOM操作,我還是覺得jQuery更簡單,因此使用jQuery。然后用Vue來綁定事件及實現一些功能(在文章中會提到)。
然后說回到代碼本身,它是有瀏覽器兼容性問題的,而且解決瀏覽器兼容性這方面是我的弱項。在代碼中我嘗試使用%的方式,來確保內容可以根據瀏覽器的寬高來等比例縮小或放大,但從結果上來看…em…差強人意,但至少一多半的內容都能正常展現。而且最開始的感覺還挺良好的,以為找到了還算不錯的解決方案。不過能出現差錯也代表著編寫的代碼是有一定問題的。以后再嘗試的話,會采用rem試試看,并盡量編寫更好的代碼。
不過游戲客戶端本身就是無法拉伸的,本著這樣的想法,最后還是用%完成了在Chrome瀏覽器的,指定頁面大小下的布局(其他瀏覽器我在嘗試的時候,確實是有兼容性問題)
(也就是說,我考慮了兼容性問題,結果在本次編寫代碼過程中,還是無法解決…)
我在編寫代碼過程中的相關素材取自:
Iconfont-阿里巴巴矢量圖標庫
覓元素
主要素材來源:
游戲下載路徑\英雄聯盟\TCLS\ui\res\test
游戲下載路徑\英雄聯盟\TCLS\ui\servers
游戲下載路徑\英雄聯盟\TCLS\ui\movie_tpf\img
游戲下載路徑\英雄聯盟\TCLS\ui\media
游戲下載路徑\英雄聯盟\Air\assets\images
游戲下載路徑\英雄聯盟\Air\assets\storeImages
說到這些素材,當我編寫登錄界面的時候,以為所有樣式內容都需要用css來實現,結果到了后面感覺很多樣式都編寫不出來時才發現,原來…我之前辛辛苦苦自己做的樣式,lol都是有相關素材的。因此,我們只要能找到素材,那我們要做的就只是定位,綁定事件即可,其實還是蠻簡單的。除此以外,因為我切圖手法比較笨拙,所以后期有一些都是我直接從客戶端上拿下來的。
進入內容前,直接上演示視頻:(只實現了 登錄 到 主界面)
【前端】仿寫LOL客戶端界面(演示視頻)
前端模仿英雄聯盟客戶端界面
- 帳號登錄界面
-
- 背景圖(img和background-image)
- 按鈕顏色漸變
- 加載效果(轉動)
- 從 安全檢測 轉成 登錄方式(頁面部分內容的變化)
- 圖標控制音樂開關
- 登錄功能
- 選擇服務器界面
-
- Vue的過渡效果(transition標簽)
- 排隊加載界面
-
- 進度條的實現
- 游戲客戶端主頁面
-
- 初次進入客戶端的廣告
- 移入移出效果(mouseenter、mouseleave)
- 好友列表的展開效果
- 視頻的自動播放問題
- 輪播圖的實現
帳號登錄界面
對于頁面設計,我個人的經驗之談就是,先劃分區域并開啟絕對定位,然后讓每個區域都處在對應的位置上。比如該部分的頁面,我把它劃分成了三個部分。劃分好區域后,所有的內容都會在各自的區域中排布。
左上區域涉及到的用法:img和background-image的用法、按鈕漸變效果
左下方區域的文字內容,本來我是自己貼圖 + 用三個div設計的,后來發現lol素材里,它有一整張圖片(除了紅色邊框中的內容外),那就直接拿來用了。紅色邊框內的文字,是一段超鏈接,我們只需要給它定位就可以了。
右側區域涉及到的用法:加載效果(轉動)、區域內容的轉化、音樂的開關、登錄功能
在右側區域,下面看到的logo的動態效果是lol的素材。
注:img可以加載gif圖片,因此這里才是動態效果,而如果是webm格式的,就比較麻煩了,在之后會提到這方面的問題。
背景圖(img和background-image)
<!--左側區域--><div class="left"><!--聯盟圖標--><div class="logo"><img src="./img/login-icon/logo-public.png"/></div></div>
/*左側顯示區域的整體樣式*/.left{position: absolute;width: 80%;height: 94%;left: 0;background-image: url("./img/login-icon/login_page.jpg");background-repeat: no-repeat;background-size: cover;}/*英雄聯盟圖標樣式*/.logo{position: absolute;width: 95%;border-bottom: 1px darkgoldenrod solid;left: 2.5%;}
最開始學習的時候,我覺得img是使用圖片的最好方法,但是當遇到越來越多的需求的時候,我發現background-image的方式更應該被靈活運用,而且可以解決很多麻煩。
比如,在這個部分我就分別用了這兩種方式。在我看來,它們的使用條件幾乎沒什么區別。
如果該圖片是和文字在一行中或者一列中排列的,那么使用img是比較好的(從代碼量上來看,性能方面未知)。因為用div設置背景,除去定位,一定要設置寬度高度,background-size和background-image。而對于img,除去定位,只需要設置寬度 / 高度 其中一項,圖片就可以等比例縮放、放大。
(對于行內元素,只有在標簽內寫了一些內容,背景才會顯示,而且無法設置背景相關信息。因此如果想把行內元素變成塊元素,那不如直接用div設置)
比如:
在這種用法里,外部容器div被我用紅色背景顯示。這個外部容器在這種情況下,可以不用設置height,除非項目中指定高度。那么這樣一來,div的高度會被內容撐起。這里能設置的樣式就很多了,比如文字和圖片之間有間距,只需要設置margin;文字和圖片使用居中方案;又或是修改圖片大小并定位。
如果是把圖片當作背景,確實是使用background會更好,因為外部容器div設置了背景,那么內部所有元素都只需要在這外部容器中操作。但是當然img也能當背景,只不過這些元素肯定是不能放在img標簽內了,只能再另建一個容器,把內容放在img上,讓img的z-index更小,那顯然這種方式不利于維護。
也就是說,其實這兩種在任何情況下都還算是可以轉換使用的,但是使用background顯然是可以設置更多屬性的去解決很多問題的。
區別還是有一些的:
如果圖片事先知道尺寸大小,且想完整顯示,那么就需要設置根標簽的寬度、高度。如果不知道卻依然堅持用background,要不就是自己手動調整寬度高度,要不就是用background-size: cover 圖片多出的部分會刪去,background-size: contain 標簽中會出現空白的部分。那么用img就可以設置寬度 / 高度 任一屬性,就可以在不知道尺寸大小的情況下,等比例縮放。
如果遇到CSS Sprites(css精靈圖),那么只能使用background。
如果遇到能點擊的圖片,那么只能使用background。
<a href="javascript:;" class="re"></a>
.re{display: block;position: absolute;width: 31px;height: 31px;right: 11%;top: 67%;background-image: url("./img/login-icon/re.png");}.re:hover{background-image: url("./img/login-icon/re_h.png");}.re:active{background-image: url("./img/login-icon/re_c.png");}
按鈕顏色漸變
這里所謂的“按鈕”,其實是一個超鏈接a。如果真的使用按鈕,首先為其設置樣式會稍微麻煩一些,而且點擊按鈕就去展示一個新頁面,不如直接使用超鏈接。
<!--查看詳情--><a href="https://lol.qq.com/main.shtml" class="detail" target="_block">查看詳情</a>
/*查看詳情的樣式*/.detail{position: absolute;display: block;width: 100px;height: 30px;left: 2.5%;bottom: 2.5%;text-align: center;line-height: 30px;background-color: #131622;border: 1.5px darkgoldenrod solid;color: #CABD8E;transition-property: all;transition-duration: 0.5s;}.detail:hover{border: 1.5px #DDC796 solid;color: #F0E5D3;background-image: linear-gradient(rgb(23,30,38),rgb(110,100,74));}
漸變效果采用的是CSS的linear-gradient去設計,這種方式挺簡單的。更復雜的可以考慮canvas。
(但是實際上,后來發現lol的按鈕是圖片效果,在lol素材里可以找到,這就方便很多了)
之后所有的漸變按鈕都是這種方式,下面這個a中的圖片,就是采用上面提到的img方式。
加載效果(轉動)
視頻中的加載效果 -> 該效果的教學視頻
從 安全檢測 轉成 登錄方式(頁面部分內容的變化)
頁面轉化是根據數字的變化,當安全檢測值到100%,就“跳轉”。這部分就很簡單了,數據綁定 + v-cloak(防止表達式閃爍)
<!--安全檢測的進度條--><div v-cloak class="finish">{{finish}}%</div>
然后在vue的mounted生命周期中,直接設置定時器,模擬安全檢測效果,并在結束時清除定時器。
mounted(){/*剛進入頁面就會直接進行安全檢測*/this.intervalTime = setInterval(()=>{this.finish += 20/*當安全檢測完成時,跳轉到登錄頁面,且清除定時器*/if(this.finish === 100){this.right = falseclearInterval(this.intervalTime)}},1000)},
在vue里設置了一個屬性right,其初始值是true。當安全檢測結束后,right為false,然后觸發v-if:
<!--右側安全檢測后的登錄區域--><div class="right" v-if="!right">....</div><!--右側展示安全登錄檢測框--><div class="right" v-else><!-- 實現安全檢測的動畫 --><div class="container"><!--旋轉球效果--><div class="rotate"><!--代表每個球--><div class="item"></div><div class="item"></div><div class="item"></div><div class="item"></div><div class="item"></div></div><!--間隔--><div class="gap"></div><p>正在進行安全檢測:</p><!--安全檢測的進度條--><div v-cloak class="finish">{{finish}}%</div></div></div>
那么這種用法將會是之后所有 部分區域頁面內容變化的實現方式 (不是v-if就是用的v-show),也就是模擬出了類似單頁應用的效果。而將這兩個div都設置同一個類,也就保證了切換后,它們最外圍容器的位置、樣式都是一樣的。
但是這種方式肯定不能和vue-router相提并論。首先這種是有切換損耗的,并且不可能實現多次的轉換(比如v-if只能用作兩部分內容的切換,v-show也類似,但是v-show可以讓多個內容同時顯示或隱藏)
圖標控制音樂開關
<!--右上角相關圖標--><div class="right-icon"><!--看不見的播放器--><audio id="player" loop="loop"><source src="./img/login-icon/sound.mp3"/></audio><a href="javascript:;" v-if="ok" @click="music"><img src="./img/login-icon/laba-off.png"/></a><a href="javascript:;" v-else @click="music"><img src="./img/login-icon/laba.png"/></a><a href="javascript:;"><img src="./img/login-icon/suoxiao.png"/></a><a href="javascript:;"><img src="./img/login-icon/guanbi.png"/></a></div>
音頻采用的是audio,只要不給其添加controls屬性,那么在頁面中就看不到這個音樂播放器,我們只要在音樂的圖標中,添加一個開關的v-if(切換圖片)和@click事件,就完成了這部分內容。
methods: {music(){ /*音樂相關信息*/this.ok = !this.okif(this.ok === false){player.src = './img/login-icon/sound.mp3';player.play();}else{player.src = '';player.pause();}}}
登錄功能
首先這里 QQ登錄 - 微信登錄、切換至快速登錄 - 使用其它帳號登錄 ,部分內容的轉換采用的都是v-if。
<!--右側安全檢測后的登錄區域--><div class="right" v-if="!right"><!-- 選擇登錄方式之后 --><div class="login-on" v-if="login"><!--上方的兩個選項--><!--QQ選項--><a href="javascript:;" :class="{classA: hasLogin, classB: !hasLogin, classC: true}" @click="qqLogin"><img src="./img/login-icon/qq.png"/>QQ登錄</a><!--微信選項--><a href="javascript:;" :class="{classA: !hasLogin, classB: hasLogin, classD: true}" @click="chatLogin"><img src="./img/login-icon/wechat.png"/>微信登錄</a><!--設定登錄小三角--><div :class="{triangleQQ: hasLogin, triangleChat: !hasLogin}"></div><!--QQ登錄區--><div class="QQAction" v-if="hasLogin"><!--正常輸入帳號區域--><div v-if="quickLogin"><div class="QQAction-color1">QQ帳號</div><input type="text" title="安全提示:騰訊英雄聯盟不會在登錄或游戲過程中詢問與您帳號有關的任何密保信息,請謹防騙取密保的盜號木馬" v-model="account"/><div :style="{height: '10px'}"></div><div class="QQAction-color1">QQ密碼</div><input type="password" title="安全提示:騰訊英雄聯盟不會在登錄或游戲過程中詢問與您帳號有關的任何密保信息,請謹防騙取密保的盜號木馬" v-model="password"/><br/><div :style="{height: '10px'}"></div><input type="checkbox"/><span class="QQAction-color2">記住賬號</span><br/><input type="checkbox" :checked="hasCheck" @click="hasCheck=!hasCheck"/><span class="QQAction-color2">我已詳細閱讀并同意</span><br/><a href="https://game.qq.com/contract.shtml" class="QQAction-color3" target="_blank">騰訊游戲用戶協議</a><span class="QQAction-color2">和</span><a href="https://game.qq.com/privacy_guide.shtml" class="QQAction-color3" target="_blank">隱私保護指引</a><div :style="{height: '10px'}"></div><a href="javascript:;" class="QQAction-color4" @click="gameStart">進入游戲</a><a href="javascript:;" class="QQAction-color5" @click="quickLogin=!quickLogin">切換至快速登錄</a></div><!--快速登錄賬號區域--><div v-else><div class="QQAction-color1">檢測到您已登錄QQ帳號,請選擇登錄</div><div :style="{height: '10px'}"></div><a href="javascript:;" class="Quick-btn">只爭朝夕不負韶華(54*****57)</a><div :style="{height: '70px'}"></div><input type="checkbox" :checked="hasCheck" @click="hasCheck=!hasCheck"/><span class="QQAction-color2">我已詳細閱讀并同意</span><br/><a href="https://game.qq.com/contract.shtml" class="QQAction-color3" target="_blank">騰訊游戲用戶協議</a><span class="QQAction-color2">和</span><a href="https://game.qq.com/privacy_guide.shtml" class="QQAction-color3" target="_blank">隱私保護指引</a><div :style="{height: '10px'}"></div><a href="javascript:;" class="QQAction-color4" @click="quickStart">確定</a><a href="javascript:;" class="QQAction-color5" @click="quickLogin=!quickLogin">使用其它帳號登錄</a></div></div><!--微信登錄區--><div class="wechatAction" v-else><div class="QQAction-color2">使用 微信掃碼 安全登錄</div><div :style="{height: '10px'}"></div><img src="./img/login-icon/QR.png"/><a href="javascript:;" class="re"></a><div :style="{height: '20px'}"></div><input type="checkbox" /><span class="QQAction-color2">我已詳細閱讀并同意</span><br/><a href="https://game.qq.com/contract.shtml" class="QQAction-color3" target="_blank">騰訊游戲用戶協議</a><span class="QQAction-color2">和</span><a href="https://game.qq.com/privacy_guide.shtml" class="QQAction-color3" target="_blank">隱私保護指引</a></div></div><!-- 進入頁面選擇登陸方式 --><div v-else><!--選擇QQ--><a href="javascript:;" class="QQLogin" @click="qqLogin"><img src="./img/login-icon/qq.png"/>QQ登錄</a><!--選擇微信--><a href="javascript:;" class="wechatLogin" @click="chatLogin"><img src="./img/login-icon/wechat.png"/>微信登錄</a></div></div>
然后是Vue中全部內容:
<script type="text/javascript">new Vue({el: '#lol',data: {ok: true, //用來判斷喇叭是否開啟right: true, //用來判斷是否在進行安全檢測finish: 0, //用來判斷安全檢測的進度login: false, //選擇一種登錄方式,且login為true后永遠不變回去hasLogin: true, // true是QQ登陸,false是微信登錄,默認QQaccount: '', //記錄帳號password: '', //記錄密碼hasCheck: false, //判斷相關說明是否已經框選quickLogin: true //判斷是否進行快速登錄},mounted(){/*剛進入頁面就會直接進行安全檢測*/this.intervalTime = setInterval(()=>{this.finish += 20/*當安全檢測完成時,跳轉到登錄頁面,且清除定時器*/if(this.finish === 100){this.right = falseclearInterval(this.intervalTime)}},1000)},methods: {music(){ /*音樂相關信息*/this.ok = !this.okif(this.ok === false){player.src = './img/login-icon/sound.mp3';player.play();}else{player.src = '';player.pause();}},qqLogin(){ /*選擇QQ登錄*/if(this.login === false){this.login = true}if(this.hasLogin === true){}else{this.hasLogin = true}},chatLogin(){ /*選擇微信登錄*/if(this.login === false){this.login = true}if(this.hasLogin === false){}else{this.hasLogin = false}},gameStart(){ //正則表達式,判斷賬號密碼是否符合規范let reg = /[0-9]{6,}/iglet reg2 = /\S{6,}/igif(reg.test(Number(this.account))&®2.test(this.password)){if(this.hasCheck){alert('登錄成功')/*登錄成功后進入選擇服務器頁面*/window.location.href="./chooseServer.html"}else{alert('請仔細閱讀內容后,勾選按鈕')}}else{alert('帳號或密碼輸入錯誤')}},quickStart(){ /*快速登錄功能*/if(this.hasCheck){alert('登錄成功')/*登錄成功后進入選擇服務器頁面*/window.location.href="./chooseServer.html"}else{alert('請仔細閱讀內容后,勾選按鈕')}}}})
</script>
那么通過之前的說明,我們要改變部分區域的內容,我們使用v-if就可以實現。也就是當我們點擊某個按鈕后,修改了data中的數據,從而導致v-if v-else觸發,在同一個區域就展示了不同的內容。
想要實現:我已詳細閱讀并同意 被選擇后才能進入下一步,就只需要綁定checked:
<input type="checkbox" :checked="hasCheck" @click="hasCheck=!hasCheck"/><span class="QQAction-color2">我已詳細閱讀并同意</span>
那么設置成:當點擊按鈕,導致hasCheck為true時,才能跳轉到下個頁面就完成了該功能。
然后點擊“進入游戲”或“確定”(超鏈接a)后,去判斷是否hasCheck為true,以及如果選擇賬號登陸,賬號密碼是否符合正則表達式即可。最后如果滿足了條件,使用window.location.href"跳轉頁面即可。
這里還有一個用法就是實現三角形,這個就是面試中常問到的問題了。
三角形很容易實現,只需要寬高設為0,給一定的border大小,將其設為透明,然后根據三角形的朝向設置color就實現了。比如下面給border-top-color,那就是箭頭朝下。border-bottom-color,那就是箭頭朝上。
然后設計一個,當點擊某登錄方式時,讓箭頭偏移位置就可以實現箭頭也跟著切換的效果了。
/*實現三角形*//*三角的通用樣式*/.triangleQQ,.triangleChat{position: absolute;width: 0px;height: 0px;border: 5px solid transparent;border-top-color: #776947;top: 37.5%}/*兩種方式三角的位置不同*/.triangleQQ{left: 25%;}.triangleChat{right: 25%;}
除此以外,第一個頁面就都是定位和設置樣式了。
選擇服務器界面
整體效果:
該界面比較簡單,如何劃分區域都可以,把它看成一個區域也行,上下兩個區域也行。
在這里先說一說我沒實現的功能:
(1)無法點擊大區圖標旁的兩個按鈕實現換區功能;
(2)在服務器列表中無法點擊服務器,去實現換區功能。
這個功能如果不構建Vue項目,感覺實現起來會十分繁瑣,單頁應用效果肯定會是最佳選擇,因為這不是單純v-if就能實現的。
在每個服務器名字前的綠點,是這么實現的:(后來發現,也有這個素材)
/*給所有服務器前加上綠色標志*/.open a::before{content: '◆';color: #1FAE69;margin-right: 10px;}
那么該部分除了定位和樣式外,只用到了Vue的過渡效果
Vue的過渡效果(transition標簽)
<transition name="serviceOpen"><div class="open" v-show="openService" v-cloak><div class="server-font" :style="{top: '1%'}">全網絡大區</div><a href="javascript:;" class="blueServer" :style="{top: '5%'}">男爵領域</a><a href="javascript:;" class="blueServer" :style="{top: '5%', left: '15%'}">峽谷之巔</a><div class="server-font" :style="{top: '15%'}">電信</div><a href="javascript:;" class="yellowServer active" :style="{top: '19%'}">艾歐尼亞</a><a href="javascript:;" class="yellowServer" :style="{top: '19%', left: '15%'}">祖安</a><a href="javascript:;" class="yellowServer" :style="{top: '19%', left: '27%'}">諾克薩斯</a><a href="javascript:;" class="yellowServer" :style="{top: '19%', left: '39%'}">班德爾城</a>...</div></transition>
transition標簽是Vue中的方法,被該標簽包裹的內容,就會在內容改變時,產生過渡效果。使用方法很簡單,而且頻繁切換也是沒問題的。如果是css中設置的過渡和動畫效果,是沒辦法實現返程的,也就是說顯示需要觸發一次,關閉再觸發一次。而Vue的transition在設置的時候,就可以設計顯示效果和隱藏效果,很方便。
/*服務器列表動畫*/.serviceOpen-leave-active,.serviceOpen-enter-active{transition: all 1s;}.serviceOpen-leave-to,.serviceOpen-enter{opacity: 0;}
排隊加載界面
整個背景采用的是素材,該部分只是向其中添加了文字和進度條。上面兩個場景的變換,依然采用v-if。排隊時間變化依然采用 在mounted生命周期中添加定時器的方式來實現。取消按鈕也和以前一樣。
在這里主要是進度條的實現
完整代碼:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>League of Legends</title><!--設置網頁圖標--><link rel="icon" href="./img/icon/lol2.ico" type="image/x-icon"><style>/*通用設置*/*{margin: 0;text-decoration: none;list-style: none;}/*防止表達式閃爍*/[v-cloak]{display:none;}/*整體架構設計*/#game{position: absolute;width: 100%;height: 100%;background-repeat: no-repeat;background-size: contain;background-image: url("img/new-icon/wait_icon.png");}/*正在排隊等候*/.wait{position: absolute;color: #F0E7D6;top: 57%;left: 49.5%;transform: translateX(-50%);font-size: 18px;}/*設置所有span顏色*/span{color: #DDC796;}/*當前位置和等待時間通用樣式*/.currentPosition,.waitTime{position: absolute;color: #F7F0E0;left: 45%;font-size: 13px;}.currentPosition{top: 62%;}.waitTime{top: 65%;}.currentPosition span{margin-left: 25px;}/*取消和進行欄*/.cancel{position: absolute;display: block;width: 8%;height: 5%;bottom: 23%;left: 45.2%;text-align: center;line-height: 35px;background-color: #131622;border: 1.5px darkgoldenrod solid;color: #CABD8E;transition-property: all;transition-duration: 0.5s;}.cancel:hover{border: 1.5px #DDC796 solid;color: #F0E5D3;background-image: linear-gradient(rgb(23,30,38),rgb(110,100,74));}/*排隊完成后,進入加載頁面*//*進度條樣式*/.progressContainer{position: absolute;width: 15%;height: 1.2%;top: 62%;left: 42%;border: 1px solid #C4A76C;border-radius: 10px;}#progress{width: 0%;height: 100%;background-image: linear-gradient(to right, rgb(0,90,130),rgb(108,200,210));}</style>
</head>
<body><div id="game"><!--正在載入--><div v-if="loading" v-cloak><div class="wait">正在載入</div><div class="progressContainer"><div id="progress"></div></div></div><!--正在排隊--><div v-else v-cloak class="waiting"><div class="wait">正在排隊等候</div><div class="currentPosition">當前位置:<span v-cloak>{{queueNum}}</span></div><div class="waitTime">預計等待時間:<span v-cloak>{{minute}}分鐘</span></div><a class="cancel" href="./chooseServer.html">取消</a></div></div></body>
<script type="text/javascript" src="js/vue.js"></script>
<script src="js/jquery-1.12.3.js" type="text/javascript"></script>
<script type="text/javascript">new Vue({el: '#game',data: {queueNum: 77777, //當前排隊位置minute: 7, //預計等待時間loading: false, /*判斷是否開始加載*/w: 0 /*代表當前加載進度*/},mounted(){/*剛進入頁面就排隊*/this.intervalTime = setInterval(()=>{this.queueNum -= 11111this.minute -= 1if(this.queueNum === 0){this.loading = true;/*現在轉為加載界面*/this.intervalLoad = setInterval(()=>{this.w += 1$('#progress').css('width', this.w +'%')if(this.w === 100){window.location.href="./LOLGame.html";clearInterval(this.intervalLoad)}},100)clearInterval(this.intervalTime)}},1000)}})
</script>
</html>
進度條的實現
this.intervalLoad = setInterval(()=>{this.w += 1$('#progress').css('width', this.w +'%')if(this.w === 100){window.location.href="./LOLGame.html";clearInterval(this.intervalLoad)}},100)
首先定時器設計的也很簡單,0.1s觸發一次,屬性w用來記錄進度條的進度,然后根據w的值,來修改進度條中的進度。當該值為100時,跳轉頁面,進入到游戲客戶端主頁面。
html部分:
<div class="progressContainer"><div id="progress"></div></div>
進度條的css實現:
/*排隊完成后,進入加載頁面*//*進度條樣式*/.progressContainer{position: absolute;width: 15%;height: 1.2%;top: 62%;left: 42%;border: 1px solid #C4A76C;border-radius: 10px;}#progress{width: 0%;height: 100%;background-image: linear-gradient(to right, rgb(0,90,130),rgb(108,200,210));}
這里的border-radius的單位一定是px,才能是兩頭圓的樣式,不能用%。然后進度條中的顏色漸變依然依靠linear-gradient。然后進度條本身也是div,出現加載的效果,是因為在定時器中不斷修改該div的width才出現的效果。
(所以進度條還是很容易實現的,之前以為會是很難的)
游戲客戶端主頁面
我將該頁面分為了三個區域:
首先涉及到初次進入客戶端出現的廣告效果
對于上方區域,從左往右說,play的按鈕本身肯定也是有素材在的,因為我沒找到所以就自己截了幾張。也就是說play是用a標簽加background的形式實現的。然后列表欄(主頁、線、云頂…),這部分內容就是所有網頁都會涉及的內容了,有一些練習可以參考我之前的【文章】。那么這么多“按鈕”點擊后,會修改左下區域的內容,去展示各自的信息,那么顯然只有Vue項目中才能做到了。除此以外,都是拿到素材,為其定位和設置樣式了。
然后上方區域還有一個就是鼠標移動到頭像時,相應內容的顯現
對于右側好友區域,因為那些圖標都需要素材,我又沒有找到的情況下,就去自己截了圖。對于好友區域上下方的各按鈕的觸發就沒有實現功能了(根據之前的功能實現,其實這部分很簡單了)
然后右側區域還有一個就是好友列表下拉欄的實現
對于主頁內容區域,除去素材的定位和元素樣式,重點就是輪播圖的實現
最后簡單說一下視頻的自動播放
初次進入客戶端的廣告
思路比較簡單:在主頁內容區域,設置一個z-index優先級很高的div,其寬高為當前區域100%。再將其背景設為黑色并設置透明度,即可實現背景陰影效果。在其中再建一個可以點擊的圖片和關閉按鈕,其z-index高于底部div即可。
<!--剛進入游戲的廣告--><div class="adver" v-show="advertise"></div><a href="https://lol.qq.com/act/a20200828anniversarychest/index.html?e_code=500142&area=1" target="_blank" class="ling" v-show="advertise"><img src="img/new-icon/lingneng.png"/></a><a href="javascript:;" class="adverClose" v-show="advertise" @click="advertise=!advertise">X</a>
/*剛進入游戲的廣告*/.adver{position: absolute;width: 100%;height: 100%;opacity: 0.7;background-color: black;z-index: 1000;}.ling{position: absolute;display: block;z-index: 1001;width: 70%;height: 80%;left: 45%;top: 50%;transform: translate(-50%,-50%);}.ling img{width: 120%;height: 100%;}
移入移出效果(mouseenter、mouseleave)
這個部分在通過之前打開服務器列表的功能實現后,也就很簡單了。只要鼠標移入就打開,鼠標移出就關閉,然后用transition設計效果即可。
<!--頭像區域--><a href="javascript:;" class="head" @mouseenter="more" @mouseleave="close"></a><!--頭像打開內容--><transition name="headMore"><div class="head_more" v-show="open" v-cloak><!--打開內容的皮膚背景--><div class="background"></div><img src="./img/game-icon/level_message.png" class="levelMessage"/><!--下方內容--><div class="message"><img src="./img/game-icon/message.png"/></div><img src="./img/game-icon/name.png" class="name"/></div></transition>
打開的詳細內容區,我又把它分為三個區域。最上方區域就是用background,中間區域的頭像框和名字、下面區域的文字內容,因為沒有具體的素材,再加上只有定位和樣式的設計,所以都是采用截圖的方式完成了。
好友列表的展開效果
這部分在我最開始構思的時候覺得很復雜,后來想到了這個很簡單的方法。因為div元素是塊元素,它會獨自占據一行,那么根據這個特性,我們完全不需要設計什么,只需要當我們點擊 最近游戲或者是好友列表,觸發事件,讓隱藏的內容出現,再像之前一樣實現三角形的樣式變化,該部分就完成了。(因為沒有具體素材信息,就直接采用截圖的方式,如果有素材,只需要將內容都放在div里,也肯定可以實現該功能)
<!--具體好友區域--><div class="friendMessage" v-cloak><a href="javascript:;" @click="message=!message" class="synthesize"><!--箭頭--><div :class="{classA: message, classB: !message}"></div>綜合 (1/1)</a><div v-show="message" class="onlyFriend"><img src="./img/new-icon/only-friend.png"/></div><a href="javascript:;" @click="message2=!message2" class="lastGame"><!--箭頭--><div :class="{classA: message2, classB: !message2}"></div>最近游戲</a><div v-show="message2" class="onlyFriend"><img src="./img/new-icon/only-friend.png"/></div></div>
視頻的自動播放問題
在主頁頁面中,這個本來是個視頻,而且決定是讓它自動播放,但是經過查閱資料發現,只能使用這種方式:(autoplay和muted共同使用)
<video src="img/game-icon/login-page.webm" id="video" autoplay muted loop @click="playVideo"></video>
但是這樣使用,也就違背了自動播放視頻的初衷,因為它不會播放音樂。除此以外還有更嚴重的問題,就是在Chrome中,就算是這么設置也有時無法自動播放視頻,而這個所謂的有時,就是初次進入頁面時。當瀏覽器緩存了視頻后,再次重新進入網頁就可以自動播放了。因此不知道有沒有什么解決方案。在這里我還實現了一個功能,就是當點擊視頻的時候可以控制視頻播放和暫停。
playVideo(){ /*播放視頻*/if(this.play === false){video.play();this.play = true;}else{video.pause();this.play = false;}}
輪播圖的實現
在具體看代碼前,先說一下這部分還存在未解決的問題:剛進入頁面的時候,第一次切換圖片沒有過渡效果,暫時不知道該如何解決。其實是有機會避免的,因為之前做過jQuery的輪播圖,但是到了這里用Vue之后,思路有點混亂,所以導致代碼部分出現了一些差錯,又不想進行過多的修改,所以導致為了掩蓋錯誤,去編寫更多代碼區彌補,不能很好的實現效果。所以相關思路可以參考我之前的文章【輪播圖練習三】(雖然代碼比較繁瑣,但至少實現了功能👇)
輪播圖的相關代碼:
<!--輪播圖--><div class="container"><!--圖片--><div id="list"><img src="./img/new-icon/pic1.jpg" alt="1"/><img src="./img/new-icon/pic2.jpg" alt="2"/><img src="./img/new-icon/pic3.jpg" alt="3"/><img src="./img/new-icon/pic4.jpg" alt="4"/><img src="./img/new-icon/pic5.jpg" alt="5"/></div></div><!--兩個箭頭--><a href="javascript:;" class="leftArrow" @click="left"></a><a href="javascript:;" class="rightArrow" @click="right"></a><!--輪播圖圓點--><div id="pointsDiv"><span index="1" class="on" @click="points($event)"></span><span index="2" @click="points($event)"></span><span index="3" @click="points($event)"></span><span index="4" @click="points($event)"></span><span index="5" @click="points($event)"></span></div>
/*箭頭*/.leftArrow,.rightArrow{position: absolute;display: block;width: 2%;height: 7%;top: 30%;background-size: contain;background-repeat: no-repeat;z-index: 999;}.leftArrow{left: 5%;background-image: url("./img/game-icon/pre_nromal.png");}.rightArrow{right: 5%;background-image: url("./img/game-icon/next_normal.png");}.leftArrow:hover{background-image: url("./img/game-icon/pre_hover.png");}.leftArrow:active{background-image: url("./img/game-icon/pre_click.png");}.rightArrow:hover{background-image: url("./img/game-icon/next_hover.png");}.rightArrow:active{background-image: url("./img/game-icon/next_click.png");}/*圖片內容區域*/.container{position: relative;width: 100%;height: 88%;top: 0;overflow: hidden;}/*包含所有圖片的<div>*/#list {width: 500%;height: 100%;position: absolute; /*絕對定位*/z-index: 1;transition-property: all;transition-duration: 0.5s;}/*所有的圖片<img>*/#list img {width: 20%;height: 120%;float: left;}/*包含所有圓點按鈕的<div>*/#pointsDiv {position: absolute;height: 10px;width: 100px;z-index: 2;bottom: 6%;left: 50%;transform: translateX(-50%);}/*所有的圓點<span>*/#pointsDiv span {cursor: pointer;float: left;border: 1px solid #A88230;width: 7px;height: 7px;border-radius: 50%;background: #333;margin-right: 5px;}/*第一個<span>*/#pointsDiv .on,#pointsDiv span:hover{background: #A88230;}
<script type="text/javascript">new Vue({el: '#lolgame',data: {/*輪播圖的本質是:一個很寬的div中存放著幾張圖片,每個圖片占據同樣的大小,*//*這個大小就是在主頁面區域能顯示的大小。那如果要切換到下一張圖,*//*其實就是修改left的值。即第一張圖就是left為0,第二張圖就是left為-100%*//*或者left是圖片的寬度(需要在設計時就考慮好)*//*因此num值的范圍不是1~5,而是0~4*/num: 1, /*記錄圖片位置,但是沒有考慮到數組的原因,num應該為0的,出現了錯誤,導致代碼繁瑣*/first: true /*為自己錯誤買單*//*因為向右切換圖片后 num比正常下標多1,所以需要標記,即:first為true *//*所以只要first為true,那么向左切換圖片,下標num就要-2,否則-1*/},mounted(){/*自動輪播*/this.intervalTime = setInterval(()=>{/*只要向右就將first設置為true*/this.first = true/*去調用right方法*/this.$options.methods.right.bind(this)();this.$options.methods.right();/*每5秒圖片切換1次*/},5000)},methods: {left(){ /*點擊左按鈕*/if(this.first === true){ /*只要圖片向右輪播*/this.num -= 2; /*那么下標要-2*/this.first = false; /*向左輪播后,first為false*/}else{ /*正在向左輪播,只需要下標-1*/this.num -= 1;}/*如果下標減成負數,那就意味著需要切換到最后一張圖片*/if(this.num === -1){this.num = 4}/*獲取到圖片列表,將圖片根據num的值,決定該顯示哪張圖片*/let $list = $('#list'); let per = -(this.num * 100);$list.css('left', per+'%');/*切換圖片后,需要修改下面圓標點的樣式,需要對應*/let index = this.num; /*獲取到當前下標,此時num沒問題*/let preIndex; /*代表著前一個圖片的點*/if(index === 4){ /*如果向左切換到最后一張圖片,那么前一張圖片必然是第一張*/preIndex = 0}else{ /*其他情況,前一張圖片就是num + 1*/preIndex = this.num + 1}/*然后獲取所有的點*/let $points = $('#pointsDiv>span');/*將前一張圖片的點的樣式清除,給當前的點添加樣式*/$points[preIndex].className = '';$points[index].className = 'on'},right(){ /*點擊右按鈕*/this.first = true /*只要向右切換,first就為true*//*之前提到num的范圍是0~4,但是這里向右輪播在設計時沒考慮到,出現了差錯*//*因為num初始值是1,向右輪播四張圖,每次num都+1了,顯然這里num為5才是最后一張圖*/if(this.num === 5){ /*如果向右切換到最后一張圖片*/this.num = 0; /*回到第一張圖*/}/*獲取到圖片列表,將圖片根據num的值,決定該顯示哪張圖片*/let $list = $('#list');let per = -(this.num * 100);$list.css('left', per+'%');this.num += 1;/*切換圖片后,需要修改下面圓標點的樣式,需要對應*/let index = this.num;let preIndex;if(index === 1){ /*如果此時index為1,也就是說上一張圖是最后一張圖*/preIndex = 4 }else{ /*否則上一張圖就會是num-2*/preIndex = this.num - 2}/*然后獲取所有的點*/let $points = $('#pointsDiv>span');/*將前一張圖片的點的樣式清除,給當前的點添加樣式*/$points[preIndex].className = '';$points[index - 1].className = 'on';},points(e){ /*點擊圓點切換圖片*//*獲取span的index值*/let targetIndex = e.target.getAttribute('index')// 只有當點擊的不是當前頁的圓點時才翻頁// 這么實現是有bug的,因為左切換圖片會導致num錯亂,這時點擊圓點切換圖片就會出現問題// 但是我個人暫時就不想再從num為0重新設計了,因此就先這么辦了// 如果全程不點左箭頭,是不會出現bug的if(targetIndex != this.num) {// 先把上一個點的樣式取消this.num += 1;let index = this.num;let preIndex;if(index === 1){preIndex = 4}else{preIndex = this.num - 2}let $points = $('#pointsDiv>span');$points[preIndex].className = '';// 然后給這一個點增加樣式this.num = targetIndex - 1let $list = $('#list');let per = -(this.num * 100);$list.css('left', per+'%');this.num += 1;index = this.num;$points[index - 1].className = 'on';}}}})
</script>
以上就是所有內容。除此以外,在游戲客戶端主頁面的基礎上,再去實現其他標簽的功能的話,涉及到更多英雄素材,比較費時,也不容易實現,如果以后有機會再來嘗試實現吧。
總結
以上是生活随笔為你收集整理的【前端html页面练习】还原英雄联盟客户端的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java线程的6种状态
- 下一篇: Java线程的优先级