对现有项目实施灯箱
Implement lightbox to existing project
这将是一个很长的问题,对此感到抱歉,但我是 hmtl/css/js 的新手并且仍在努力学习,我正在尝试为我使用 [=21= 从 pexels 获取的照片实现灯箱],我想实现灯箱,所以当我单击图片时它会显示更大等,我非常感谢您的帮助我希望它不会太多,代码在这里,如果您需要其他任何东西,请告诉我:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Kavivanar&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lobster+Two:ital@0;1&display=swap" rel="stylesheet">
<title>Title</title>
<link rel="stylesheet" href="./lightboxTest.css">
</head>
<!--
- Basic HTML index, if you hover over the Gallery text you will see another text that says "Return to start".
- When you hover over pictures there is a text to let you know that if you click the picture you get the original size.
- Getting a search icon from ionicons in one of the script tags.
- Having some links to my social media, thinking that if this was a real company the users could visit.
-->
<body>
<section>
<div class="container">
<ul>
<span title="Visit our Instagram page!"><li><a href="https://www.facebook.com/myName" target="_blank"><i class="fab fa-facebook" aria-hidden="true"></i></a></li></span>
<span title="Visit our Instagram page!"><li><a href="https://twitter.com/myName" target="_blank"><i class="fab fa-twitter" aria-hidden="true"></i></a></li></span>
<span title="Visit our Instagram page!"><li><a href="https://www.instagram.com/myName/" target="_blank"><i class="fab fa-instagram" aria-hidden="true"></i></a></li></span>
<span title="Contact"><li><a href="contact.html"><i class="fas fa-id-card-alt" aria-hidden="true"></i></a></li></span>
<!-- <span title="Contact"><li><a href="contact"><i class="contact" aria-hidden="true">@</i></a></li></span> -->
</ul>
<div class="header">
<span title="Return to start"><h1 class="logo">G a l l e r y</h1></span>
<form>
<input type="text" placeholder="Search Photos">
<ion-icon name="search-outline"></ion-icon>
</form>
</div>
<span title="Click on picture to see original size"><div class="gallery"></span></div>
<span title="Load more pictures"><a class="load-more data-img='curated'">View More</a></span>
</div>
</section>
<script src="https://unpkg.com/ionicons@5.1.2/dist/ionicons.js"></script>
<script src="./main.js"></script>
<script src="./newTab.js"></script>
</body>
</html>
这里是 css:
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@300;900&display=swap");
/* Asterix means: Select all elementes and set the properties inside of the curly brackets */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-family: "Montserrat", sans-serif;
font-size: 100%;
}
body {
background-color: gray;
}
/* Properties for my social media contacts aswell contact icon. */
ul {
position: relative;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
text-align: center;
align-items: center;
justify-content: center;
margin: 0 10px;
text-decoration: none;
}
ul li {
list-style: none;
}
ul li a {
position: relative;
width:60px;
height:60px;
display:block;
text-align:center;
margin:0 10px;
border-radius: 50%;
padding: 6px;
text-decoration:none;
box-shadow: 0 10px 15px rgba(0,0,0,0.3);
background: linear-gradient(0deg, #ddd, #fff);
transition: .5s;
}
ul li a:hover {
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
text-decoration:none;
}
ul li a .fab {
width: 100%;
height:100%;
display: inline-block;
background: linear-gradient(0deg, #fff, #ddd);
border-radius: 50%;
line-height: calc(60px - 12px);
font-size:24px;
color: #262626;
transition: .5s;
}
ul li a .fas {
width: 100%;
height:100%;
display: inline-block;
background: linear-gradient(0deg, #fff, #ddd);
border-radius: 50%;
line-height: calc(60px - 12px);
font-size:24px;
color: #262626;
transition: .5s;
}
/* Child is the different icons, number 1 is facebook, 2 twitter and so on. */
ul li:nth-child(1) a:hover .fab {
color: #3b5998;
}
ul li:nth-child(2) a:hover .fab {
color: #00aced;
}
ul li:nth-child(3) a:hover .fab {
color: #e4405f;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
section {
min-height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin: 100px 0;
}
/* Containing pretty much everything you see on the site, can you call it a wrapper?? */
.container {
background-color: lightgray;
width: 90%;
max-width: 900px;
margin: 0 auto;
box-shadow: 0px 0px 61px 7px #5e849c40;
padding: 50px 20px;
border-radius: 20px;
text-align: center;
}
.header {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
}
.header h1 {
font-size: 40px;
font-weight: 900;
letter-spacing: -2px;
}
/* For the search section */
form {
margin-top: 30px;
width: 80%;
max-width: 300px;
position: relative;
}
/* Input box properties, where the user can search for photos */
input {
border: none;
border-bottom: 2px solid gray;
font-size: 20px;
width: 100%;
outline: none;
color: black;
background-color: transparent;
position: relative;
}
/* Placeholder properties, in this case "Search Photos" */
input::placeholder {
opacity: 0.5;
color: black;
font-family: "Montserrat";
}
/* Ionicon properties which is the magnifying glass in the search box */
form ion-icon {
position: absolute;
right: 0;
font-size: 20px;
opacity: 0.5;
color: black;
}
/* Properties of gallery logo */
.logo
{
color: black;
transition: 0.3s ease;
font-family: 'Kavivanar', cursive;
}
/* Gallery logo hovering effects */
.logo:hover
{
color: darkgray;
text-shadow: 2px 2px black;
}
.gallery{
display: grid;
grid-template-columns: repeat(3, 200px);
justify-content: center;
grid-gap: 10px;
height: 100vh;
}
img{
cursor: pointer;
width: 200px;
height: 200px;
}
#item {
position: fixed;
z-index: 1000;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0, .8);
display: none;
}
#item.active{
display: flex;
justify-content: center;
align-items: center;
}
这是 JS:
class PhotoGallery
{
//Constructor containing my selectors
constructor()
{
this.API_KEY = '563492ad6f917000010000013a6f79bdd68a47199caa701bab553adf';
// The querySelector() method returns the first element that matches a specified CSS selector(s) in the document.
this.galleryDIv = document.querySelector('.gallery');
this.searchForm = document.querySelector('.header form');
this.loadMore = document.querySelector('.load-more');
this.logo = document.querySelector('.logo');
this.pageIndex = 1;
this.searchValueGlobal = '';
this.eventHandle();
}
//Eventhandler, eg when the DOMContent is loaded I wanna retrieve the pictures from my API_KEY
eventHandle()
{
document.addEventListener('DOMContentLoaded', () => {
this.getImg(1);
});
this.searchForm.addEventListener('submit', (e) => {
this.pageIndex = 1;
this.getSearchedImages(e);
});
this.loadMore.addEventListener('click', (e) => {
this.loadMoreImages(e);
});
this.logo.addEventListener('click', () => {
this.pageIndex = 1;
this.galleryDIv.innerHTML = '';
this.getImg(this.pageIndex);
});
}
//Getting images from my API_KEY by calling the function fetchImages.
async getImg(index){
this.loadMore.setAttribute('data-img', 'curated');
const baseURL = `https://api.pexels.com/v1/curated?page=${index}&per_page=12`;
const data = await this.fetchImages(baseURL);
this.GenerateHTML(data.photos);
console.log(data);
}
//Fetching the images from my API_KEY
async fetchImages(baseURL){
const response = await fetch(baseURL,{
method: 'GET',
headers:{
Accept: 'application/json',
Authorization: this.API_KEY
}
});
const data = await response.json();
return data;
}
// the document.createElement() method creates the HTML element specified by tagName, or an HTMLUnknownElement if tagName isn't recognized.
GenerateHTML(photos){
photos.forEach(photo=>{
const item = document.createElement('div');
item.classList.add('item');
item.innerHTML = `
<a href='${photo.src.original}' target="_blank"></a>
<img src="${photo.src.medium}">
<h3>${photo.photographer}</h3>
</a>
`;
this.galleryDIv.appendChild(item);
})
}
async getSearchedImages(e){
this.loadMore.setAttribute('data-img', 'search');
// preventDefault method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur.
e.preventDefault();
this.galleryDIv.innerHTML = '';
const searchValue = e.target.querySelector('input').value;
this.searchValueGlobal = searchValue;
const baseURL = `https://api.pexels.com/v1/search?query=${searchValue}&page=1&per_page=12`;
const data = await this.fetchImages(baseURL);
this.GenerateHTML(data.photos)
e.target.reset();
}
async getMoreSearchedImages(index){
const baseURL = `https://api.pexels.com/v1/search?query=${this.searchValueGlobal}&page=${index}&per_page=12`;
const data = await this.fetchImages(baseURL);
console.log(data);
this.GenerateHTML(data.photos)
}
loadMoreImages(e){
let index = ++this.pageIndex;
// The getAttribute() method of the Element interface returns the value of a specified attribute on the element.
// If the given attribute does not exist, the value returned will either be null or "" (the empty string);
const loadMoreData = e.target.getAttribute('data-img');
if(loadMoreData === 'curated')
{
this.getImg(index)
}
else
{
this.getMoreSearchedImages(index);
}
}
}
//Creating a new instance of the PhotoGallery
const gallery = new PhotoGallery;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Kavivanar&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lobster+Two:ital@0;1&display=swap" rel="stylesheet">
<title>Title</title>
<link rel="stylesheet" href="./lightboxTest.css">
<style>
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@300;900&display=swap");
/* Asterix means: Select all elementes and set the properties inside of the curly brackets */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-family: "Montserrat", sans-serif;
font-size: 100%;
}
body {
background-color: gray;
}
/* Properties for my social media contacts aswell contact icon. */
ul {
position: relative;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
text-align: center;
align-items: center;
justify-content: center;
margin: 0 10px;
text-decoration: none;
}
ul li {
list-style: none;
}
ul li a {
position: relative;
width:60px;
height:60px;
display:block;
text-align:center;
margin:0 10px;
border-radius: 50%;
padding: 6px;
text-decoration:none;
box-shadow: 0 10px 15px rgba(0,0,0,0.3);
background: linear-gradient(0deg, #ddd, #fff);
transition: .5s;
}
ul li a:hover {
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
text-decoration:none;
}
ul li a .fab {
width: 100%;
height:100%;
display: inline-block;
background: linear-gradient(0deg, #fff, #ddd);
border-radius: 50%;
line-height: calc(60px - 12px);
font-size:24px;
color: #262626;
transition: .5s;
}
ul li a .fas {
width: 100%;
height:100%;
display: inline-block;
background: linear-gradient(0deg, #fff, #ddd);
border-radius: 50%;
line-height: calc(60px - 12px);
font-size:24px;
color: #262626;
transition: .5s;
}
/* Child is the different icons, number 1 is facebook, 2 twitter and so on. */
ul li:nth-child(1) a:hover .fab {
color: #3b5998;
}
ul li:nth-child(2) a:hover .fab {
color: #00aced;
}
ul li:nth-child(3) a:hover .fab {
color: #e4405f;
}
.m {
width: 100%;
height: 100%;
object-fit: cover;
}
section {
min-height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin: 100px 0;
}
/* Containing pretty much everything you see on the site, can you call it a wrapper?? */
.container {
background-color: lightgray;
width: 90%;
max-width: 900px;
margin: 0 auto;
box-shadow: 0px 0px 61px 7px #5e849c40;
padding: 50px 20px;
border-radius: 20px;
text-align: center;
}
.header {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
}
.header h1 {
font-size: 40px;
font-weight: 900;
letter-spacing: -2px;
}
/* For the search section */
form {
margin-top: 30px;
width: 80%;
max-width: 300px;
position: relative;
}
/* Input box properties, where the user can search for photos */
input {
border: none;
border-bottom: 2px solid gray;
font-size: 20px;
width: 100%;
outline: none;
color: black;
background-color: transparent;
position: relative;
}
/* Placeholder properties, in this case "Search Photos" */
input::placeholder {
opacity: 0.5;
color: black;
font-family: "Montserrat";
}
/* Ionicon properties which is the magnifying glass in the search box */
form ion-icon {
position: absolute;
right: 0;
font-size: 20px;
opacity: 0.5;
color: black;
}
/* Properties of gallery logo */
.logo
{
color: black;
transition: 0.3s ease;
font-family: 'Kavivanar', cursive;
}
/* Gallery logo hovering effects */
.logo:hover
{
color: darkgray;
text-shadow: 2px 2px black;
}
.gallery{
margin-top: 10px;
margin-bottom: 10px;
display: grid;
grid-template-columns: repeat(3, 200px);
justify-content: center;
grid-gap: 10px;
height: 100%;
}
.main {
cursor: pointer;
width: 200px;
height: 200px;
}
#item {
position: fixed;
z-index: 1000;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0, .8);
display: none;
}
#item.active{
display: flex;
justify-content: center;
align-items: center;
}
.load-more{
cursor: pointer;
}
.popup{
border: none;
}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
-webkit-animation-name: fadeIn; /* Fade in the background */
-webkit-animation-duration: 0.4s;
animation-name: fadeIn;
animation-duration: 0.4s
}
/* Modal Content */
.modal-content {
margin-left: 7%;
margin-right: 7%;
position: fixed;
top: 5%;
background-color: lightgray;
width: 86%;
-webkit-animation-name: slideIn;
-webkit-animation-duration: 0.4s;
animation-name: slideIn;
animation-duration: 0.4s;
border-radius: 20px;
justify-content: center;
}
/* The Close Button */
.close {
color: white;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.modal-header {
padding: 2px 16px;
background-color: gray;
color: white;
border-radius: 20px 20px 0px 0px;
}
.modal-footer {
padding: 2px 16px;
background-color: gray;
border-radius: 0px 0px 20px 20px;
color: white;
}
.modal-body {padding: 2px 16px; height: 100%;}
/* Add Animation */
@-webkit-keyframes slideIn {
from {bottom: -300px; opacity: 0}
to {bottom: 0; opacity: 1}
}
@keyframes slideIn {
from {bottom: -300px; opacity: 0}
to {bottom: 0; opacity: 1}
}
@-webkit-keyframes fadeIn {
from {opacity: 0}
to {opacity: 1}
}
@keyframes fadeIn {
from {opacity: 0}
to {opacity: 1}
}
.open::after {
content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAASUlEQVQoU5WQwQ4AIAhC4/8/2rJmQ5NDHuUNBhjizMxYwvMAEABrGwSJHeS/FkxOwGGqY4UiIYEKaqO7BO8gy3Cpf1CNfous+SZoSE/7IpEx6wAAAABJRU5ErkJggg==');
margin: 0 3px 0 5px;
}
.open{
color: white;
text-decoration: none;
}
</style>
</head>
<!--
- Basic HTML index, if you hover over the Gallery text you will see another text that says "Return to start".
- When you hover over pictures there is a text to let you know that if you click the picture you get the original size.
- Getting a search icon from ionicons in one of the script tags.
- Having some links to my social media, thinking that if this was a real company the users could visit.
-->
<body>
<section>
<div class="container">
<ul>
<span title="Visit our Instagram page!"><li><a href="https://www.facebook.com/myName" target="_blank"><i class="fab fa-facebook" aria-hidden="true"></i></a></li></span>
<span title="Visit our Instagram page!"><li><a href="https://twitter.com/myName" target="_blank"><i class="fab fa-twitter" aria-hidden="true"></i></a></li></span>
<span title="Visit our Instagram page!"><li><a href="https://www.instagram.com/myName/" target="_blank"><i class="fab fa-instagram" aria-hidden="true"></i></a></li></span>
<span title="Contact"><li><a href="contact.html"><i class="fas fa-id-card-alt" aria-hidden="true"></i></a></li></span>
<!-- <span title="Contact"><li><a href="contact"><i class="contact" aria-hidden="true">@</i></a></li></span> -->
</ul>
<div class="header">
<span title="Return to start"><h1 class="logo">G a l l e r y</h1></span>
<form>
<input type="text" placeholder="Search Photos">
<ion-icon name="search-outline"></ion-icon>
</form>
</div>
<span title="Click on picture to see original size"><div class="gallery"></div></span>
<span title="Load more pictures"><a class="load-more data-img='curated'">View More</a></span>
</div>
</section>
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2 id="hed">Modal Header</h2>
</div>
<div class="modal-body">
<img id="imgs" class="loading" style="cursor: auto;margin-left: 34%;
margin-right: 34%;
width: 32%;" src=""/>
</div>
<div class="modal-footer">
<h4><a class="open" target="_blank" id="foot" href="">Modal Footer</a></h4>
</div>
</div>
</div>
<script src="https://unpkg.com/ionicons@5.1.2/dist/ionicons.js"></script>
<script src="./main.js"></script>
<script src="./newTab.js"></script>
</body>
</html>
<script>
class PhotoGallery
{
//Constructor containing my selectors
constructor()
{
this.API_KEY = '563492ad6f917000010000013a6f79bdd68a47199caa701bab553adf';
// The querySelector() method returns the first element that matches a specified CSS selector(s) in the document.
this.galleryDIv = document.querySelector('.gallery');
this.searchForm = document.querySelector('.header form');
this.loadMore = document.querySelector('.load-more');
this.logo = document.querySelector('.logo');
this.pageIndex = 1;
this.searchValueGlobal = '';
this.eventHandle();
}
//Eventhandler, eg when the DOMContent is loaded I wanna retrieve the pictures from my API_KEY
eventHandle()
{
document.addEventListener('DOMContentLoaded', () => {
this.getImg(1);
});
this.searchForm.addEventListener('submit', (e) => {
this.pageIndex = 1;
this.getSearchedImages(e);
});
this.loadMore.addEventListener('click', (e) => {
this.loadMoreImages(e);
});
this.logo.addEventListener('click', () => {
this.pageIndex = 1;
this.galleryDIv.innerHTML = '';
this.getImg(this.pageIndex);
});
}
//Getting images from my API_KEY by calling the function fetchImages.
async getImg(index){
this.loadMore.setAttribute('data-img', 'curated');
const baseURL = `https://api.pexels.com/v1/curated?page=${index}&per_page=12`;
const data = await this.fetchImages(baseURL);
this.GenerateHTML(data.photos);
console.log(data);
}
//Fetching the images from my API_KEY
async fetchImages(baseURL){
const response = await fetch(baseURL,{
method: 'GET',
headers:{
Accept: 'application/json',
Authorization: this.API_KEY
}
});
const data = await response.json();
return data;
}
// the document.createElement() method creates the HTML element specified by tagName, or an HTMLUnknownElement if tagName isn't recognized.
GenerateHTML(photos){
photos.forEach(photo=>{
const item = document.createElement('div');
item.classList.add('item');
item.innerHTML = `
<button class="popup" onclick="popup('${photo.src.original}','${photo.photographer}');"/>
<img class="main" src="${photo.src.medium}"></button>
<h3>${photo.photographer}</h3>
</a>
`;
this.galleryDIv.appendChild(item);
})
}
async getSearchedImages(e){
this.loadMore.setAttribute('data-img', 'search');
// preventDefault method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur.
e.preventDefault();
this.galleryDIv.innerHTML = '';
const searchValue = e.target.querySelector('input').value;
this.searchValueGlobal = searchValue;
const baseURL = `https://api.pexels.com/v1/search?query=${searchValue}&page=1&per_page=12`;
const data = await this.fetchImages(baseURL);
this.GenerateHTML(data.photos)
e.target.reset();
}
async getMoreSearchedImages(index){
const baseURL = `https://api.pexels.com/v1/search?query=${this.searchValueGlobal}&page=${index}&per_page=12`;
const data = await this.fetchImages(baseURL);
console.log(data);
this.GenerateHTML(data.photos)
}
loadMoreImages(e){
let index = ++this.pageIndex;
// The getAttribute() method of the Element interface returns the value of a specified attribute on the element.
// If the given attribute does not exist, the value returned will either be null or "" (the empty string);
const loadMoreData = e.target.getAttribute('data-img');
if(loadMoreData === 'curated')
{
this.getImg(index)
}
else
{
this.getMoreSearchedImages(index);
}
}
}
//Creating a new instance of the PhotoGallery
const gallery = new PhotoGallery;
// Get the modal
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
function popup(url,name){
modal.style.display = "block";
document.getElementById("hed").innerHTML = name;
document.getElementById("imgs").src = url;
document.getElementById("foot").href = url;
document.getElementById("foot").innerHTML = 'Open Image';
}
// When the user clicks on the button, open the modal
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
我为你感到难过,所以我希望这能奏效!
注意:单击展开代码段可查看全文!
这将是一个很长的问题,对此感到抱歉,但我是 hmtl/css/js 的新手并且仍在努力学习,我正在尝试为我使用 [=21= 从 pexels 获取的照片实现灯箱],我想实现灯箱,所以当我单击图片时它会显示更大等,我非常感谢您的帮助我希望它不会太多,代码在这里,如果您需要其他任何东西,请告诉我:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Kavivanar&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lobster+Two:ital@0;1&display=swap" rel="stylesheet">
<title>Title</title>
<link rel="stylesheet" href="./lightboxTest.css">
</head>
<!--
- Basic HTML index, if you hover over the Gallery text you will see another text that says "Return to start".
- When you hover over pictures there is a text to let you know that if you click the picture you get the original size.
- Getting a search icon from ionicons in one of the script tags.
- Having some links to my social media, thinking that if this was a real company the users could visit.
-->
<body>
<section>
<div class="container">
<ul>
<span title="Visit our Instagram page!"><li><a href="https://www.facebook.com/myName" target="_blank"><i class="fab fa-facebook" aria-hidden="true"></i></a></li></span>
<span title="Visit our Instagram page!"><li><a href="https://twitter.com/myName" target="_blank"><i class="fab fa-twitter" aria-hidden="true"></i></a></li></span>
<span title="Visit our Instagram page!"><li><a href="https://www.instagram.com/myName/" target="_blank"><i class="fab fa-instagram" aria-hidden="true"></i></a></li></span>
<span title="Contact"><li><a href="contact.html"><i class="fas fa-id-card-alt" aria-hidden="true"></i></a></li></span>
<!-- <span title="Contact"><li><a href="contact"><i class="contact" aria-hidden="true">@</i></a></li></span> -->
</ul>
<div class="header">
<span title="Return to start"><h1 class="logo">G a l l e r y</h1></span>
<form>
<input type="text" placeholder="Search Photos">
<ion-icon name="search-outline"></ion-icon>
</form>
</div>
<span title="Click on picture to see original size"><div class="gallery"></span></div>
<span title="Load more pictures"><a class="load-more data-img='curated'">View More</a></span>
</div>
</section>
<script src="https://unpkg.com/ionicons@5.1.2/dist/ionicons.js"></script>
<script src="./main.js"></script>
<script src="./newTab.js"></script>
</body>
</html>
这里是 css:
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@300;900&display=swap");
/* Asterix means: Select all elementes and set the properties inside of the curly brackets */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-family: "Montserrat", sans-serif;
font-size: 100%;
}
body {
background-color: gray;
}
/* Properties for my social media contacts aswell contact icon. */
ul {
position: relative;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
text-align: center;
align-items: center;
justify-content: center;
margin: 0 10px;
text-decoration: none;
}
ul li {
list-style: none;
}
ul li a {
position: relative;
width:60px;
height:60px;
display:block;
text-align:center;
margin:0 10px;
border-radius: 50%;
padding: 6px;
text-decoration:none;
box-shadow: 0 10px 15px rgba(0,0,0,0.3);
background: linear-gradient(0deg, #ddd, #fff);
transition: .5s;
}
ul li a:hover {
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
text-decoration:none;
}
ul li a .fab {
width: 100%;
height:100%;
display: inline-block;
background: linear-gradient(0deg, #fff, #ddd);
border-radius: 50%;
line-height: calc(60px - 12px);
font-size:24px;
color: #262626;
transition: .5s;
}
ul li a .fas {
width: 100%;
height:100%;
display: inline-block;
background: linear-gradient(0deg, #fff, #ddd);
border-radius: 50%;
line-height: calc(60px - 12px);
font-size:24px;
color: #262626;
transition: .5s;
}
/* Child is the different icons, number 1 is facebook, 2 twitter and so on. */
ul li:nth-child(1) a:hover .fab {
color: #3b5998;
}
ul li:nth-child(2) a:hover .fab {
color: #00aced;
}
ul li:nth-child(3) a:hover .fab {
color: #e4405f;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
section {
min-height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin: 100px 0;
}
/* Containing pretty much everything you see on the site, can you call it a wrapper?? */
.container {
background-color: lightgray;
width: 90%;
max-width: 900px;
margin: 0 auto;
box-shadow: 0px 0px 61px 7px #5e849c40;
padding: 50px 20px;
border-radius: 20px;
text-align: center;
}
.header {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
}
.header h1 {
font-size: 40px;
font-weight: 900;
letter-spacing: -2px;
}
/* For the search section */
form {
margin-top: 30px;
width: 80%;
max-width: 300px;
position: relative;
}
/* Input box properties, where the user can search for photos */
input {
border: none;
border-bottom: 2px solid gray;
font-size: 20px;
width: 100%;
outline: none;
color: black;
background-color: transparent;
position: relative;
}
/* Placeholder properties, in this case "Search Photos" */
input::placeholder {
opacity: 0.5;
color: black;
font-family: "Montserrat";
}
/* Ionicon properties which is the magnifying glass in the search box */
form ion-icon {
position: absolute;
right: 0;
font-size: 20px;
opacity: 0.5;
color: black;
}
/* Properties of gallery logo */
.logo
{
color: black;
transition: 0.3s ease;
font-family: 'Kavivanar', cursive;
}
/* Gallery logo hovering effects */
.logo:hover
{
color: darkgray;
text-shadow: 2px 2px black;
}
.gallery{
display: grid;
grid-template-columns: repeat(3, 200px);
justify-content: center;
grid-gap: 10px;
height: 100vh;
}
img{
cursor: pointer;
width: 200px;
height: 200px;
}
#item {
position: fixed;
z-index: 1000;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0, .8);
display: none;
}
#item.active{
display: flex;
justify-content: center;
align-items: center;
}
这是 JS:
class PhotoGallery
{
//Constructor containing my selectors
constructor()
{
this.API_KEY = '563492ad6f917000010000013a6f79bdd68a47199caa701bab553adf';
// The querySelector() method returns the first element that matches a specified CSS selector(s) in the document.
this.galleryDIv = document.querySelector('.gallery');
this.searchForm = document.querySelector('.header form');
this.loadMore = document.querySelector('.load-more');
this.logo = document.querySelector('.logo');
this.pageIndex = 1;
this.searchValueGlobal = '';
this.eventHandle();
}
//Eventhandler, eg when the DOMContent is loaded I wanna retrieve the pictures from my API_KEY
eventHandle()
{
document.addEventListener('DOMContentLoaded', () => {
this.getImg(1);
});
this.searchForm.addEventListener('submit', (e) => {
this.pageIndex = 1;
this.getSearchedImages(e);
});
this.loadMore.addEventListener('click', (e) => {
this.loadMoreImages(e);
});
this.logo.addEventListener('click', () => {
this.pageIndex = 1;
this.galleryDIv.innerHTML = '';
this.getImg(this.pageIndex);
});
}
//Getting images from my API_KEY by calling the function fetchImages.
async getImg(index){
this.loadMore.setAttribute('data-img', 'curated');
const baseURL = `https://api.pexels.com/v1/curated?page=${index}&per_page=12`;
const data = await this.fetchImages(baseURL);
this.GenerateHTML(data.photos);
console.log(data);
}
//Fetching the images from my API_KEY
async fetchImages(baseURL){
const response = await fetch(baseURL,{
method: 'GET',
headers:{
Accept: 'application/json',
Authorization: this.API_KEY
}
});
const data = await response.json();
return data;
}
// the document.createElement() method creates the HTML element specified by tagName, or an HTMLUnknownElement if tagName isn't recognized.
GenerateHTML(photos){
photos.forEach(photo=>{
const item = document.createElement('div');
item.classList.add('item');
item.innerHTML = `
<a href='${photo.src.original}' target="_blank"></a>
<img src="${photo.src.medium}">
<h3>${photo.photographer}</h3>
</a>
`;
this.galleryDIv.appendChild(item);
})
}
async getSearchedImages(e){
this.loadMore.setAttribute('data-img', 'search');
// preventDefault method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur.
e.preventDefault();
this.galleryDIv.innerHTML = '';
const searchValue = e.target.querySelector('input').value;
this.searchValueGlobal = searchValue;
const baseURL = `https://api.pexels.com/v1/search?query=${searchValue}&page=1&per_page=12`;
const data = await this.fetchImages(baseURL);
this.GenerateHTML(data.photos)
e.target.reset();
}
async getMoreSearchedImages(index){
const baseURL = `https://api.pexels.com/v1/search?query=${this.searchValueGlobal}&page=${index}&per_page=12`;
const data = await this.fetchImages(baseURL);
console.log(data);
this.GenerateHTML(data.photos)
}
loadMoreImages(e){
let index = ++this.pageIndex;
// The getAttribute() method of the Element interface returns the value of a specified attribute on the element.
// If the given attribute does not exist, the value returned will either be null or "" (the empty string);
const loadMoreData = e.target.getAttribute('data-img');
if(loadMoreData === 'curated')
{
this.getImg(index)
}
else
{
this.getMoreSearchedImages(index);
}
}
}
//Creating a new instance of the PhotoGallery
const gallery = new PhotoGallery;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Kavivanar&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lobster+Two:ital@0;1&display=swap" rel="stylesheet">
<title>Title</title>
<link rel="stylesheet" href="./lightboxTest.css">
<style>
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@300;900&display=swap");
/* Asterix means: Select all elementes and set the properties inside of the curly brackets */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-family: "Montserrat", sans-serif;
font-size: 100%;
}
body {
background-color: gray;
}
/* Properties for my social media contacts aswell contact icon. */
ul {
position: relative;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
text-align: center;
align-items: center;
justify-content: center;
margin: 0 10px;
text-decoration: none;
}
ul li {
list-style: none;
}
ul li a {
position: relative;
width:60px;
height:60px;
display:block;
text-align:center;
margin:0 10px;
border-radius: 50%;
padding: 6px;
text-decoration:none;
box-shadow: 0 10px 15px rgba(0,0,0,0.3);
background: linear-gradient(0deg, #ddd, #fff);
transition: .5s;
}
ul li a:hover {
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
text-decoration:none;
}
ul li a .fab {
width: 100%;
height:100%;
display: inline-block;
background: linear-gradient(0deg, #fff, #ddd);
border-radius: 50%;
line-height: calc(60px - 12px);
font-size:24px;
color: #262626;
transition: .5s;
}
ul li a .fas {
width: 100%;
height:100%;
display: inline-block;
background: linear-gradient(0deg, #fff, #ddd);
border-radius: 50%;
line-height: calc(60px - 12px);
font-size:24px;
color: #262626;
transition: .5s;
}
/* Child is the different icons, number 1 is facebook, 2 twitter and so on. */
ul li:nth-child(1) a:hover .fab {
color: #3b5998;
}
ul li:nth-child(2) a:hover .fab {
color: #00aced;
}
ul li:nth-child(3) a:hover .fab {
color: #e4405f;
}
.m {
width: 100%;
height: 100%;
object-fit: cover;
}
section {
min-height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin: 100px 0;
}
/* Containing pretty much everything you see on the site, can you call it a wrapper?? */
.container {
background-color: lightgray;
width: 90%;
max-width: 900px;
margin: 0 auto;
box-shadow: 0px 0px 61px 7px #5e849c40;
padding: 50px 20px;
border-radius: 20px;
text-align: center;
}
.header {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
}
.header h1 {
font-size: 40px;
font-weight: 900;
letter-spacing: -2px;
}
/* For the search section */
form {
margin-top: 30px;
width: 80%;
max-width: 300px;
position: relative;
}
/* Input box properties, where the user can search for photos */
input {
border: none;
border-bottom: 2px solid gray;
font-size: 20px;
width: 100%;
outline: none;
color: black;
background-color: transparent;
position: relative;
}
/* Placeholder properties, in this case "Search Photos" */
input::placeholder {
opacity: 0.5;
color: black;
font-family: "Montserrat";
}
/* Ionicon properties which is the magnifying glass in the search box */
form ion-icon {
position: absolute;
right: 0;
font-size: 20px;
opacity: 0.5;
color: black;
}
/* Properties of gallery logo */
.logo
{
color: black;
transition: 0.3s ease;
font-family: 'Kavivanar', cursive;
}
/* Gallery logo hovering effects */
.logo:hover
{
color: darkgray;
text-shadow: 2px 2px black;
}
.gallery{
margin-top: 10px;
margin-bottom: 10px;
display: grid;
grid-template-columns: repeat(3, 200px);
justify-content: center;
grid-gap: 10px;
height: 100%;
}
.main {
cursor: pointer;
width: 200px;
height: 200px;
}
#item {
position: fixed;
z-index: 1000;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0, .8);
display: none;
}
#item.active{
display: flex;
justify-content: center;
align-items: center;
}
.load-more{
cursor: pointer;
}
.popup{
border: none;
}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
-webkit-animation-name: fadeIn; /* Fade in the background */
-webkit-animation-duration: 0.4s;
animation-name: fadeIn;
animation-duration: 0.4s
}
/* Modal Content */
.modal-content {
margin-left: 7%;
margin-right: 7%;
position: fixed;
top: 5%;
background-color: lightgray;
width: 86%;
-webkit-animation-name: slideIn;
-webkit-animation-duration: 0.4s;
animation-name: slideIn;
animation-duration: 0.4s;
border-radius: 20px;
justify-content: center;
}
/* The Close Button */
.close {
color: white;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.modal-header {
padding: 2px 16px;
background-color: gray;
color: white;
border-radius: 20px 20px 0px 0px;
}
.modal-footer {
padding: 2px 16px;
background-color: gray;
border-radius: 0px 0px 20px 20px;
color: white;
}
.modal-body {padding: 2px 16px; height: 100%;}
/* Add Animation */
@-webkit-keyframes slideIn {
from {bottom: -300px; opacity: 0}
to {bottom: 0; opacity: 1}
}
@keyframes slideIn {
from {bottom: -300px; opacity: 0}
to {bottom: 0; opacity: 1}
}
@-webkit-keyframes fadeIn {
from {opacity: 0}
to {opacity: 1}
}
@keyframes fadeIn {
from {opacity: 0}
to {opacity: 1}
}
.open::after {
content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAASUlEQVQoU5WQwQ4AIAhC4/8/2rJmQ5NDHuUNBhjizMxYwvMAEABrGwSJHeS/FkxOwGGqY4UiIYEKaqO7BO8gy3Cpf1CNfous+SZoSE/7IpEx6wAAAABJRU5ErkJggg==');
margin: 0 3px 0 5px;
}
.open{
color: white;
text-decoration: none;
}
</style>
</head>
<!--
- Basic HTML index, if you hover over the Gallery text you will see another text that says "Return to start".
- When you hover over pictures there is a text to let you know that if you click the picture you get the original size.
- Getting a search icon from ionicons in one of the script tags.
- Having some links to my social media, thinking that if this was a real company the users could visit.
-->
<body>
<section>
<div class="container">
<ul>
<span title="Visit our Instagram page!"><li><a href="https://www.facebook.com/myName" target="_blank"><i class="fab fa-facebook" aria-hidden="true"></i></a></li></span>
<span title="Visit our Instagram page!"><li><a href="https://twitter.com/myName" target="_blank"><i class="fab fa-twitter" aria-hidden="true"></i></a></li></span>
<span title="Visit our Instagram page!"><li><a href="https://www.instagram.com/myName/" target="_blank"><i class="fab fa-instagram" aria-hidden="true"></i></a></li></span>
<span title="Contact"><li><a href="contact.html"><i class="fas fa-id-card-alt" aria-hidden="true"></i></a></li></span>
<!-- <span title="Contact"><li><a href="contact"><i class="contact" aria-hidden="true">@</i></a></li></span> -->
</ul>
<div class="header">
<span title="Return to start"><h1 class="logo">G a l l e r y</h1></span>
<form>
<input type="text" placeholder="Search Photos">
<ion-icon name="search-outline"></ion-icon>
</form>
</div>
<span title="Click on picture to see original size"><div class="gallery"></div></span>
<span title="Load more pictures"><a class="load-more data-img='curated'">View More</a></span>
</div>
</section>
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2 id="hed">Modal Header</h2>
</div>
<div class="modal-body">
<img id="imgs" class="loading" style="cursor: auto;margin-left: 34%;
margin-right: 34%;
width: 32%;" src=""/>
</div>
<div class="modal-footer">
<h4><a class="open" target="_blank" id="foot" href="">Modal Footer</a></h4>
</div>
</div>
</div>
<script src="https://unpkg.com/ionicons@5.1.2/dist/ionicons.js"></script>
<script src="./main.js"></script>
<script src="./newTab.js"></script>
</body>
</html>
<script>
class PhotoGallery
{
//Constructor containing my selectors
constructor()
{
this.API_KEY = '563492ad6f917000010000013a6f79bdd68a47199caa701bab553adf';
// The querySelector() method returns the first element that matches a specified CSS selector(s) in the document.
this.galleryDIv = document.querySelector('.gallery');
this.searchForm = document.querySelector('.header form');
this.loadMore = document.querySelector('.load-more');
this.logo = document.querySelector('.logo');
this.pageIndex = 1;
this.searchValueGlobal = '';
this.eventHandle();
}
//Eventhandler, eg when the DOMContent is loaded I wanna retrieve the pictures from my API_KEY
eventHandle()
{
document.addEventListener('DOMContentLoaded', () => {
this.getImg(1);
});
this.searchForm.addEventListener('submit', (e) => {
this.pageIndex = 1;
this.getSearchedImages(e);
});
this.loadMore.addEventListener('click', (e) => {
this.loadMoreImages(e);
});
this.logo.addEventListener('click', () => {
this.pageIndex = 1;
this.galleryDIv.innerHTML = '';
this.getImg(this.pageIndex);
});
}
//Getting images from my API_KEY by calling the function fetchImages.
async getImg(index){
this.loadMore.setAttribute('data-img', 'curated');
const baseURL = `https://api.pexels.com/v1/curated?page=${index}&per_page=12`;
const data = await this.fetchImages(baseURL);
this.GenerateHTML(data.photos);
console.log(data);
}
//Fetching the images from my API_KEY
async fetchImages(baseURL){
const response = await fetch(baseURL,{
method: 'GET',
headers:{
Accept: 'application/json',
Authorization: this.API_KEY
}
});
const data = await response.json();
return data;
}
// the document.createElement() method creates the HTML element specified by tagName, or an HTMLUnknownElement if tagName isn't recognized.
GenerateHTML(photos){
photos.forEach(photo=>{
const item = document.createElement('div');
item.classList.add('item');
item.innerHTML = `
<button class="popup" onclick="popup('${photo.src.original}','${photo.photographer}');"/>
<img class="main" src="${photo.src.medium}"></button>
<h3>${photo.photographer}</h3>
</a>
`;
this.galleryDIv.appendChild(item);
})
}
async getSearchedImages(e){
this.loadMore.setAttribute('data-img', 'search');
// preventDefault method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur.
e.preventDefault();
this.galleryDIv.innerHTML = '';
const searchValue = e.target.querySelector('input').value;
this.searchValueGlobal = searchValue;
const baseURL = `https://api.pexels.com/v1/search?query=${searchValue}&page=1&per_page=12`;
const data = await this.fetchImages(baseURL);
this.GenerateHTML(data.photos)
e.target.reset();
}
async getMoreSearchedImages(index){
const baseURL = `https://api.pexels.com/v1/search?query=${this.searchValueGlobal}&page=${index}&per_page=12`;
const data = await this.fetchImages(baseURL);
console.log(data);
this.GenerateHTML(data.photos)
}
loadMoreImages(e){
let index = ++this.pageIndex;
// The getAttribute() method of the Element interface returns the value of a specified attribute on the element.
// If the given attribute does not exist, the value returned will either be null or "" (the empty string);
const loadMoreData = e.target.getAttribute('data-img');
if(loadMoreData === 'curated')
{
this.getImg(index)
}
else
{
this.getMoreSearchedImages(index);
}
}
}
//Creating a new instance of the PhotoGallery
const gallery = new PhotoGallery;
// Get the modal
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
function popup(url,name){
modal.style.display = "block";
document.getElementById("hed").innerHTML = name;
document.getElementById("imgs").src = url;
document.getElementById("foot").href = url;
document.getElementById("foot").innerHTML = 'Open Image';
}
// When the user clicks on the button, open the modal
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
我为你感到难过,所以我希望这能奏效!
注意:单击展开代码段可查看全文!