前陣子可以看到許多單頁式網頁的設計,單頁式網頁就是在一頁裡面把所有要傳達的訊息都傳達完,而網友可以透過捲動捲軸的方式,讓網頁產生類似輪撥的效果。
本堂課完成的結果就像這樣。
註:但也許是因為會控制網友右側捲軸的關係,使網友在使用上的控制感較差,所以近年來這種設計開始變少,取而代之的是視差滾動的效果,也就是再不控制滑鼠捲軸的情況下,當網友滑動捲軸時背後圖層可以產生連帶動畫,例如這個網站的設計fannabee。本次會學習到的函數共包含:
CSS
border-radius:邊框變弧形,可用來製作圓形。
box-shadow:製作邊框的陰影效果。
scrollTop:從頁面最上方到某捲軸位置的距離。
jQuery
$( ).css({"標籤" :"值","標籤" :"值"}):針對某個標籤(包含class、id)修改css樣式。
$( ).height( ):擷取某個屬性的高度。
$( ).resize( ):當某個屬性(例如:視窗)被縮放時。
$( ).offset( ).top:距離最上面的距離,如果是要做左邊的距離,把top改成left。
$( ).scroll( ):當我轉動捲軸時產生效果。
console.log( ):可以透過console(chrome瀏覽器按F12)視窗產生訊息
border-radius:邊框變弧形,可用來製作圓形。
box-shadow:製作邊框的陰影效果。
scrollTop:從頁面最上方到某捲軸位置的距離。
jQuery
$( ).css({"標籤" :"值","標籤" :"值"}):針對某個標籤(包含class、id)修改css樣式。
$( ).height( ):擷取某個屬性的高度。
$( ).resize( ):當某個屬性(例如:視窗)被縮放時。
$( ).offset( ).top:距離最上面的距離,如果是要做左邊的距離,把top改成left。
$( ).scroll( ):當我轉動捲軸時產生效果。
console.log( ):可以透過console(chrome瀏覽器按F12)視窗產生訊息
基本版型設計
找圖
首先,我到Unsplash抓了五張好看的圖片,作為等一下輪撥式網頁的背景,我把這5張圖片都存到images這個資料夾當中。
由於這些下載下來的圖片都是原檔,檔案的容量很大,這會影響到我們之後網頁讀取的速度和順暢度,因此我先都用JPEGmini把檔案容量縮小(參考:縮小圖片檔案大小卻又不失品質的好方法─JPEGmini)。
把圖片放入網頁中
我的想法是利用背景圖片的方式來呈現這些圖片,而且我希望每一張圖片呈現的大小都會隨著瀏覽器的高度而變,占滿整個頁面,所以我把它分成5個區塊,分別取不同的class。
然後在css的地方,我用background-image的方式放入背景圖片,background-size: cover設成cover,希望它能夠盡可能的放滿整個背景頁面。height:100vh的地方,我們用之前說明的vh來使用,意思是它的高度要是整個瀏覽器視窗的高度,而且這個高度可以隨著視窗的縮放而改變(參考:好用的css 3新單位vh vw ─ 讓你的圖片可以隨著螢幕大小而不同)。
透過上述這兩段程式碼,背景圖片就可以完整的呈現在整個頁面上了,而且既使視窗有縮放, 背景圖片還是會佈滿整個頁面,如下圖:
加上導覽標籤
導覽標籤的用意就是讓網友知道現在是在第幾頁,一般來說用個圓點就可以了。寫法如下:
我利用表單標籤<ul></ul>來建立表單,因為我們有5張圖,所以一共會有5組的標籤。
接下來,我想直接用CSS的方法來建立標籤(圓點)
這裡分了兩個部分:
在nav這個class中,我把位置設成fixed,位置則是設在右方,高度大約50%的地方(這樣做雖然可以隨著螢幕縮放而改變nav的位置,但是它並不是真的垂直置中,後面會在說明垂直置中的方式)。
在li這個標籤中,我們則是希望設定一個高和寬為10px的圓點,要變成圓點我們只需要使用border-radius這個指令就可以了,當border-radius的大小超過長和寬的一半時,它就變變成圓形。box-shadow這個指令則是用來製造陰影的,因為我希望的我圓點更有立體感。list-style-type: none則是希望把原本ul標籤會有的標點拿掉。
完成後的結果會長的像這樣子:
透過jQuery讓導覽列垂直置中
在之前整理的CSS垂直置中的方法這篇文章中,我們已經說明了許多不同的垂直置中方法,這裡因為我們的position是設定成fixed的關係,所以並不適合使用margin+position或inline-block這些方法。那我們到底該怎麼辦呢?這時候只好用jQuery來解決這個問題了!
寫法是這樣的
匯入jQuery
一開始一樣要記得匯入jQuery
計算垂直置中的高度
接著我們的概念是這樣的,我們希望把nav這個class的高度設成是瀏覽器高度的一半,這時候top就應該設成是二分之一的視窗高度(window height)減掉二分之一的導覽列高度(nav height),如下圖:
接著,我們就把這樣的概念用jQuery的語法寫出來:
這裡我們設定一個變數,叫做pos,它的高度會是window(瀏覽器可視範圍)高度的一半,減掉導覽列高度的一半(註:為什麼是用window而不是body可參考這篇計算網頁底部位置),要擷取某個屬性的高度時,我們可以用$( ).height( )然後我們要用之前學過的$().css()這個語法,讓導覽列的高度會在導覽器的位置垂直置中。
但這麼做還不夠,因為當我們縮放視窗的時候,這個導覽列並不會隨著縮放而垂直置中,那麼該怎麼做呢?
當網頁縮放時仍能垂直置中
這時候我們會用到一個新的語法,叫做$( ).resize ( ),我們希望當我們的瀏覽器視窗被縮放時,會幫我們重新計算pos的高度。
這時候,不管你的視窗怎麼縮放,右邊的導覽列都會一直垂直置中了。
我們也可以讓我們的程式碼更簡潔一點,乾脆寫成一個叫做center的函數
點選導覽列移動到指定頁面
scrollTop
為了讓導覽列移動到指定的頁面,我們會用到上一堂課所學到的$( ).animate( )指令(參考: animate使用:製作輪撥式廣告),搭配上scrollTop這個語法。
那我們來看看要怎麼寫:
scrollTop基本的用法,就是告訴它你要到距離網頁頂端幾像素的。這段語法的意思是,當我點第一個按鈕時,移動到距離網頁頂端0像素的地方(也就是頁頂。至於我們要對誰移動到頁頂這個很重要,我們同時填了html和body,之所以要填兩個的主要原因在於,整個網頁在IE和Firefox中被稱做html,但在chomre中稱做body,所以如果你只填其中一個,都可能會讓其他瀏覽器失效。兩個中間則用「,」加以區隔就可以了。
這時候,雖然點選導覽列時,就會產生捲動旁邊捲軸的動畫,但是這麼做並沒有辦法讓我們到達想要的位置,因為我們背景圖片的高度在最上面的地方是設定vh,也就是會隨著視窗大小而變,這使我們沒辦法給定一個固定的px值,請它轉到那個位置。那麼我們可以怎麼解決這樣的問題呢?
.offset( )
為了解決這個問題,我們會用到$( ).offset( ).top,寫法是這樣:
我們可以把offset想成是「距離」,後面多了.top,也就是「到最上面的距離」,而前面有一個selector,分別是p01、p02、p03、...,這是我們div取的class名稱,所以第一段的語法的意思就會是p01這個div到最上面的距離,第二段的語法就是p02這個div到最上面的距離。
因為我們前面有加scrollTop,所以會分別移動到該div的位置。
寫成回圈
寫法如下:
首先,要知道導覽列中有幾個按鈕,可以用$( ).length這個語法,並且把它取名為變數num_li。
接著,我們用for( ){ }撰寫回圈,要再記得一次,for裡面是要用「;」間隔,接著我們要把i這個變數引入click當中,所以function的地方要寫成{id:i},funtion(e){},同樣的,這裡的id、e都是可以自己取的變數,data則是關鍵字。因為我們的圖片是從1開始編號,而不是從0開始編號,所以我把page這個引進i的變數都加上1,最後在把它放入scollTop後。
為了讓我們的動畫更完美,我們也可以加入一段$("html,body").stop()再for迴圈裡面的最上面,避免白木的網友一直點我們的游標,導致網站動畫秀斗。
根據哪個游標被點擊,來改變該游標的顏色
點選那個游標,哪個游標就變色
我們希望導覽列能夠根據我們目前所在的頁面來顯示不同的顏色,我們可以透過$( ).css( )來達到這樣的效果,寫法如下:
這裡分成兩個部分,我們先看下面那行,這行的意思是,當某個li被點到的時候,這個li的背景顏色要改變(這裡是變成綠色))。上面那行則是會了讓所有的圓點都變回白色(除了被點到的那個),沒有這行的話,最後會變成全都是綠色點。
第一個游標預設成被點擊的狀態
因為網友一進來就是看到第一頁,所以第一個游標照理來說一開始就是綠色的,因此我們要把第一個游標加上綠色:
根據捲軸位置,來改變該游標的顏色
再來這個部分就比較特別一些,我們希望導覽列的游標,除了被點擊時會變色外,也要能根據我滑鼠移到的圖片而改變,為了達到這個效果,我們會用到$( ).scroll( )這個指令,這個指令是當我轉動捲軸時能夠產生相對應的效果。同時,我們還要統整上面所學到的語法。
我們可以利用如下的語法達到我們想要的效果:
因為程式碼有點長,我們先分開來看,首先這一段
if($(window).scrollTop()>=$(".p01").offset().top && $(window).scrollTop()<$(".p02").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(0)").css("background-color","#46dd46")這段的意思指的是說,如果我目前視窗範圍的頂端($(window).scrollTop())大於等於第一頁的頂端($(".p01").offset().top)),且小於第二頁的頂端($(".p02").offset().top))時,則把第一個導覽列的點(".nav li:eq(0)")改成綠色。
接著第二段是
}else if($(window).scrollTop()>=$(".p02").offset().top && $(window).scrollTop()<$(".p03").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(1)").css("background-color","#46dd46")意思指的是,如果我目前視窗範圍的頂端($(window).scrollTop())大於等於第二頁的頂端($(".p02").offset().top)),而且小於第三頁的頂端($(".p03").offset().top))時,則把第二個導覽列的點(".nav li:eq(1)")改成綠色。
其他的就是繼續這樣else if 下去,完整的程式碼長的像這樣:
$(window).scroll(function(){ if($(window).scrollTop()>=$(".p01").offset().top && $(window).scrollTop()<$(".p02").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(0)").css("background-color","#46dd46") }else if($(window).scrollTop()>=$(".p02").offset().top && $(window).scrollTop()<$(".p03").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(1)").css("background-color","#46dd46") }else if($(window).scrollTop()>=$(".p03").offset().top && $(window).scrollTop()<$(".p04").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(2)").css("background-color","#46dd46") }else if($(window).scrollTop()>=$(".p04").offset().top && $(window).scrollTop()<$(".p05").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(3)").css("background-color","#46dd46") }else if($(window).scrollTop()>=$(".p05").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(4)").css("background-color","#46dd46") } })
利用console.log( )
console.log可以這樣用,例如我想知道p04這個div到網頁頂端的距離是多少($(".p04").offset( ).top),同時我也想知道,我的捲軸目前到最頂端的距離有多少($(window).scrollTop( )),就可以輸入下面那段console.log
console.log("offset(p01):"+$(".p01").offset().top) console.log("offset(p02):"+$(".p02").offset().top) console.log("offset(p03):"+$(".p03").offset().top) console.log("offset(p04):"+$(".p04").offset().top) console.log("offset(p05):"+$(".p05").offset().top) console.log("scrollTop:"+$(window).scrollTop())
這時候用chrome預覽畫面時,按下F12,當我捲動捲軸時就會出現記錄了,這樣我就可以進行偵錯,也可以知道我想知道的訊息。
至於這種寫法要怎麼讓程式碼更精簡我目前還沒想到,若有人知道也歡迎留言告知!
結果
這次完整的程式碼如下:
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>單頁輪撥式網站設計</title> <!-- 匯入jQuery --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(document).ready(function(){ //根據捲軸的位置改變右方導覽列游標的顏色 $(window).scroll(function(){ if($(window).scrollTop()>=$(".p01").offset().top && $(window).scrollTop()<$(".p02").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(0)").css("background-color","#46dd46") }else if($(window).scrollTop()>=$(".p02").offset().top && $(window).scrollTop()<$(".p03").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(1)").css("background-color","#46dd46") }else if($(window).scrollTop()>=$(".p03").offset().top && $(window).scrollTop()<$(".p04").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(2)").css("background-color","#46dd46") }else if($(window).scrollTop()>=$(".p04").offset().top && $(window).scrollTop()<$(".p05").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(3)").css("background-color","#46dd46") }else if($(window).scrollTop()>=$(".p05").offset().top){ $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 $(".nav li:eq(4)").css("background-color","#46dd46") } }) //點選右方導覽列時會到指定圖片 var num_li=$("li").length for(i=0;i<=num_li;i++){ $(".nav li:eq("+i+")").click({id:i},function(e){ $("html,body").stop() $(".nav li").css("background-color","white")//除了被點擊到的游標,其他都恢復成原來的顏色 page=e.data.id+1 $("html,body").animate({"scrollTop":$(".p0"+page).offset().top}) $(".nav li:eq("+e.data.id+")").css("background-color","#46dd46")//被點擊到的游標變色,前面的selector用this也可以 }) } //一進入網頁時,將導覽列垂直置中計算導覽列置中的位置 center() //縮放網頁時,將導覽列垂直置中 $(window).resize(function(){ center() }) //計算導覽列垂直置中的高度 function center(){ pos=$(window).height()/2-$(".nav").height()/2 $(".nav").css("top",pos) } }) </script> <style> *{ padding:0; margin:0; } /* 插入背景圖片 */ .p01{ background-image:url(images/p01.jpg); background-size:cover; background-repeat: no-repeat; height:100vh; } .p02{ background-image:url(images/p02.jpg); background-size:cover; background-repeat: no-repeat; height:100vh; } .p03{ background-image:url(images/p03.jpg); background-size:cover; background-repeat: no-repeat; height:100vh; } .p04{ background-image:url(images/p04.jpg); background-size:cover; background-repeat: no-repeat; height:100vh; } .p05{ background-image:url(images/p05.jpg); background-size:cover; background-repeat: no-repeat; height:100vh; } /* 插入導覽列 */ .nav{ position: fixed; top:50%; right:0px; cursor:pointer; } li{ width:10px; height:10px; margin: 10px; background-color: white; border-radius: 5px; box-shadow: 1px 1px 1px rgba(0,0,0,0.5) inset,-1px -1px 1px rgba(0,0,0,0.5) inset; list-style-type: none; } h1{ font-size:60px; color:ghostwhite; text-shadow:0px 0px 15px black; } </style> </head> <body> <div class="container"> <div class="nav"> <ul> <li style="background-color:#46dd46"></li> <li></li> <li></li> <li></li> <li></li> </ul> </div> <div class="p01"><h1>Page 1</h1></div> <div class="p02"><h1>Page 2</h1></div> <div class="p03"><h1>Page 3</h1></div> <div class="p04"><h1>Page 4</h1></div> <div class="p05"><h1>Page 5</h1></div> </div> </body> </html>寫的好辛苦阿!讓我們趕快來看一下結果吧!
0 意見:
張貼留言