本文共 14813 字,大约阅读时间需要 49 分钟。
写下博客用于自我复习和总结,方便我之后遇到相关问题后能迅速找到解决方案。但是个人水平能力有限,解决方案可能比较复杂且繁琐,因此仅供各位参考,希望某些解决方案可以给各位提供一些思路。如果您有更好的解决方案也可以在评论区提出。
在仿写客户端的过程中,我使用了HTML、CSS、JavaScript、jQuery、Vue
其中JS和jQuery用来实现DOM操作(主要还是用jQuery) => 那么为什么不用Vue来实现?首先,本人还在学习状态,模仿客户端界面是一时兴起,想着做点什么练练手,看看各种复杂的功能该如何实现,也没有接触过项目,不知道规范,因此才混合起来使用这些技术,在我的知识能力范围内来说,这样实现功能会更加轻松。
而且在编写代码前,我对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的用法、按钮渐变效果左下方区域的文字内容,本来我是自己贴图 + 用三个div设计的,后来发现lol素材里,它有一整张图片(除了红色边框中的内容外),那就直接拿来用了。红色边框内的文字,是一段超链接,我们只需要给它定位就可以了。
右侧区域涉及到的用法:加载效果(转动)、区域内容的转化、音乐的开关、登录功能
在右侧区域,下面看到的logo的动态效果是lol的素材。
注:img可以加载gif图片,因此这里才是动态效果,而如果是webm格式的,就比较麻烦了,在之后会提到这方面的问题。/*左侧显示区域的整体样式*/ .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。.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"); }
查看详情
/*查看详情的样式*/ .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的去设计,这种方式挺简单的。更复杂的可以考虑canvas。
(但是实际上,后来发现lol的按钮是图片效果,在lol素材里可以找到,这就方便很多了)
之后所有的渐变按钮都是这种方式,下面这个a中的图片,就是采用上面提到的img方式。
页面转化是根据数字的变化,当安全检测值到100%,就“跳转”。这部分就很简单了,数据绑定 + v-cloak(防止表达式闪烁)
{ {finish}}%
然后在vue的mounted生命周期中,直接设置定时器,模拟安全检测效果,并在结束时清除定时器。
mounted(){ /*刚进入页面就会直接进行安全检测*/ this.intervalTime = setInterval(()=>{ this.finish += 20 /*当安全检测完成时,跳转到登录页面,且清除定时器*/ if(this.finish === 100){ this.right = false clearInterval(this.intervalTime) } },1000) },
在vue里设置了一个属性right,其初始值是true。当安全检测结束后,right为false,然后触发v-if:
....正在进行安全检测:
{ {finish}}%
那么这种用法将会是之后所有 部分区域页面内容变化的实现方式 (不是v-if就是用的v-show),也就是模拟出了类似单页应用的效果。而将这两个div都设置同一个类,也就保证了切换后,它们最外围容器的位置、样式都是一样的。
但是这种方式肯定不能和vue-router相提并论。首先这种是有切换损耗的,并且不可能实现多次的转换(比如v-if只能用作两部分内容的切换,v-show也类似,但是v-show可以让多个内容同时显示或隐藏)
音频采用的是audio,只要不给其添加controls属性,那么在页面中就看不到这个音乐播放器,我们只要在音乐的图标中,添加一个开关的v-if(切换图片)和@click事件,就完成了这部分内容。
methods: { music(){ /*音乐相关信息*/ this.ok = !this.ok if(this.ok === false){ player.src = './img/login-icon/sound.mp3'; player.play(); }else{ player.src = ''; player.pause(); } } }
首先这里 QQ登录 - 微信登录、切换至快速登录 - 使用其它帐号登录 ,部分内容的转换采用的都是v-if。
然后是Vue中全部内容:
那么通过之前的说明,我们要改变部分区域的内容,我们使用v-if就可以实现。也就是当我们点击某个按钮后,修改了data中的数据,从而导致v-if v-else触发,在同一个区域就展示了不同的内容。
想要实现:我已详细阅读并同意 被选择后才能进入下一步,就只需要绑定checked:
我已详细阅读并同意
那么设置成:当点击按钮,导致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的过渡效果
transition标签是Vue中的方法,被该标签包裹的内容,就会在内容改变时,产生过渡效果。使用方法很简单,而且频繁切换也是没问题的。如果是css中设置的过渡和动画效果,是没办法实现返程的,也就是说显示需要触发一次,关闭再触发一次。而Vue的transition在设置的时候,就可以设计显示效果和隐藏效果,很方便。
/*服务器列表动画*/ .serviceOpen-leave-active, .serviceOpen-enter-active{ transition: all 1s; } .serviceOpen-leave-to, .serviceOpen-enter{ opacity: 0; }
在这里主要是进度条的实现
完整代码:
League of Legends 正在载入
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部分:
进度条的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项目中才能做到了。除此以外,都是拿到素材,为其定位和设置样式了。
然后上方区域还有一个就是鼠标移动到头像时,相应内容的显现对于右侧好友区域,因为那些图标都需要素材,我又没有找到的情况下,就去自己截了图。对于好友区域上下方的各按钮的触发就没有实现功能了(根据之前的功能实现,其实这部分很简单了)
然后右侧区域还有一个就是好友列表下拉栏的实现对于主页内容区域,除去素材的定位和元素样式,重点就是轮播图的实现
最后简单说一下视频的自动播放
X
/*刚进入游戏的广告*/ .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%; }
打开的详细内容区,我又把它分为三个区域。最上方区域就是用background,中间区域的头像框和名字、下面区域的文字内容,因为没有具体的素材,再加上只有定位和样式的设计,所以都是采用截图的方式完成了。
但是这样使用,也就违背了自动播放视频的初衷,因为它不会播放音乐。除此以外还有更严重的问题,就是在Chrome中,就算是这么设置也有时无法自动播放视频,而这个所谓的有时,就是初次进入页面时。当浏览器缓存了视频后,再次重新进入网页就可以自动播放了。因此不知道有没有什么解决方案。在这里我还实现了一个功能,就是当点击视频的时候可以控制视频播放和暂停。
playVideo(){ /*播放视频*/ if(this.play === false){ video.play(); this.play = true; }else{ video.pause(); this.play = false; } }
在具体看代码前,先说一下这部分还存在未解决的问题:刚进入页面的时候,第一次切换图片没有过渡效果,暂时不知道该如何解决。其实是有机会避免的,因为之前做过jQuery的轮播图,但是到了这里用Vue之后,思路有点混乱,所以导致代码部分出现了一些差错,又不想进行过多的修改,所以导致为了掩盖错误,去编写更多代码区弥补,不能很好的实现效果。所以相关思路可以参考我之前的文章【】(虽然代码比较繁琐,但至少实现了功能👇)
轮播图的相关代码:
/*箭头*/ .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; } /*包含所有图片的*/ #list { width: 500%; height: 100%; position: absolute; /*绝对定位*/ z-index: 1; transition-property: all; transition-duration: 0.5s; } /*所有的图片 */ #list img { width: 20%; height: 120%; float: left; } /*包含所有圆点按钮的*/ #pointsDiv { position: absolute; height: 10px; width: 100px; z-index: 2; bottom: 6%; left: 50%; transform: translateX(-50%); } /*所有的圆点 */ #pointsDiv span { cursor: pointer; float: left; border: 1px solid #A88230; width: 7px; height: 7px; border-radius: 50%; background: #333; margin-right: 5px; } /*第一个*/ #pointsDiv .on, #pointsDiv span:hover{ background: #A88230; }
以上就是所有内容。除此以外,在游戏客户端主页面的基础上,再去实现其他标签的功能的话,涉及到更多英雄素材,比较费时,也不容易实现,如果以后有机会再来尝试实现吧。
转载地址:http://mlyki.baihongyu.com/