works.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>실습 예제: 취업용 프로필 페이지 제작</title>
<link rel="stylesheet" href="css/style.css" />
<script
src="https://kit.fontawesome.com/ccbe8c103f.js"
crossorigin="anonymous"
></script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Gowun+Batang&family=Noto+Sans+KR:wght@100..900&family=Orbitron:wght@400..900&display=swap"
rel="stylesheet"
/>
<script type="module" src="js/common.js"></script>
<script type="module" src="js/youtube.js"></script>
</head>
<body>
<div class="wrap">
<header>
<h1><a href="index.html" title="인트로 페이지 이동">SANG-DO NAM</a></h1>
<nav>
<a href="profile.html">About me</a>
<a href="works.html">My works</a>
<a href="blog.html">Diary</a>
<a href="join.html">Join</a>
<a href="login.html">Login</a>
</nav>
<div class="btnToggle">
<p></p>
<p></p>
<p></p>
</div>
</header>
<main class="work">
<h1>My Works</h1>
<section class="frame"></section>
</main>
<footer>
<ul>
<li>
<a href="#" target="_blank"><i class="fa-brands fa-youtube"></i></a>
</li>
<li>
<a href="https://sd-ux.blogspot.com/" target="_blank"
><i class="fa-brands fa-google"></i
></a>
</li>
<li>
<a href="#" target="_blank"
><i class="fa-brands fa-square-facebook"></i
></a>
</li>
</ul>
<p>2025 nam sang do © All right reserved.</p>
</footer>
</div>
<aside class="mobileMenu"></aside>
<aside class="popup">
<span class="closePop">close</span>
<div class="con"></div>
</aside>
</body>
</html>
youtube.js
const api_key = 'AIzaSyAA1--4yowu_MLnUqDB7a200vEhqphM84Q';
const pid = 'PLXVj76JGLotR4xaw0HyL9VwOa5y6efr_j';
const num = 3;
const base_url = 'https://www.googleapis.com/youtube/v3/playlistItems';
const req_url = `${base_url}?part=snippet&playlistId=${pid}&key=${api_key}&maxResults=${num}`;
const frame = document.querySelector('.frame');
// 유튜브 데이터 호출 및 동적 UI 생성
fetch(req_url)
.then(data => {
return data.json();
})
.then(json => {
const youtubeData = json.items;
let tags = '';
youtubeData.forEach((data, index) => {
console.log(data);
let tit = '';
let desc = '';
if (data.snippet.title.length > 35) {
tit = data.snippet.title.substring(0, 35) + '...';
} else {
tit = data.snippet.title;
}
data.snippet.description.length > 120
? (desc = data.snippet.description.substring(0, 120) + '...')
: (desc = data.snippet.description);
// 동적으로 생성될 유튜브 제목, 썸네일, 본문 정보
tags += `
<article>
<h2>${tit}</h2>
<!-- 추후 figure클릭시 영상 출력을 위해서 videoId값 data-vid란 커스텀 속성에 미리 담아둠 -->
<figure class='pic' data-vid=${data.snippet.resourceId.videoId}>
<img src=${data.snippet.thumbnails.high.url} />
</figure>
<p>${desc}</p>
<span>${data.snippet.publishedAt
.split('T')[0]
.split('-')
.join('.')}</span>
</article>
`;
});
//해당 시점이 빈문서에 동적으로 썸네일이 생성되는 시점 (동적 요소 생성 시점)
frame.innerHTML = tags;
//모달 열고 닫기 이벤트 연결 (동적돔이 생성된 이후에 이벤트 연결 가능)
const popup = document.querySelector('.popup');
const popupCon = popup.querySelector('.con');
const pics = document.querySelectorAll('.pic');
const closePop = document.querySelector('.closePop');
//복수개 썸네일 요소에 일괄적으로 이벤트 연결
pics.forEach((data, index) => {
data.addEventListener('click', e => {
e.preventDefault();
console.dir(data);
// 썸네일 클릭시 미리 준비한 data-vid의 속성에 있는 videoId값 가져옴
const vidId = data.getAttribute('data-vid');
console.log(vidId);
//console.log(`${index}번째 썸네일 클릭`);
popup.style.display = 'block';
// 해당 vidId값을 ifrrame의 src 부분에 연결해서 유튜브 영상 프레임 동적 생성
popupCon.innerHTML = `<iframe src="http://www.youtube.com/embed/${vidId}"></iframe>`;
});
});
// 팝업 닫기 버튼 이벤트 연결
closePop.addEventListener('click', e => {
e.preventDefault();
popup.style.display = 'none';
});
});
_work.scss
.work {
width: 100%;
h1 {
font: 600 1.3rem/1 'orbitron';
margin-bottom: 40px;
text-align: left;
}
section {
width: 100%;
display: flex;
justify-content: space-between;
margin-bottom: 50px;
article {
width: 32%;
text-align: left;
h2 {
font-weight: bold;
font-size: 1rem;
margin-bottom: 10px;
text-align: left;
}
figure {
width: 100%;
height: 10vw;
margin-bottom: 10px;
filter: saturate(0);
transition: 0.5s;
&:hover {
filter: saturate(1.6);
}
}
p {
font-size: 0.8rem;
line-height: 1.2;
text-align: justify;
opacity: 0.6;
}
span {
font-size: 0.7rem;
color: var(--point-lch);
font-family: 'orbitron';
}
}
}
}
.popup {
width: 80%;
height: 80vh;
position: fixed;
top: 50%;
left: 50%;
background: black;
margin-left: -40%;
margin-top: -40vh;
display: none;
padding: 100px;
.closePop {
position: absolute;
top: 50px;
right: 50px;
color: white;
cursor: pointer;
transition: 0.5s;
&:hover {
color: var(--point-lch);
}
}
.con {
width: 100%;
height: 100%;
border: 1px solid gray;
iframe {
width: 100%;
height: 100%;
object-fit: cover;
border: none;
}
}
}
Tags:
웹개발_교육