[Project] 자기소개 웹페이지

SuJeong·2022년 10월 11일
0

Project

목록 보기
1/4
post-thumbnail

대대적인 리뉴얼을 통한 자기소개 웹페이지 완성 🙌
박스 그룹화로 div 묶는 법... CSS 변수 설정 및 속성 등 조금 더 공부해보니 초기에 기획했던 AS-IS가 말도안되게 엉망이었다는 것을 깨닫고 전체적인 리뉴얼 결심!!!
HTML 마크업, CSS 설정까지 전반적으로 수정하고 자바스크립트로 기능을 추가하였다.

1. 기획 : 프로토타입 및 와이어프레임


AS-IS : 초기 기획당시, 피그마를 이용하여 프로토타입을 구현

단순하기 짝이 없는 프로토타입이다... 너무 단순한 구성과 색상, 자바스크립트를 이용하여 구현할 기능이 부족한 페이지라고 판단하고 갈아엎었다.

TO-BE : 간단한 와이어프레임 진행

일정이 빠듯한데..급하게 전면수정해야해서 기획단계는 간소화하였다. 간단하게 펜과 스케치북을 가지고 와이어프레임을 진행하였다. 어떻게 만들지 틀만 대충 생각해보았다.

2. 자바스크립트로 구현한 주요기능


2-1. typing & cursor blinking

제일 먼저 보게 될 홈페이지 인트로 부분에서 정적인 것보다는 동적인 애니메이션으로 포인트를 주면 좋을 것 같다고 생각하여 영상을 넣을지 방법을 고민하다가 타이핑효과를 구현하였다.

👇 html

<div class="home__title">
    <h2 class="home__introtext"></h2>
</div>     

👇 css

.home__introtext::after {
  content: "|";
  animation: blink 320ms step-end infinite;
}

@keyframes blink {
  50% {
    border-color: var(--color-white);
    opacity: 0;
  }
}
  • animation : .home__introtext뒤에 해당 애니메이션을 넣어준다.
    -> 함수명 / 반복시간 / timingfunction / 반복되는count
  • @keyframes : 애니메이션을 재생할 프레임의 스타일을 정의한다.
    -> content의 색은 흰색으로 지정하고 실행 시 50% 구간에서 투명하게 해 깜빡거리는 것과 같은 효과를 줄 수 있다.

참고 : MDN(animation)

👇 자바스크립트

/* intro 타이핑효과 */
const introText = document.querySelector(".home__introtext");
const content = "안녕하세요.\n저는 구수정입니다 :)";
let index = 0;
let putWord = "";

const typingInterval = setInterval(() => {
  putWord += content[index++];
  introText.innerText = putWord;
  // introText.innerText += content[index++];
  // 위의 코드처럼 진행 시 띄어쓰기가 나올 경우 ex) "저는 "까지 입력된 innerText를 가져올 시 띄어쓰기가 trim됨
}, 320);

setTimeout(() => {
  clearInterval(typingInterval);
}, 320 * content.length + 30);

textContent / innerText / innerHTML

  • textContent<script>, <style> 요소를 포함한 모든 요소의 콘텐츠를 가져온다.
  • innerText는 렌더링이 되어 "사람이 읽을 수 있는" 요소만 처리한다.
  • innerHTML은 DOM트리를 수정하는 것으로 XSS 공격에 취약하므로 가급적 사용하지 않는것이 좋다.
  • setInterval() : 한글자 입력하는데 설정한 시간인 0.32초마다 함수를 실행시킨다. 따라서 한글자씩 .home__introtext에 들어가진다.
  • setTimeout() : 모든 문장을 입력하는데 설정한 시간이 지나면 함수를 호출한다. -> 사파리에서 약간 시간지연 있어 +30 적용
  • clearInterval() : 해당 함수의 인터벌을 중단시킨다. 함수명 입력 시 '()'를 입력한다면 해당 함수의 반환값을 가져오는 것이므로 함수명만 적어준다.

2-2. navbar 메뉴 클릭 시 해당 부분으로 이동하고 스크롤 이벤트 발생

👇 html

<ul class="navbar__menu">
	<li class="navbar__menu__item selected" data-link="#home">Home</li>
    <li class="navbar__menu__item" data-link="#about">About</li>
    <li class="navbar__menu__item" data-link="#skill">Skill</li>
    <li class="navbar__menu__item" data-link="#work">Portfolio</li>
    <li class="navbar__menu__item" data-link="#footer">contact</li>
</ul>

👇 css

.navbar__menu {
  display: flex;
  flex-flow: row;
  justify-content: space-evenly;
}

.navbar__menu__item {
  padding: 10px;
  margin: 0 10px;
  cursor: pointer;
  color: var(--color-white);
}

.navbar__menu__item:hover {
  color: var(--color-blue);
  border-radius: 15px;
  background-color: var(--color-white);
}
  • hover : 마우스 위에 커서를 올렸을 때 요소를 선택한다.
    -> .navbar__menu__item 요소 위에 마우스가 올라가면 이렇게 스타일링하겠다.

👇 자바스크립트

const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (event) => {
  // event.target : <li class="navbar__menu__item active">Home</li>
  // event.target.dataset : DOMStringMap {link: '#about'}
  const link = event.target.dataset.link;
  if (link == null) return;
  scrollinto(link);
});
/* 해당 목적지까지 스크롤 이동 */
function scrollinto(selector) {
  const destination = document.querySelector(selector);
  destination.scrollIntoView({ behavior: "smooth" });
}
  • addEventListener(): 클릭 시 이벤트를 등록한다.
  • event.target.dataset.link : 클릭한 navbar__menu 클래스를 가진 요소의 data객체의 키 link의 value를 가져온다.
  • scrollinto() : 해당 value를 id값으로 가지고 있는 곳으로 스크롤이 이동한다. 옵션으로 behavior:"smooth"를 지정하여 스크롤이 부드럽게 이동하게끔 해주었다.

2-3. 스크롤 내릴 시 intro 섹션 점점 불투명하게 스타일링

👇 자바스크립트

const intro = document.querySelector(".home__container");
const introHeight = intro.offsetHeight;
document.addEventListener("scroll", () => {
  intro.style.opacity = 1 - window.scrollY / introHeight;
});
  • offsetHeight(): 우리가 보고 있는 부분의 높이값을 가져오는 함수
  • scroll이벤트가 일어났을 때 scroll한만큼 Y값을 가져와서 opacity값을 지정한다.

2-4. 스크롤 내릴 시 top버튼 생성 후 클릭 시 맨위로 스크롤링


👇 css

.top-btn {
  position: fixed;
  right: 30px;
  bottom: 30px;
  font-size: 50px;
  color: var(--color-white);
  border: none;
  background-color: transparent;
  opacity: 0;
  /* opacity로 버튼을 가려놓은 상태라 해당 위치에 마우스를 올리면 포인터가 생기기 때문에
    지워주는 스타일링 */
  pointer-events: none;
  transition: all 300ms ease-in;
}

.top-btn.visible {
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
}

👇 자바스크립트

const topBtn = document.querySelector(".top-btn");
document.addEventListener("scroll", () => {
  if (window.scrollY > introHeight / 2) {
    topBtn.classList.add("visible");
  } else {
    topBtn.classList.remove("visible");
  }
});
topBtn.addEventListener("click", () => {
  scrollinto("#home");
});
/* 해당 목적지까지 스크롤 이동 */
function scrollinto(selector) {
  const destination = document.querySelector(selector);
  destination.scrollIntoView({ behavior: "smooth" });
}
  • 스크롤이 첫화면의 반이상을 지났을 때 .top-btn의 요소에 visible이라는 클래스를 추가하여 top버튼을 생성한다.
  • 해당 버튼을 클릭했을 때 #home id를 가지고 있는 요소, 즉 첫화면으로 스크롤 이동시킨다.

2-5. fortfolio 섹션 버튼 클릭 시 스타일링 및 Front, back 나누어 해당 카테고리별로 필터링해서 보여주기

👇 html

	<div class="work__categories">
        <button class="category__btn selected" data-filter="*">
          all
          <span class="category__count">3</span>
        </button>
        <button class="category__btn" data-filter="front">
          front
          <span class="category__count">2</span>
        </button>
        <button class="category__btn" data-filter="back">
          back
          <span class="category__count">1</span>
        </button>
     </div>

👇 자바스크립트

const categoryBtn = document.querySelector(".work__categories");
const projects = document.querySelectorAll(".project");
const projectContainer = document.querySelector(".work__projects");
categoryBtn.addEventListener("click", (e) => {
  const selected = document.querySelector(".category__btn.selected");
  // 기존 선택되었던 버튼 스타일링 삭제
  selected.classList.remove("selected");
  const target =
    e.target.nodeName === "BUTTON" ? e.target : e.target.parentNode;
  // 선택된 버튼에 스타일링
  target.classList.add("selected");

  /*
  숫자버튼을 나타내는 span 태그를 클릭시 data-filter가 정의되어있지 않아 parentnode인
  category__btn의 filter값을 가져온다.
  */
  const filter = e.target.dataset.filter || e.target.parentNode.dataset.filter;
  if (filter == null) return;
  projectContainer.classList.add("anim-out");
  setTimeout(() => {
    projects.forEach((project) => {
      /*
      카테고리버튼의 filter값이랑 project이미지의 filter값이랑 같아야
      front일때 front프로젝트, back일 때 back프로젝트만 보여짐
      */
      if (filter === "*" || filter === project.dataset.type) {
        project.classList.remove("invisible");
      } else {
        project.classList.add("invisible");
      }
    });
    projectContainer.classList.remove("anim-out");
  }, 300);
});
  • 하나의 버튼에는 <button><span>이 함께있어서 <button> 클릭시에는 바로 target을 지정해주면 되지만 <span> 클릭 시에는 부모노드를 target으로 지정해주어야 한다.
  • 이미지들이 안보였다가 필터링 후 0.3초 뒤에 필터링된 이미지들이 새롭게 보여야하므로 setTimeout()안에서 필터링을 진행했다.
    -> setTimeout()밖에서 진행할 시 이미지들이 필터링이 된 모습으로 보여졌다가 사라졌다가 다시 보이게 되어 애니메이션이 불편해보인다.
  • 카테고리버튼의 filter값이랑 project이미지의 filter값이랑 같아야 front일때 front 프로젝트만, back일 때 back프로젝트만 보여짐

💡 반응형 웹페이지

미디어쿼리와 flex, position을 이용하여 스타일링하여 반응형으로 구현해보았다.
보편적인 모바일 사이즈인 768px이하일 때 navigation bar를 토글버튼으로 묶어서 구현하였고 전체적인 폰트사이즈, padding값을 수정하였다.

/* 768px 이하의 스크린에서 */
@media screen and (max-width: 768px) { ... }

더 자세한 코드들이 궁금하시다면?


3. 회고 🙏

이번에 홈페이지를 만들면서 마크업, 어떻게 div박스들끼리 묶을지 고민하는 과정이 큰 틀을 짜는데 중요한 초기과정이라는 걸 느꼈다. flex, position의 개념을 잡아가는데 좋은 경험이었고 각 브라우저 별 개발자모드에서 요소들의 정보를 파악하고 디버깅에 대해 경험했고 자바스크립트의 문법을 조금 더 공부해야겠다.

profile
Front-End Developer

0개의 댓글