纯Javascript Lightbox / 图片弹出框
我想分享一个完全符合ARIA导航指南的纯Javascript Lightbox或图片弹出框,它非常轻量级且易于实现,因为:
- 它不需要任何JQUERY,因此可以避免额外的CDN导入请求和整个JQUERY库的缓冲。
- 这是一种部署并忘记的设计,我们只需要添加与LIGHTBOX相关的HTML、CSS和JAVASCRIPT,而无需将唯一的ID或CLASS添加到图像或其父A标签的HTML标记中。因此,稍后从您现有的网页中添加或删除图像将不需要更改Javascript或IMG/A标记的ID/CLASS属性。
为了实现这一点,先决条件是IMG标记中的所有图像都应该是父级A标记的唯一子节点,如<a title="" href=""><img alt="" src=""/></a>
。
此外,需要注意的一点是,在A标记和IMG标记的开放和关闭之间不应该有空格,并且它应该显示为<a><img/></a>
。
由于页面下载时只加载IMG标记图像而不加载A标记,因此为所有IMG标记创建父级A标记允许在IMG标记中存储较小尺寸的图像和在父级A标记中存储相同图像的较大尺寸。
将IMG标记与Loading="lazy"
结合使用可以进一步加快页面加载速度。
当在网页上实现时,这个Lightbox的工作非常简单,即您可以点击、触摸或按下IMG标记上的任何图像,然后弹出一个模态框或Lightbox来显示相同URL图像或存储在IMG标记的父级A标记中的不同图像。
- 存储不同质量图像的相同或不同URL取决于您的选择。前者更容易实现,而后者具有更好的性能。
现在让我们看一些代码:
这是一个包含图像和指向其他页面的URL的A标签的示例HTML。
<a href="https://1.bp.blogspot.com/-jNZtfo_qgNM/YHH_XF6FooI/AAAAAAAAC5E/y_tNUslqFPITSVncCkF3zyEC-RROSvETgCLcBGAsYHQ/s328/1.jpg" title="first image"><img alt="first image" src="https://1.bp.blogspot.com/-jNZtfo_qgNM/YHH_XF6FooI/AAAAAAAAC5E/y_tNUslqFPITSVncCkF3zyEC-RROSvETgCLcBGAsYHQ/s320/1.jpg"/></a>
<a href="https://1.bp.blogspot.com/-F0sshQGKu8Y/YHH_XL41aDI/AAAAAAAAC5M/fyAeo4X2tFw-RN-g8YFxNcel0WivQjj5gCLcBGAsYHQ/s400/2.jpg" title="second image"><img alt="second image" src="https://1.bp.blogspot.com/-F0sshQGKu8Y/YHH_XL41aDI/AAAAAAAAC5M/fyAeo4X2tFw-RN-g8YFxNcel0WivQjj5gCLcBGAsYHQ/s320/2.jpg"/></a>
<a href="https://1.bp.blogspot.com/-xk_pNZ1fh7o/YHH_XEROwmI/AAAAAAAAC5I/-WOsyfKgtSMRzXQBeEX-yjRX8TBJuEkFwCLcBGAsYHQ/s400/3.jpg" title="third image"><img alt="third image" src="https://1.bp.blogspot.com/-xk_pNZ1fh7o/YHH_XEROwmI/AAAAAAAAC5I/-WOsyfKgtSMRzXQBeEX-yjRX8TBJuEkFwCLcBGAsYHQ/s320/3.jpg"/></a>
<a href="https://1.bp.blogspot.com/-e3gjnYR7exE/YHH_YHRQgLI/AAAAAAAAC5Q/kgQYFsvBjuYPAXTjzMFkzvsRT6JgQlkywCLcBGAsYHQ/s720/4.jpg" title="fourth image"><img alt="fourth image" src="https://1.bp.blogspot.com/-e3gjnYR7exE/YHH_YHRQgLI/AAAAAAAAC5Q/kgQYFsvBjuYPAXTjzMFkzvsRT6JgQlkywCLcBGAsYHQ/s320/4.jpg"/></a>
<a href="https://1.bp.blogspot.com/-zGPorKCAHqw/YHH_YHcIpSI/AAAAAAAAC5U/Jx2serYqk58fa_HSf1GPwDZu2nT1c8kJgCLcBGAsYHQ/s1280/5.jpg" title="fifth image"><img alt="fifth image" src="https://1.bp.blogspot.com/-zGPorKCAHqw/YHH_YHcIpSI/AAAAAAAAC5U/Jx2serYqk58fa_HSf1GPwDZu2nT1c8kJgCLcBGAsYHQ/s320/5.jpg"/></a>
<a href="https://anubhavyadavjovian.blogspot.com/">Anubhav yadav</a>
假设我们的网页上有五张图片,它们都是以上面定义的格式<a title="" href=""><img alt="" src=""/></a>
显示的。
为了展示这个Lightbox是动态的,我们还包括了一个额外的<a href="https://anubhavyadavjovian.blogspot.com/">Anubhav yadav</a>
,当单击、触摸或按Enter键时,它将像一个普通的A Href标签一样运行,而只有IMG标签作为子元素的A标签将弹出Lightbox。
<div id='lightbox-home'>
<div id='lightbox-container' onclick='hideoverlay()'>
<img alt='' id='lightbox-cont-img' onclick='hideoverlay()' src=''/>
</div>
</div>
上面的真实HTML代码是为我们的灯箱设计的,其中一个ID为"lightbox-container"的元素作为半透明黑色背景,另一个ID为"lightbox-cont-img"的元素则用于显示图片。
#lightbox-container {
z-index:2000;
position:fixed;
bottom:-5000px;
left:0px;
width:100%;
height:100%;
margin:0px;
background-color: rgba(38, 38, 38, 0.85);
transition: all 0.4s ease-out;
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
}
#lightbox-container.showcontainer {
bottom:0px;
}
#lightbox-container img {
max-width:95%;
max-height:95%;
object-fit:contain;
}
:focus {
border: 2px solid gold;
}
以上是用于 Lightbox 装饰以及出现和消失时创建过渡效果的
真实 CSS。
var atagswithimgtag = document.querySelectorAll("a[href]");
var allimgurlarray = [];
for(i=0;i<atagswithimgtag.length;i++){
var childAIMGtag = atagswithimgtag[i].childNodes;
if (childAIMGtag[0].nodeType != Node.TEXT_NODE)
{
atagswithimgtag[i].addEventListener("click", function(event){
event.preventDefault();
});
var listofnodes = atagswithimgtag[i];
allimgurlarray[i] = [];
allimgurlarray[i][0] = i;
allimgurlarray[i][1] = " Image URL is ";
allimgurlarray[i][2] = listofnodes.getAttributeNode("href").value;
}
console.log(childAIMGtag[0].innerHTML);
}
document.onkeydown = function(event){
if(event.keyCode==27){
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){
document.getElementById("lightbox-container").classList.remove("showcontainer");
}
}
else if(event.keyCode==13) {
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){
document.getElementById("lightbox-container").classList.remove("showcontainer");
}
else {
var currentEventTarget = document.activeElement;
if(currentEventTarget.tagName=='A'){
var entertargetchild = currentEventTarget.childNodes;
if(entertargetchild[0].tagName=='IMG'){
var hrefofparent = currentEventTarget.getAttribute("href");
document.getElementById("lightbox-cont-img").setAttribute("src", hrefofparent);
document.getElementById("lightbox-container").classList.add("showcontainer");
document.getElementById("lightbox-cont-img").focus();
}
}
}
}
else if(event.keyCode==9) {
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){
document.getElementById("lightbox-container").classList.remove("showcontainer");
}
}
else if(event.keyCode==37) {
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){
var currimgsrc = document.getElementById("lightbox-cont-img").getAttribute("src");
var serialofarray = 0;
for(k=0;k<allimgurlarray.length;k++){
if(currimgsrc == allimgurlarray[k][2]){
serialofarray = allimgurlarray[k][0];
}
}
if(serialofarray<=0){
serialofarray = allimgurlarray.length - 1;
}
else {
serialofarray = serialofarray - 1;
}
console.log("Left Arrow : "+serialofarray);
document.getElementById("lightbox-cont-img").setAttribute("src", allimgurlarray[serialofarray][2]);
}
}
else if(event.keyCode==39) {
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){
var currimgsrc = document.getElementById("lightbox-cont-img").getAttribute("src");
var serialofarray = 0;
for(l=0;l<allimgurlarray.length;l++){
if(currimgsrc == allimgurlarray[l][2]){
serialofarray = allimgurlarray[l][0];
}
}
if(serialofarray>=allimgurlarray.length-1){
serialofarray = 0;
}
else {
serialofarray = serialofarray + 1;
}
console.log("Right Arrow : "+serialofarray);
document.getElementById("lightbox-cont-img").setAttribute("src", allimgurlarray[serialofarray][2]);
}
}
else {
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){
document.getElementById("lightbox-container").classList.remove("showcontainer");
}
}
}
document.onclick= function(event) {
overlaypop(event);
};
function overlaypop(event) {
if (event===undefined) event= window.event;
var targettag = event.target;
var targetparent = event.target.parentNode;
if(targettag.tagName=='IMG'){
if(targetparent.nodeName=='A'){
event.preventDefault();
var hrefofparent = targetparent.getAttribute("href");
document.getElementById("lightbox-cont-img").setAttribute("src", hrefofparent);
document.getElementById("lightbox-container").classList.add("showcontainer");
document.getElementById("lightbox-cont-img").focus();
}
}
}
function hideoverlay() {
document.getElementById('lightbox-container').classList.remove('showcontainer')
}
通过上述Javascript,我们希望实现以下目的。
- 当触摸、点击或按下键盘上的Enter键后进入所需图像时,弹出全屏幕带半透明黑色背景的图像。
- 除了左右箭头键外,在屏幕上任何位置触摸、点击或按下键盘上的任意键都会隐藏此灯箱。
- 使用左右箭头键浏览网页上所有以 格式提供的图像。
简而言之,让我们通过理解Javascript的各个部分来了解此脚本如何实现我们的目的。
使用
document.querySelectorAll("a[href]")
,我们希望获取所有包含IMG标签的父级A标签的数组,并将其命名为
atagswithimgtag
。
我们将使用此数组,首先通过使用
event.preventDefault()
来禁用打开新页面的默认行为。
然后,我们将使用此数组创建一个名为
allimgurlarray
的新二维数组,以存储A标签的HREF URL和它们的索引号。这样可以更好地跟踪使用左右键时的情况。
之后,我们必须处理两种类型的事件,即按键事件和触摸/点击事件。
按键事件使用
document.onkeydown
进行处理。在这里,我们必须使用If-Else-If条件来处理Enter、Tab、Esc、Right和Left箭头键。
触摸或点击事件使用
document.onclick
进行处理。
我们使用
.classList.contains
来检查Lightbox是否隐藏或可见。我们使用
.classList.add
和
.classList.remove
来分别显示和隐藏Lightbox。
我们使用
document.activeElement
、
.tagName
和
.childNodes
来识别在使用TAB键进行导航后按下Enter键的IMG标签及其父级A标签。
当单击或触摸相应图像时,我们使用
window.event
、
event.target
、
event.target.parentNode
和
.nodeName
来识别IMG标签及其父级A标签。
为使Lightbox更符合ARIA,我们使用
.focus()
将焦点放在当前显示在Lightbox中的图像上。
当 Lightbox 可见时,单击、触摸或按下任意键都将隐藏它。
查看本答案以详细了解此JavaScript将如何处理诸如 ESC , LEFT 和 RIGHT 箭头等键的一般按键事件。