做一個略調皮的個人首頁--菜單篇
- #原創
- CSS3
- 單頁面網站模闆
申請達人,去除贊助商連結
由于要重新找工作,是以做了一個自己的個人首頁,覺得還好,是以分享出來,也算是自己的一些記錄。
具體示範可以檢視我的個人首頁。
大體都是一些css3的應用,幹貨實在很少,做來玩樂罷了。
第一次寫這方面的文章,行散神也散,望海涵。
首先,先列出less檔案的公共部分以及常量。
公共類:
- /*居中*/
- .getCenter (@x, @y) {left:50%; right:50%; top:50%; bottom:50%; margin-left:- @x/2; margin-top: - @y/2;}
- /*圓角*/
- .getBorderRadius (@m) {
- border-radius:@m;
- -webkit-border-radius:@m;
- -moz-border-radius:@m;
- -ms-border-radius:@m;
- }
- /*過渡*/
- .geTtransition (@transition) {
- -webkit-transition:@transition;
- -moz-transition:@transition;
- -o-transition:@transition;
- -ms-transition:@transition;
- transition:@transition;
- }
- /*形變*/
- .getTransform (@transform) {
- -webkit-transform:@transform;
- -moz-transform:@transform;
- -o-transform:@transform;
- -ms-transform:@transform;
- transform:@transform;
- }
- /* 陰影 */
- .getBoxShdow (@boxshdow){
- -webkit-box-shadow:@boxshdow;
- -moz-box-shadow:@boxshdow;
- -o-box-shadow:@boxshdow;
- -ms-box-shadow:@boxshdow;
- box-shadow:@boxshdow;
- }
- /*動畫*/
- .getAnimate (@animate) {
- animation: @animate;
- -moz-animation: @animate;
- -webkit-animation: @animate;
- -ms-animation: @animate;
- -o-animation: @animate;
- }
- .getTransform (@transform) {
- -webkit-transform:@transform;
- -moz-transform:@transform;
- -o-transform:@transform;
- -ms-transform:@transform;
- transform:@transform;
- }
- /*形變*/
- .getTransformOrgin (@transform) {
- -webkit-transform-origin:@transform;
- -moz-transform-origin:@transform;
- -o-transform-origin:@transform;
- -ms-transform-origin:@transform;
- transform-origin:@transform;
- }
- /* 梯度漸變 */
- .getGradient(@type, @color1, @color2) {
- background:-moz-linear-gradient(@type, @color1, @color2);/*Mozilla*/
- background:-webkit-linear-gradient(@type, @color1, @color2);/*new gradient for Webkit*/
- background:-o-linear-gradient(@type, @color1, @color2); /*Opera11*/
- background:-ms-linear-gradient(@type, @color1, @color2); /*Ie 11+*/
- filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr= @color1,endcolorstr= @color2,gradientType=0); /*Ie 10-*/
- }
常量:
- @color1:#E8B118; //菜單顔色
- @color2:#DC7913; //菜單顔色
- @color3:#CE1131; //菜單顔色
- @color4:#A71955; //菜單顔色
- @color5:#33619F; //菜單顔色
- @color6:#149B70; //菜單顔色
- @color7:#79B053; //菜單顔色
- @animateTime : 300ms; //動畫時間
- @delay : 50ms; //延時時間
然後先把html的代碼寫出來,總共是7個菜單的标簽,以及5個區域的标簽。
整個頁面的展現形式最終會有五種,分别為 normal left right left right。
- <ul class="indexMenu">
- <li data-type="normal"><span class="glyphicon glyphicon-home" ></span><em class=" rel">我的首頁</em></li>
- <li data-type="left"><span class="glyphicon glyphicon-user " ></span><em class=" rel">我的資訊</em></li>
- <li data-type="top"><span class="glyphicon glyphicon-picture "></span><em class=" rel">我的相冊</em></li>
- <li data-type="right"><span class="glyphicon glyphicon-pencil "></span><em class=" rel">我的随筆</em></li>
- <li data-type="bottom"><span class="glyphicon glyphicon-film "></span><em class=" rel">我的臨摹網站</em></li>
- <li data-type="left"><span class="glyphicon glyphicon-folder-open "></span><em class=" rel">我的工作經曆</em></li>
- <li data-type="right"><span class="glyphicon glyphicon-send "></span><em class=" rel">我的遊戲</em></li>
- </ul>
- <section class="area_main abs ovh"></section>
- <section class="area_right abs"></section>
- <section class="area_left abs"></section>
- <section class="area_top abs"></section>
- <section class="area_bottom abs"></section>
用到了一些boot的glyphicon标簽。大體的結構差不多就是這些代碼就夠了,下面我們來建構第一個頁面。
首先是7個标簽的css樣式:
- .indexMenu{
- display:block; width:100%;height:100%; z-index:5;position:absolute;top:0px;left:0px;
- .geTtransition(all @animateTime ease);
- li {
- width:100%;height:14.285%;color:#FFF; cursor:pointer;position:relative;left:0px;top:0px;
- em{
- line-height:36px;font-size:18px;top:50%;margin-top:-18px;float:right;
- .geTtransition(all @animateTime ease );
- }
- span {
- font-size:36px;top:50%;margin-top:-18px;display:block;width:90px !important;text-align:center; float:right;
- .geTtransition(all @animateTime ease );
- }
- }
- li:hover{padding-right:40px;}
- li:nth-child(1){background:@color1; }
- li:nth-child(1):hover{background:lighten(@color1,10%)}
- li:nth-child(2){background:@color2;}
- li:nth-child(2):hover{background:lighten(@color2,10%);}
- li:nth-child(3){background:@color3;}
- li:nth-child(3):hover{background:lighten(@color3,10%);}
- li:nth-child(4){background:@color4;}
- li:nth-child(4):hover{background:lighten(@color4,10%);}
- li:nth-child(5){background:@color5;}
- li:nth-child(5):hover{background:lighten(@color5,10%);}
- li:nth-child(6){background:@color6;}
- li:nth-child(6):hover{background:lighten(@color6,10%);}
- li:nth-child(7){background:@color7;}
- li:nth-child(7):hover{background:lighten(@color7,10%);}
- }
然後是所有詳細區域的樣式:
- section{
- width:100%;height:100%; background:#FFF; overflow:hidden;.geTtransition(all @animateTime ease);
- }
area_main的樣式:
- . top:0px;left:-100%;padding-left:400px;z-index:6;
- .getBorderRadius(350px);
- .geTtransition(all @animateTime ease @animateTime);
- } area_main {
注意現在的main_area 區域是隐藏在左側的,由于是有五種形态,但是操作的都是這些标簽,是以我把形态的辨別放在了body上,比如normal就是 <body class="type_normal"></body>
是以css的樣式還有這麼一句:
- .type_normal{
- .main_area{left:-400px;}
- }
這樣整個第一種形态就差不多了。之後我們需要做的就是切換形态。我把形态的資訊用data-type的形式寫在了li标簽裡,這樣如果想改的話也很友善。每次切換形态簡單說來就是改變body的class。這樣就會改變css樣式,我們加了過渡和形變的樣式就會呈現動畫效果。這裡我們應用js控制:
- /* 首頁菜單點選後跳轉效果 */
- var menuClickType = {
- 'normal' : function () {}
- , 'left' : function () {}
- , 'top' : function () {}
- , 'right' : function () {}
- , 'bottom' : function () {}
- }
- var $menus = $('.indexMenu li');
- $menus
- /* 首頁菜單點選動作 */
- .click(function () {
- var $this = $(this), type = $this.data('type');//擷取type 展現形态辨別
- menuClickType[type](); //調取相應的方法
- });
這樣基本的架構就搭好啦,開始做left的方法,首先我們先看一下left形态的效果:
然後是left形态的跳轉效果方法:
css樣式:
- .type_left{
- .indexMenu{
- li:hover{
- padding-right:0px;
- margin-left:150px;
- }
- }
- .area_main{
- .geTtransition(all @animateTime ease);
- }
- .area_left{opacity:1;z-index:auto;}
- }
js代碼:
- $body.removeClass().addClass('type_left');
- $menus.css({
- 'left':'-'+ (bodyWidth - 90) +'px'
- ,'top' : '0px'
- ,'height' : bodyHeight/7 + 'px'
- });
這裡解釋一下,由于有很多東西不能單憑css去控制,也需要js輔助區控制。控制的主要屬性為top,left 以及 height,top的控制是以後要用,這裡的從normal 轉換到left 形态,隻是改變了left的值,至于height屬性,是由于以後展現的要求,我把菜單的ul的高設成了0。這樣它才不會阻擋住螢幕,而其中li的高度自然就需要手動的去加上去。
然後在type_left的css中,加入菜單的hover效果(和normal下是不一樣的)。以及main和left區域的效果,這裡我們需要把area_left區域展現出來,并且把.area_main區域收起,由于已經去掉了body上 type_normal 的樣式,是以area_main區域就自動的縮回左邊去了。
最後在加上菜單有順序的向左移動,好像波浪一樣的效果,主要是css3的過渡代碼:
- li:nth-child(1){background:@color1; .geTtransition2(all @animateTime ease, left @animateTime ease @delay * 1)}
- li:nth-child(1):hover{background:lighten(@color1,10%)}
- li:nth-child(2){background:@color2; .geTtransition2(all @animateTime ease, left @animateTime ease @delay * 2)}
- li:nth-child(2):hover{background:lighten(@color2,10%);}
- li:nth-child(3){background:@color3; .geTtransition2(all @animateTime ease, left @animateTime ease @delay * 3)}
- li:nth-child(3):hover{background:lighten(@color3,10%);}
- li:nth-child(4){background:@color4; .geTtransition2(all @animateTime ease, left @animateTime ease @delay * 4)}
- li:nth-child(4):hover{background:lighten(@color4,10%);}
- li:nth-child(5){background:@color5; .geTtransition2(all @animateTime ease, left @animateTime ease @delay * 5)}
- li:nth-child(5):hover{background:lighten(@color5,10%);}
- li:nth-child(6){background:@color6; .geTtransition2(all @animateTime ease, left @animateTime ease @delay * 6)}
- li:nth-child(6):hover{background:lighten(@color6,10%);}
- li:nth-child(7){background:@color7; .geTtransition2(all @animateTime ease, left @animateTime ease @delay * 7)}
- li:nth-child(7):hover{background:lighten(@color7,10%);}
把之前的li标簽的css樣式增加一些東西,這裡就是增加了過渡,給left屬性的過渡增加延時,标簽index越大,延時就越多,這樣就可以做出首頁中的動畫效果啦。
animateTime 和 delay 都是上面設定的常量。
當然我們還要從left能回到 normal 形态上。是以 normal的js代碼是:
- $body.removeClass().addClass('type_normal');
- $menus.css({
- 'left':'0px'
- ,'top' : '0px'
- ,'height' : bodyHeight/7 + 'px'
- });
這樣,從normal 形态 到left 形态的效果就做好了。就是示範中第一個按鈕我的首頁以及第二個按鈕我的資訊的點選效果。
之後來看第三個形态——right形态的效果:
這個菜單是沒有動的,隻是相對應的區域(section)從左側滑了出來,是以這個是很好做的。
css樣式:
- .area_right{
- z-index:6;overflow:hidden;top:0px;left:-100%;padding-left:90px;
- }
- .type_right{
- .indexMenu{
- li{left:0px;}
- }
- .area_main{
- .geTtransition(all @animateTime ease);
- }
- .area_right{
- left:-90px;
- .geTtransition(all @animateTime ease @animateTime);
- }
- .indexMenu{
- li:hover{
- padding-right:0px;
- span{
- .getAnimate(animate_menu @animateTime ease);
- }
- }
- }
- }
js代碼:
- $body.removeClass().addClass('type_right' );
- $menus.css({
- 'left':'0px'
- ,'top' : '0px'
- ,'height' : bodyHeight/7 + 'px'
- });
值得注意的一點事,這三種形态的css代碼中,都有area_main的樣式,但是隻有一句過渡的,不同的地方時有的有延時,有的沒有,這個是考慮normal形态和right形态切換的時候,其實就area_main向左收回,area_right向右展開,如果同時進行,很不友好,是以呢,就加了這個延時。具體的邏輯大家試一下就知道啦。
然後是top和bottom。這兩個其實是一回事,隻不過一個在上一個在下,隻挑一個top說一下即可。
top形态:
bottom形态:
這個是把整個菜單标簽的結構都給換了,以前是 width:100%; height:100%/7。 現在是 反過來了,是以每次做變化之前,都需要把标簽全部移動到上方(或者下方)的螢幕外,然後做變化,再顯示出來。具體動畫效果請參考示範。
具體的cssy樣式:
- .type_top_end{
- .indexMenu{
- height:100%;
- top:-100%;
- }
- .main_area{
- .geTtransition(all @animateTime ease);
- }
- }
- .type_top{
- .indexMenu{
- height:100%;
- top:-100%;
- li {
- height:100% !important;width:14.285%;float:left;left:0px;overflow:hidden;
- .geTtransition3(all 0s ease, top @animateTime ease, background @animateTime ease);
- em{
- position:absolute;bottom:5px;top:auto;width:100%;text-align:center;opacity:0;
- .getTransform(scale(2));
- }
- span {
- top:100%;margin-top:-40px;float:none;left:50%;margin-left:-45px;.getTransform(scale(1));
- }
- }
- li:hover{
- padding-right:0px;
- span{
- opacity:0;
- .getTransform(scale(2));
- }
- em{
- opacity:1;
- .getTransform(scale(1));
- }
- }
- }
- .area_top{opacity:1;z-index:auto;}
- }
這裡有兩個css樣式,type_top_end是最終的顯示結果,type_top可以當做是變形的過程,這個設計有一些蹩腳,當時沒有設計好。
js代碼:
- $body.removeClass().addClass('type_top_end' );
- $menus.css({
- 'left':'0px'
- ,'top' : '0px'
- });
- setTimeout(function () {
- $body.addClass('type_top' );
- $menus.css({
- 'left':'0px'
- ,'top' : '43px'
- });
- } , animateTime);
先收到最上面去,然後setTImeout中 改變top的值,讓其在下來一部分。組成所見的标簽。
這樣,基本的效果就出現了,不過還是有一點的欠缺,具體說來:
第一,從top或者bottom效果便到别的效果時,動畫顯的很混亂;
第二,從top效果換到bottom效果時,也很亂;
第三,由于隻有五種展現形式,不過内容卻有七個,是以left和right是重複的兩個,那麼當從一個left跳轉到另一個left(如示範中第二個标簽——我的資訊跳轉到第六個标簽——我的工作經曆)時,也需要重新設定動畫。
為了解決這三個問題,我們先做一個限定,再次點選同一個标簽,是要屏蔽掉的。代碼如下:
- $menus
- /* 首頁菜單點選動作 */
- .click(function () {
- var $this = $(this), type = $this.data('type'), target = $this.data('target')
- , $area = $('.area_'+ type),flag = $area.data('flag') ? $area.data('flag') : '';
- if($body.hasClass('type_'+ type) && flag == target) return;
- menuClickType[type](); //調取相應的方法
- });
這個屏蔽有兩個判斷,第二個判斷是加内容時候需要的,我們現在隻看第一個即可。
其次是解決第一個問題,即對top以及bottom形态的修正。我們寫一個方法:
- /* type_top type_bottom 修正 */
- function amend_top_bottom () {
- if($body.hasClass('type_top') || $body.hasClass('type_bottom') ){
- $menus.css({
- 'left':'0px'
- ,'top' : '0px'
- });
- return animateTime;
- }
- return 0;
- }
然後在别的click點選事件中,調用這個方法,擷取一個數值,即延時,然後把之後的執行放到一個setTimeOut裡,延時即這個數值。當點選時目前的形态不是top或bottom時,傳回0,即馬上運作,當是這兩種形态時,即先把露出的菜單縮會,然後給一個animateTime的延時,這段延時後在走點選事件的方法,即可。
第二個問題。隻要在top 和bottom 的點選事件中 加一下是否目前形态為彼此的另一個即可,代碼為:
- if($body.hasClass('type_bottom')){
- $body.addClass('type_top' ).addClass('type_top_end').removeClass('type_bottom').removeClass('type_bottom_end');
- $menus.css({
- 'left':'0px'
- ,'top' : '43px'
- });
- else {
- /*之前點選事件的代碼*/
- }
效果可參考從第三個菜單——我的相冊點選到第五個菜單——我的臨摹網站的效果。
最後一個問題。就需要在left和right的方法中加入本身的判斷啦。具體代碼為:
- var time = amend_top_bottom();
- if($body.hasClass('type_right')){
- time = animateTime;
- $body.removeClass();
- }
- setTimeout (function () {
- $body.removeClass().addClass('type_right' );
- $menus.css({
- 'left':'0px'
- ,'top' : '0px'
- ,'height' : bodyHeight/7 + 'px'
- });
- }, time);
簡單說,就是在removeClass 和addClass之間加一個延時,即可。
這樣就達到了大體的效果。不過由于我的特定需求,讓代碼寫的有些随意,不是很好。如果規範一點,每次點選事件都需要判斷這樣幾件事,即:
1:是否是重複點選。
2:如果是重複點選,内容是否變動(5個形态,7個内容),如果改變,則需要添加從本身變本身的動畫。
3:特殊前提(如是否是從top或bottom下變換過來等)。