在本教程中,我們將創建一個充滿氣泡的圖像庫,以獨特的方式顯示您的圖像。這個想法是用一種圓形的方式顯示相冊的縮略圖,這樣用戶就可以通過移動滑鼠來自動滾動它們。點擊一個縮略圖將會放大一個大的圓圈和完整的圖像,將會自動調整大小以適應屏幕。在圖像中導航會將當前的圖像滑動到一邊,使新的圖像以類似變焦的方式出現。
我們將使用Manos Malihu的絕妙的縮略圖滾動條,你可以在這裡找到:Manos Malihu的縮略圖滾動條。
這些美麗的照片是由天才的geishaboy500拍攝的,你可以在他的flickr照片流上找到更多令人驚嘆的照片:
好的,讓我們開始吧!
標記
讓我們從創建HTML結構開始。我們將會有相當多的元素,所以我們將從我們查看完整圖像時出現的頂部菜單開始:
<div id="top_menu"><span id="description"></span><a id="back" href="#"><span></span>back</a><div><span>Album 1</span><span> / Shot 1</span></div></div>
我們需要一個選項,可以返回到縮略圖視圖、描述區域和顯示我們當前正在查看的圖像的信息區域。當我們點擊縮略圖時,這個元素就會顯示出來。空span將用於添加一個小的後箭頭。
我們還需要一個加載器元素:
<div id="loader"></div>
現在,讓我們看一下標題元素,我們將把主h1元素放到gallery標題中:
<div id="header" style="top:-90px;"><!--top 30 px to show--><h1>Bubbleriffic<span>jQuery Image Gallery</span></h1></div>
當我們加載頁面時,我們希望將這個元素從頂部滑動,所以我們最初將最高值設置為- 90像素。在JavaScript中,我們把它動畫到30像素。您還可以將此樣式添加到樣式表中,而不是使用內聯樣式。
下一個元素將是縮略圖包裝,它將擁有所有的縮略圖。由於我們將使用Manos的縮略圖滾動條,我們將在該結構上建立標記。三張專輯將有三個滾動的容器,其中將有「tshf_container」類:
<div id="thumbnails_wrapper" style="top:-255px;"><!-- top:110px to show--><div id="tshf_container1" ><div><div><div><div><a href="#"><img src="images/albums/album1/thumbs/1.jpg" alt="Description" /></a><span></span></div></div><div> ... </div></div></div></div><div id="tshf_container2" > ... </div><div id="tshf_container3" > ... </div></div>
將圖像保存在div中的空span將被用於覆蓋圖像上的一個洞,使縮略圖看起來像小氣泡。
現在我們將加入黃色氣泡,當我們想要查看完整的圖像時,會被用來創建像隧道效應這樣的泡泡。
<div><img id="bubble" src="images/bubble.png" alt=""/></div>
使用導航的完整圖像視圖的預覽容器將具有以下結構:
<div id="preview"><a id="prev_image" href="#"></a><a id="next_image" href="#"></a></div>
頁腳可以用來添加一些信息:
<div><!-- Add something here --></div>
讓我們看看它的風格!
CSS
首先,我們將重置樣式並定義一些連結、列表和正文的一般屬性:
*{ margin:0; padding:0;}a{ text-decoration:none; outline:none;}ul{ list-style:none;}body{ background:#222 url(../bg.jpg) repeat top left; font-family:"Trebuchet MS", "Myriad Pro", Helvetica, sans-serif; font-size:13px; color: #fff; text-transform:uppercase; text-shadow:0px 0px 1px #fff; letter-spacing:1px; overflow:hidden;}
當我們查看完整的圖片時出現的頂部菜單將有以下樣式:
.top_menu{ height:30px; line-height:30px; position:absolute; top:-30px; left:0; width:100%; overflow:hidden; background:#010101; border-bottom:1px solid #000; z-index:100; -moz-box-shadow:0px 0px 4px #010101; -webkit-box-shadow:0px 0px 4px #010101; box-shadow:0px 0px 4px #010101;}
(如果你知道你的文本只在一個特定的元素中佔據一行,那麼你可以將該元素的行高設置為它的高度,以使包含的文本垂直居中。)
為了隱藏元素,我們將頂部設置為- 30像素。
後面的連結將有以下風格:
.top_menu .back{ position:absolute; top:0px; left:10px; height:30px; line-height:30px; cursor:pointer; color:#aaa;}
我們將為後面的連結添加一個小箭頭圖標,它實際上具有與導航元素相同的背景圖像。我們使用雙倍的寬度,這樣我們可以重複圖像兩次:
.top_menu .back span{ width:14px; height:30px; display:block; float:left; background:#000 url(../images/prev.png) repeat-x center left; margin-right:5px; opacity:0.5;}.top_menu .back:hover{ color:#fff;}.top_menu .back:hover span{ opacity:0.9;}
描述將以中心為中心:
.top_menu span.description{ font-style:italic; position:absolute; width:100%; text-align:center; top:0px; left:0px; height:30px; line-height:30px;}
信息將會向右浮動:
.top_menu .info{ float:right; margin-right:10px;}
現在讓我們來設計主標題。我們會把它定位,因為我們想讓它從頂部開始動畫我們會給它一個黃色背景色和一些漂亮的盒子陰影:
.header{ height:80px; position:absolute; top:30px; left:0px; width:100%; overflow:hidden; z-index:90; background-color:#ffd800; -moz-box-shadow:0px 0px 10px #010101; -webkit-box-shadow:0px 0px 10px #010101; box-shadow:0px 0px 10px #010101;}h1{ font-size:60px; padding-left:20px; color:#010101; line-height:80px; text-shadow:1px 1px 1px #000;}h1 span{ font-size:16px; float:right; margin-right:20px;}
在我們設計縮略圖包裝之前,先看看其他元素的樣式。
完整的圖像將被完全定位,但是我們將在JavaScript中設置它的最終位置:
.preview img{ position:absolute; left:0; top:0; -moz-box-shadow:1px 1px 5px #111; -webkit-box-shadow:1px 1px 5px #111; box-shadow:21px 1px 5px #111; -webkit-box-reflect: below 5px-webkit-gradient( linear, left top, left bottom, from(transparent), color-stop(0.8, transparent), to(rgb(255, 216, 0)) );}
我們將為webkit瀏覽器和一些不錯的框陰影添加一些不錯的反射。
footer的風格幾乎和top菜單一樣,除了定位和其他細節,比如邊框:
.footer{ z-index:100; height:30px; line-height:30px; text-align:center; font-size:10px; background:#010101; border-top:1px solid #000; position:absolute; bottom:0px; left:0px; width:100%; -moz-box-shadow:0px 0px 4px #010101; -webkit-box-shadow:0px 0px 4px #010101; box-shadow:0px 0px 4px #010101;}.footer a{ color:#999; text-decoration:none; margin:40px;}
加載元素將被放置在頁面的中間,我們通過將邊框半徑設置為其寬度/高度的一半來實現。
.loader{ display:none; width:200px; height:200px; background: #000 url(../images/ajax-loader.gif) no-repeat center center; position:fixed; top:50%; left:50%; margin:-100px 0px 0px -100px; opacity: 0.7; z-index:9999; -moz-border-radius:100px; -webkit-border-radius:100px; border-radius:100px;}
導航元素將有以下常見樣式:
a.next_image,a.prev_image{ width:50px; height:50px; position:fixed; top:50%; margin-top:-25px; cursor:pointer; opacity:0.7; z-index:999999; -moz-box-shadow:0px 0px 3px #000; -webkit-box-shadow:0px 0px 3px #000; box-shadow:0px 0px 3px #000; -moz-border-radius:25px; -webkit-border-radius:25px; border-radius:25px;}a.next_image:hover,a.prev_image:hover{ opacity:0.9;}
不同的風格是
a.next_image{ background:#000 url(../images/next.png) no-repeat center center; right:-50px;}a.prev_image{ background:#000 url(../images/prev.png) no-repeat center center; left:-50px;}
最初,它們都是隱藏的,這就是為什麼我們要把它們的左/右定位設置為它們寬度的負值。
現在,我們來設計縮略圖包裝:
.thumbnails_wrapper{ position:absolute; top:-255px; left:0px; width:100%; -moz-box-shadow:0px 3px 5px #000; -webkit-box-shadow:0px 3px 5px #000; box-shadow:0px 3px 5px #000;}
氣泡圖像將被放置在頁面的中心,並且有一個寬度和高度為0。我們將在JavaScript中激活它:
.bubble img{ position:fixed; top:50%; left:50%; width:0px; height:0px;}
現在,我們將修改Manos縮略圖滾動條的樣式:
.tshf_container{ height:85px; position:relative; width:100%; background:#ffd800;}.tshf_container .thumbScroller{ position:relative; width:100%; overflow:hidden;}.tshf_container .thumbScroller,.tshf_container .thumbScroller .container,.tshf_container .thumbScroller .content{ height:85px;}.tshf_container .thumbScroller .container{ position:relative; left:0;}.tshf_container .thumbScroller .content{ float:left;}.tshf_container .thumbScroller .content div{ height:100%; position:relative;}.tshf_container .thumbScroller img{ border:none;}.tshf_container .thumbScroller .content div a{ display:block; height:85px; width:85px;}.tshf_container .thumbScroller .content div a img{ width:85px;}.tshf_container .thumbScroller .content div a:hover{ border-color:#fff;}
我們將使用額外的跨度來添加我們的氣泡覆蓋:
.tshf_container .thumbScroller .content span{ cursor:pointer; position:absolute; width:85px; height:85px; top:0px; left:0px; background:transparent url(../images/thumb_overlay.png) no-repeat top left;}.tshf_container .thumbScroller .content div:hover span{ background:transparent url(../images/thumb_overlay_hover.png) no-repeat top left;}
這就是所有的風格。現在,讓我們加入魔法!
JavaScript
首先,我們將包括以下腳本:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script><script type="text/javascript" src="js/jquery.easing.1.3.js"></script><script type="text/javascript" src="js/jquery.thumbnailScroller.js"></script>
首先,我們將緩存一些重要的元素,並定義一些索引:
var $thumbnails_wrapper = $('#thumbnails_wrapper'), $thumbs = $thumbnails_wrapper.find('.tshf_container').find('.content'), $top_menu = $('#top_menu'), $header = $('#header'), $bubble = $('#bubble'), $loader = $('#loader'), $preview = $('#preview'), $thumb_images = $thumbnails_wrapper.find('img'), total_thumbs = $thumb_images.length, $next_img = $('#next_image'), $prev_img = $('#prev_image'), $back = $('#back'), $description = $('#description'), //current album and current photo//(indexes of the tshf_container and content elements) currentAlbum = -1, currentPhoto = -1;
然後,我們將顯示加載元素(直到所有的縮略圖都被加載),並調用打開相冊的函數:
$loader.show();//shows the main menu and thumbs menuopenPhotoAlbums();
這就是這個函數的樣子:
function openPhotoAlbums(){ //preload all the thumb imagesvar cnt_loaded = 0; $thumb_images.each(function(){ var $thumb = $(this); var image_src = $thumb.attr('src'); $('<img/>').load(function(){ ++cnt_loaded; if(cnt_loaded == total_thumbs){ $loader.hide(); createThumbnailScroller(); //show the main menu and thumbs menu$header.stop() .animate({'top':'30px'},700,'easeOutBack'); $thumbnails_wrapper.stop() .animate({'top':'110px'},700,'easeOutBack'); } }).attr('src',image_src); }); }
這個函數「createThumbnailScroller()」將使縮略圖在Manos的腳本之後可以滾動,但是我們稍後會講到。
接下來,我們將定義單擊縮略圖時會發生什麼。
$thumbs.bind('click',function(e){ //show loading image$loader.show(); var $thumb = $(this), //source of the corresponding large image img_src = $thumb.find('img.thumb') .attr('src') .replace('/thumbs',''); //track the current album / photo currentPhoto= $thumb.index(), currentAlbum= $thumb.closest('.tshf_container') .index(); //displays the current album and current photo updateInfo(currentAlbum,currentPhoto); //preload the large image $('<img/>').load(function(){ var $this = $(this); //record the size that the large image //should have when it is shown saveFinalPositions($this); //margin_circle is the diameter for the //bubble imagevar w_w = $(window).width(), w_h = $(window).height(), margin_circle = w_w + w_w/3; if(w_h>w_w) margin_circle = w_h + w_h/3; //the image will be positioned on the center,//with width and height of 0px$this.css({ 'width' : '0px', 'height' : '0px', 'marginTop' : w_h/2 +'px', 'marginLeft': w_w/2 +'px' }); $preview.append($this); //hide the header$header.stop().animate({'top':'-90px'},400, function(){ $loader.hide(); //show the top menu with the back button,//and current album/picture info$top_menu.stop() .animate({'top':'0px'},400,'easeOutBack'); //animate the bubble image$bubble.stop().animate({ 'width' : margin_circle + 'px', 'height' : margin_circle + 'px', 'marginTop' : -margin_circle/2+'px', 'marginLeft': -margin_circle/2+'px' },700,function(){ //solve resize problem $('BODY').css('background','#FFD800'); }); //after 200ms animate the large image//and show the navigation buttons setTimeout(function(){ var final_w = $this.data('width'), final_h = $this.data('height'); $this.stop().animate({ 'width' : final_w + 'px', 'height' : final_h + 'px', 'marginTop' : w_h/2 - final_h/2 + 'px', 'marginLeft': w_w/2 - final_w/2 + 'px' },700,showNav); //show the description$description.html($thumb.find('img.thumb').attr('alt')); },200); }); //hide the thumbs$thumbnails_wrapper.stop() .animate({ 'top' : w_h+'px' },400,function(){ //solve resize problem $(this).hide(); }); }).attr('src',img_src); });
當我們點擊導航的「下一個」元素時,我們希望發生以下情況:
$next_img.bind('click',function(){ //increment the currentPhoto ++currentPhoto; //current album:var $album = $thumbnails_wrapper.find('.tshf_container') .eq(currentAlbum), //the next element / thumb to show$next = $album.find('.content').eq(currentPhoto), $current = $preview.find('img'); if($next.length == 0 || $current.is(':animated')){ --currentPhoto; return false; } else{ $loader.show(); updateInfo(currentAlbum,currentPhoto); //preload the large imagevar img_src = $next.find('img.thumb') .attr('src') .replace('/thumbs',''), w_w = $(window).width(), w_h = $(window).height(); $('<img/>').load(function(){ var $this = $(this); //record the size that the large image //should have when it is shown saveFinalPositions($this); $loader.hide(); $current.stop() .animate({'marginLeft':'-'+($current.width()+20)+'px'},500,function(){ //the current image gets removed $(this).remove(); }); //the new image will be positioned on the center,//with width and height of 0px$this.css({ 'width' : '0px', 'height' : '0px', 'marginTop' : w_h/2 +'px', 'marginLeft': w_w/2 +'px' }); $preview.prepend($this); var final_w = $this.data('width'), final_h = $this.data('height'); $this.stop().animate({ 'width' : final_w + 'px', 'height' : final_h + 'px', 'marginTop' : w_h/2 - final_h/2 + 'px', 'marginLeft': w_w/2 - final_w/2 + 'px' },700); //show the description$description.html($next.find('img.thumb').attr('alt')); }).attr('src',img_src); } });
現在我們來定義當我們點擊之前的圖像時發生了什麼:
$prev_img.bind('click',function(){ --currentPhoto; //current album:var $album = $thumbnails_wrapper.find('.tshf_container') .eq(currentAlbum), $prev = $album.find('.content').eq(currentPhoto), $current = $preview.find('img'); if($prev.length == 0 || $current.is(':animated') || currentPhoto < 0){ ++currentPhoto; return false; } else{ $loader.show(); updateInfo(currentAlbum,currentPhoto); //preload the large imagevar img_src = $prev.find('img.thumb') .attr('src') .replace('/thumbs',''), w_w = $(window).width(), w_h = $(window).height(); $('<img/>').load(function(){ var $this = $(this); //record the size that the large image //should have when it is shown saveFinalPositions($this); $loader.hide(); $current.stop() .animate({'marginLeft':(w_w+20)+'px'},500,function(){ //the current image gets removed $(this).remove(); }); //the new image will be positioned on the center,//with width and height of 0px$this.css({ 'width' : '0px', 'height' : '0px', 'marginTop' : w_h/2 +'px', 'marginLeft': w_w/2 +'px' }); $preview.append($this); var final_w = $this.data('width'), final_h = $this.data('height'); $this.stop().animate({ 'width' : final_w + 'px', 'height' : final_h + 'px', 'marginTop' : w_h/2 - final_h/2 + 'px', 'marginLeft': w_w/2 - final_w/2 + 'px' },700); //show the description$description.html($prev.find('img.thumb').attr('alt')); }).attr('src',img_src); } });
當我們調整窗口大小時,我們需要重新計算圖像的位置和大小:
$(window).resize(function(){ var $current = $preview.find('img'), w_w = $(window).width(), w_h = $(window).height(); if($current.length > 0){ saveFinalPositions($current); var final_w = $current.data('width'), final_h = $current.data('height'); $current.css({ 'width' : final_w + 'px', 'height' : final_h + 'px', 'marginTop' : w_h/2 - final_h/2 + 'px', 'marginLeft': w_w/2 - final_w/2 + 'px' }); } });
當我們點擊後連結時,我們想要關閉圖像的預覽:
$back.bind('click',closePreview)
顯示和隱藏導航功能的功能有:
//shows the navigation buttonsfunction showNav(){ $next_img.stop().animate({ 'right' : '10px' },300); $prev_img.stop().animate({ 'left' : '10px' },300); }//hides the navigation buttonsfunction hideNav(){ $next_img.stop().animate({ 'right' : '-50px' },300); $prev_img.stop().animate({ 'left' : '-50px' },300); }
下面的函數將更新專輯/圖像信息:
//updates the current album and current photo infofunction updateInfo(album,photo){ $top_menu.find('.album_info') .html('Album ' + (album+1)) .end() .find('.image_info') .html(' / Shot ' + (photo+1)) }
下一個功能根據窗口大小計算將顯示的完整圖像的最終寬度和高度:
function saveFinalPositions($image){ var theImage = new Image(); theImage.src = $image.attr("src"); var imgwidth = theImage.width; var imgheight = theImage.height; //140 is 2*60 of next/previous buttons plus 20 of extra marginvar containerwidth = $(window).width() - 140; //150 is 30 of header + 30 of footer + extra 90 var containerheight = $(window).height() - 150; if(imgwidth > containerwidth){ var newwidth = containerwidth; var ratio = imgwidth / containerwidth; var newheight = imgheight / ratio; if(newheight > containerheight){ var newnewheight = containerheight; var newratio = newheight/containerheight; var newnewwidth =newwidth/newratio; theImage.width = newnewwidth; theImage.height= newnewheight; } else{ theImage.width = newwidth; theImage.height= newheight; } } else if(imgheight > containerheight){ var newheight = containerheight; var ratio = imgheight / containerheight; var newwidth = imgwidth / ratio; if(newwidth > containerwidth){ var newnewwidth = containerwidth; var newratio = newwidth/containerwidth; var newnewheight =newheight/newratio; theImage.height = newnewheight; theImage.width= newnewwidth; } else{ theImage.width = newwidth; theImage.height= newheight; } } $image.data({'width':theImage.width,'height':theImage.height}); }
當我們點擊後連結時,我們希望當前的圖像再次縮小與大的黃色氣泡。然後我們再展示縮略圖:
function closePreview(){ var $current = $preview.find('img'), w_w = $(window).width(), w_h = $(window).height(), margin_circle = w_w + w_w/3; if(w_h>w_w) margin_circle = w_h + w_h/3; if($current.is(':animated')) return false; //hide the navigation hideNav(); //hide the topmenu$top_menu.stop() .animate({'top':'-30px'},400,'easeOutBack'); //hide the image$current.stop().animate({ 'width' : '0px', 'height' : '0px', 'marginTop' : w_h/2 +'px', 'marginLeft': w_w/2 +'px' },700,function(){ $(this).remove(); }); //animate the bubble image//first set the positions correctly - //it could have changed on a window resize setTimeout(function(){ $bubble.css({ 'width' : margin_circle + 'px', 'height' : margin_circle + 'px', 'margin-top' : -margin_circle/2+'px', 'margin-left': -margin_circle/2+'px' }); $('BODY').css('background','url("bg.jpg") repeat scroll left top #222222'); $bubble.animate({ 'width' : '0px', 'height' : '0px', 'marginTop' : '0px', 'marginLeft': '0px' },500); },200); setTimeout(function(){ $header.stop() .animate({'top':'30px'},700,'easeOutBack'); $thumbnails_wrapper.stop() .show() .animate({'top':'110px'},700,'easeOutBack'); },600); }
最後,我們定義了一個函數,它可以通過應用Manos的縮略圖滾動條來實現縮略圖的滾動:
function createThumbnailScroller(){ /* ThumbnailScroller function parameters: 1) id of the container (div id) 2) thumbnail scroller type. Values: "horizontal", "vertical"3) first and last thumbnail margin (for better cursor interaction) 4) scroll easing amount (0 for no easing) 5) scroll easing type6) thumbnails default opacity 7) thumbnails mouseover fade speed (in milliseconds) */ ThumbnailScroller("tshf_container1","horizontal",10,800,"easeOutCirc",0.5,300); ThumbnailScroller("tshf_container2","horizontal",10,800,"easeOutCirc",0.5,300); ThumbnailScroller("tshf_container3","horizontal",10,800,"easeOutCirc",0.5,300); }
這是它!我們希望你喜歡這個教程,發現它有用!