JavaScript - 创建订制自己的图片浏览器
随着Javascript的不断发展,越来越多的开发者加入Javascript的开发队伍,随之而来的是越来越多的页面效果出现,其中一个值得一提的就是图片浏览器。
在这之前,一般我们浏览图片,通常是点击页面中的某一个图片,选中之后,跳转到另一个页面当中并且显示当前的图片,因此我们需要不断的在页面之间来回的切换已达到浏览不同的图片。
近来,随着Javascript跟HTML技术的不断演变,一种新的图片浏览方式出现了并且被大量的应用于我们的网站当中。
现在市面上已经有许许多多非常成熟可靠的图片浏览器框架,我们只需要简单的把它们include进我们所在的网站页面当中就可以实现许多动态的效果。
这里,我们不使用任何JS图片浏览器框架,自己纯手工打造一个属于自己的图片浏览器,当是练练手,同时也可以加深我们对这种技术的理解(此例省略css部分演示,请自行脑补,末尾附上全部代码)。
废话不多说,直接先上图:
图一: 未选中图片的当前图片显示列表页面
图二: 选中某图片之后的当前显示页面
整个示例所要达到的效果就是:当我们在浏览某一个页面,选中某一个图片的时候,在当前页面上方,首先弹出一个半透明的遮罩层,这个遮罩层覆盖于当前正常显示页面的上方,并且覆盖这个页面,在这个半透明的遮罩层上方继续显示当前选中的图片以及前后浏览的箭头;当我们再次点中半透明的遮罩层的时候,隐层当前显示的图片跟半透明遮罩层,回到当前浏览的正常页面。
首先,我们先创建HTML页面,代码如下所示:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>My Image Gallery</title> 5 <link rel="stylesheet" type="text/css" href='gallery.css'></link> 6 <script type='' src=''></script> 7 </head> 8 <body> 9 <center><h1>My Image Gallery Demo</h1></center> 10 11 <!-- 巧妇难为无米之炊,首先我们要初始化自己的图片列表,通过css优化页面效果 --> 12 <!-- 提示:我们必须要保证,如果Javascript disabled的情况下,该页面也可以正常显示跟运作 --> 13 <ul class='gallery'> 14 <li><a href='imgs/IMG_1.JPG'><img src='imgs/IMG_1.JPG' alt='IMG 01' /></a></li> 15 <li><a href='imgs/IMG_2.JPG'><img src='imgs/IMG_2.JPG' alt='IMG 01' /></a></li> 16 <li><a href='imgs/IMG_3.JPG'><img src='imgs/IMG_3.JPG' alt='IMG 01' /></a></li> 17 <li><a href='imgs/IMG_4.JPG'><img src='imgs/IMG_4.JPG' alt='IMG 01' /></a></li> 18 <li><a href='imgs/IMG_5.JPG'><img src='imgs/IMG_5.JPG' alt='IMG 01' /></a></li> 19 <li><a href='imgs/IMG_6.JPG'><img src='imgs/IMG_6.JPG' alt='IMG 01' /></a></li> 20 <li><a href='imgs/IMG_7.JPG'><img src='imgs/IMG_7.JPG' alt='IMG 01' /></a></li> 21 </ul> 22 23 <!-- 24 当我们选择中某一个图片的时候,我们在页面上首先会弹出一个半透明的遮罩层,覆盖满这个页面 25 当我们再次点击这个半透明的遮罩层的时候,隐藏该遮罩层,显示下面的图片列表 26 --> 27 <div id='overlay'></div> 28 29 <!-- 30 创建一个Image Gallery Div层,当我们选中某一个图片的时候,在上面的半透明遮罩层的上面弹出 31 并显示当前的图片,并且重新调整图片的显示比例,同时显示前后navigation button,可以让user 32 前后翻动图片 33 --> 34 <div id='imgGallery'> 35 <div id='gallery_image'></div> 36 <div id='gallery_prev'><a href=''>«Prev</a></div> 37 <div id='gallery_next'><a href=''>»Next</a></div> 38 <div id='gallery_title'></div> 39 </div> 40 </body> 41 </html>
接下来我们要开始为页面注入Javascript代码,绑定对应的处理事件:
1 <script> 2 window.onload = function () { 3 var imgGallery = id('imgGallery'); 4 imgGallery.style.display = 'none'; 5 6 /* 当点中遮罩层的时候,隐藏并回到当前页面 */ 7 var overlay = id('overlay'); 8 overlay.onclick = function () { 9 hideOverlay(); 10 } 11 12 /* 我们假定当前页面有任意多个Image Gallerys并遍历每一个Image Gallery */ 13 var galleryULs = byClassName('gallery'); 14 for (var i = 0, len = galleryULs.length; i < len; i++) { 15 var ul = galleryULs[i]; 16 17 /* 获取任意某一个Image Gallery下面的图片列表 */ 18 var imgs = tag('a', ul); 19 for (var j = 0, imgLen = imgs.length; j < imgLen; j++) { 20 var img = imgs[j]; 21 22 /** 23 * 为每一个选中的图片绑定处理事件: 24 * 1. 显示半透明的遮罩层 25 */ 26 img.onclick = function () { 27 showOverlay(); 28 return false; 29 } 30 } 31 } 32 }; 33 34 function showOverlay () { 35 var overlay = id('overlay'); 36 overlay.style.display = 'block'; 37 overlay.style.width = getPageWidth() + 'px'; 38 overlay.style.height = getPageHeight() + 'px'; 39 }; 40 41 function hideOverlay() { 42 var overlay = id('overlay'); 43 overlay.style.display = 'none'; 44 } 45 </script>
运行当前页面,现在的页面效果如下图所示,当我们点击图片时,弹出遮罩层,点击遮罩层时隐层并返回页面,实现了来回之间的效果切换:
接下来要处理的便是显示并且调整图片的尺寸:
1 for (var i = 0, len = galleryULs.length; i < len; i++) { 2 var ul = galleryULs[i]; 3 4 /* 获取任意某一个Image Gallery下面的图片列表 */ 5 var imgs = tag('a', ul); 6 for (var j = 0, imgLen = imgs.length; j < imgLen; j++) { 7 var img = imgs[j]; 8 9 /** 10 * 为每一个选中的图片绑定处理事件: 11 * 1. 显示半透明的遮罩层 12 * 2. 显示被选中的图片并调整显示尺寸 13 */ 14 img.onclick = function () { 15 showOverlay(); 16 showImage(this.parentNode); 17 return false; 18 } 19 } 20 }
// 显示并调整图片尺寸 var currentImg; function showImage (elem) { currentImg = elem; var img = id('gallery_image'); if (img.firstChild) { // 清掉当前的图片 img.removeChild(img.firstChild); } img.appendChild(elem.firstChild.cloneNode(true)); id('gallery_title').innerHTML = elem.firstChild.firstChild.alt; adjustGallery(); }; function adjustGallery() { var gallery = id('imgGallery'); gallery.style.display = 'block'; var newLeft = getScrollX() + (getWindowWidth() / 2 - getWidth(gallery) / 2); var newTop = getScrollY() + (getWindowHeight() / 2 - getHeight(gallery) / 2); if (newLeft < 0) newLeft = 0; if (newTop < 0) newTop = 0; gallery.style.left = newLeft + 'px'; gallery.style.top = newTop + 'px'; return false; };
运行效果如下所示:
到目前为止,我们基本上就build好了这个骨架,接下来我们要处理的是图片的前后活动,当点击Prev箭头是,显示前一张图片,当点击Next箭头时显示下一张图片,当为第一张图片时,只显示Next箭头,最后一张时只显示Prev箭头,代码如下所示:
/* 为Navigation Button绑定处理事件 */ var prevBtn = id('gallery_prev'); prevBtn.onclick = showPrevImage; var nextBtn = id('gallery_next'); nextBtn.onclick = showNextImage; function showPrevImage() { showImage(prev(currentImg)); return false; }; function showNextImage() { showImage(next(currentImg)); return false; };
运行效果截图如下:
最后,为图片浏览器增添自动轮播功能,代码如下:
// 幻灯片显示五毛特效 function startSlideShow(gallery) { var lis = tag('li', gallery); for (var i = 0, len = lis.length; i < len; i++) { // 每个3秒显示下一张图片 new function () { var cur = lis[i]; setTimeout(function () { showImage(cur); setTimeout(function() { hide(id('imgGallery')); }, 2500); }, i * 3000); }; } // 遍历完所有图片之后隐层遮罩层 setTimeout(hideOverlay, lis.length * 3000); // 当开始5毛特效之前,显示遮罩层 showOverlay(); }
最后完整Demo代码:
<!DOCTYPE html> <html> <head> <title>My Image Gallery</title> <link rel="stylesheet" type="text/css" href='gallery.css'></link> <script type='text/javascript' src='gallery.js'></script> </head> <body> <center><h1>My Image Gallery Demo</h1></center> <div id='slideShow'><span></span><a href=''>View As SlideShow »</a></div> <!-- 巧妇难为无米之炊,首先我们要初始化自己的图片列表,通过css优化页面效果 --> <!-- 提示:我们必须要保证,如果Javascript disabled的情况下,该页面也可以正常显示跟运作 --> <ul class='gallery' title='My Image Gallery'> <li><a href='imgs/IMG_1.JPG'><img src='imgs/IMG_1.JPG' alt='IMG 01' /></a></li> <li><a href='imgs/IMG_2.JPG'><img src='imgs/IMG_2.JPG' alt='IMG 02' /></a></li> <li><a href='imgs/IMG_3.JPG'><img src='imgs/IMG_3.JPG' alt='IMG 03' /></a></li> <li><a href='imgs/IMG_4.JPG'><img src='imgs/IMG_4.JPG' alt='IMG 04' /></a></li> <li><a href='imgs/IMG_5.JPG'><img src='imgs/IMG_5.JPG' alt='IMG 05' /></a></li> <li><a href='imgs/IMG_6.JPG'><img src='imgs/IMG_6.JPG' alt='IMG 06' /></a></li> <li><a href='imgs/IMG_7.JPG'><img src='imgs/IMG_7.JPG' alt='IMG 07' /></a></li> </ul> <!-- 当我们选择中某一个图片的时候,我们在页面上首先会弹出一个半透明的遮罩层,覆盖满这个页面 当我们再次点击这个半透明的遮罩层的时候,隐藏该遮罩层,显示下面的图片列表 --> <div id='overlay'></div> <!-- 创建一个Image Gallery Div层,当我们选中某一个图片的时候,在上面的半透明遮罩层的上面弹出 并显示当前的图片,并且重新调整图片的显示比例,同时显示前后navigation button,可以让user 前后翻动图片 --> <div id='imgGallery'> <div id='gallery_image'></div> <div id='gallery_prev'><a href=''>«Prev</a></div> <div id='gallery_next'><a href=''>Next»</a></div> <div id='gallery_title'></div> </div> <script> window.onload = function () { var imgGallery = id('imgGallery'); imgGallery.style.display = 'none'; /* 当点中遮罩层的时候,隐藏并回到当前页面 */ var overlay = id('overlay'); overlay.onclick = function () { hideOverlay(); hideImageGallery(); } /* 为Navigation Button绑定处理事件 */ var prevBtn = id('gallery_prev'); prevBtn.onclick = showPrevImage; var nextBtn = id('gallery_next'); nextBtn.onclick = showNextImage; /* 我们假定当前页面有任意多个Image Gallerys并遍历每一个Image Gallery */ var galleryULs = byClassName('gallery'); for (var i = 0, len = galleryULs.length; i < len; i++) { var ul = galleryULs[i]; /* 获取任意某一个Image Gallery下面的图片列表 */ var imgs = tag('a', ul); for (var j = 0, imgLen = imgs.length; j < imgLen; j++) { var img = imgs[j]; /** * 为每一个选中的图片绑定处理事件: * 1. 显示半透明的遮罩层 * 2. 显示被选中的图片并调整显示尺寸 */ img.onclick = function () { showOverlay(); showImage(this.parentNode); return false; } } tag('span', id('slideShow'))[0].innerHTML = ul.title; tag('a', id('slideShow'))[0].onclick = function () { startSlideShow(ul); return false; } } }; function showOverlay () { var overlay = id('overlay'); overlay.style.display = 'block'; overlay.style.width = getPageWidth() + 'px'; overlay.style.height = getPageHeight() + 'px'; }; function hideOverlay() { var overlay = id('overlay'); overlay.style.display = 'none'; }; function hideImageGallery() { var gallery = id('imgGallery'); gallery.style.display = 'none'; }; // 显示并调整图片尺寸 var currentImg; function showImage (elem) { currentImg = elem; var img = id('gallery_image'); if (img.firstChild) { // 清掉当前的图片 img.removeChild(img.firstChild); } img.appendChild(elem.firstChild.cloneNode(true)); id('gallery_title').innerHTML = elem.firstChild.firstChild.alt; var prevBtn = id('gallery_prev'); if(!(prev(currentImg))) { hide(prevBtn); } else { show(prevBtn); } var nextBtn = id('gallery_next'); if(!(next(currentImg))) { hide(nextBtn); } else { show(nextBtn); } adjustGallery(); }; function adjustGallery() { var gallery = id('imgGallery'); gallery.style.display = 'block'; var newLeft = getScrollX() + (getWindowWidth() / 2 - getWidth(gallery) / 2); var newTop = getScrollY() + (getWindowHeight() / 2 - getHeight(gallery) / 2); if (newLeft < 0) newLeft = 0; if (newTop < 0) newTop = 0; gallery.style.left = newLeft + 'px'; gallery.style.top = newTop + 'px'; return false; }; function showPrevImage() { showImage(prev(currentImg)); return false; }; function showNextImage() { showImage(next(currentImg)); return false; }; // 幻灯片显示五毛特效 function startSlideShow(gallery) { var lis = tag('li', gallery); for (var i = 0, len = lis.length; i < len; i++) { // 每个3秒显示下一张图片 new function () { var cur = lis[i]; setTimeout(function () { showImage(cur); setTimeout(function() { hide(id('imgGallery')); }, 2500); }, i * 3000); }; } // 遍历完所有图片之后隐层遮罩层 setTimeout(hideOverlay, lis.length * 3000); // 当开始5毛特效之前,显示遮罩层 showOverlay(); } </script> </body> </html>
ul.gallery { overflow: auto; list-style: none; border: 1px solid #AAA; padding: 5px; background: #EEE; } ul.gallery li { float: left; width: 110px; height: 110px; margin: 6px; border: 2px solid #AAA; background: #FFF; } ul.gallery img { width: 100px; height: 100px; margin: 5px; border: 0; } #overlay { z-index:100; background: #000; opacity: 0.5; height: 100%; width: 100%; position: absolute; cursor: pointer; cursor: hand; top: 0px; left: 0px; display: none; } #imgGallery { z-index:110; position: absolute; width: 630px; height: 510px; background: #FFF; display: none; } #imgGallery img { z-index: 115; width : 610px; height : 480px; margin : 10px; border:0; } #gallery_title { position: absolute; bottom: 0px; left: 5px; width: 100%; text-align: center; font-size: 16px; } #gallery_prev, #gallery_next { position: absolute; width: 60px; bottom:0px; right:0px; text-align: center; font-size: 14px; font-family: Arial; z-index: 120; } #gallery_prev { left: 0px; } #gallery_prev a, #gallery_next a { text-decoration: none; color: red; } #slideShow { position : relative; padding: 4px; margin-top: 10px; text-align: right; } #slideShow span { position: absolute; bottom: 3px; left: 0px; font-size: 18px; font-weight: bold; } #slideShow a { text-decoration: none; color: red; }
function id (id) { return document.getElementById(id); } function tag (name, elem) { elem = elem || document; return elem.getElementsByTagName(name); } function byClassName(name, elem) { var elems = tag('*', elem); var results = []; for (var i = 0; i < elems.length; i++) { if(elems[i].className && (elems[i].className.indexOf(name) !== -1)){ results.push(elems[i]); } } return results; } function getStyle(elem, name) { if (elem.style[name]) { return elem.style[name]; } else if (elem.currentStyle) { return elem.currentStyle[name]; } else if (document.defaultView && document.defaultView.getComputedStyle) { var s = document.defaultView.getComputedStyle(elem, ''); return s && s.getPropertyValue(name.toLowerCase()); } else { return null; } } function getPageWidth() { return document.body.scrollWidth; } function getPageHeight() { return document.body.scrollHeight; } function getWidth(elem) { return parseInt(getStyle(elem, 'width')); } function getHeight(elem) { return parseInt(getStyle(elem, 'height')); } function getScrollX() { var de = document.documentElement; return self.pageXOffset || (de && de.scrollLeft) || document.body.scrollLeft; } function getScrollY() { var de = document.documentElement; return self.pageYOffset || (de && de.scrollTop) || document.body.scrollTop; } function getWindowWidth() { var de = document.documentElement; return self.innerWidth || (de && de.clientWidth) || document.body.clientWdith; } function getWindowHeight() { var de = document.documentElement; return self.innerHeight || (de && de.clientHeight) || document.body.clientHeight; } function prev(elem) { do { elem = elem.previousSibling; } while (elem && elem.nodeType !==1); return elem; } function next(elem) { do { elem = elem.nextSibling; } while (elem && elem.nodeType !== 1); return elem; } function hide(elem) { elem.style.display = 'none'; } function show(elem) { elem.style.display = 'block'; }