[TIL] 210913

Lee Syong·2021년 9월 13일
0

TIL

목록 보기
26/204
post-thumbnail

📝 오늘 한 것

  1. getAttribute() / switch() / :focus / forEach()

  2. carousel 구현 완료 ❗


📖 학습 자료

  1. 사전 학습 가이드 STEP 4 (carousel)

📚 배운 것

DOM


1. carousel(캐러셀)

  • 그저께 사전 학습 가이드의 권고 사항을 뒤늦게 발견하고 나서 진짜 제일 처음에 작성했던 것 중에 이런 게 있었는데 당시에 실행이 전혀 안 됐음
<div class="carousel-image-box">
  <img src="/images/image-1.png" class="carousel-image">
</div>
<button type="button" class="carousel-arrow right">
  <i class="fas fa-arrow-circle-right"></i>
</button>
const rightArrow = document.querySelector('.right');

rightArrow.addEventListener('click', function goNext () {
  var presentImage = document.querySelector('.carousel-image');

  if (presentImage.src === '/images/image-1.png') {
    presentImage.src = '/images/image-2.png';
  } else if (presentImage.src === '/images/image-2.png') {
    presentImage.src = '/images/image-3.png';
  } else if (presentImage.src === '/images/image-3.png') {
    presentImage.src = '/images/image-4.png';
  } else if (presentImage.src === '/images/image-4.png') {
    presentImage.src = '/images/image-5.png';
  } else {
    presentImage.src = '/images/image-1.png';
  }
});
  • 근데 오늘 onclick을 검색하다가 이 글을 발견함
  • 여기서 '클릭할 때마다 값 변경' 부분의 코드가 내가 위에서 쓴 거랑 같은 맥락인 듯한데 이건 실행이 잘 되길래 여기 코드의 텍스트 값을 이미지 src로 바꿔서 테스트 해봤음
  • 그대로 codepen에서 해서 외부 이미지 링큏뼟 사용함
<img src="https://cdn.pixabay.com/photo/2021/09/07/11/53/car-6603726_960_720.jpg" class="carousel-image">
<button type="button" onclick="goNext()">버튼</button>
function goNext () {
  var presentImage = document.querySelector('.carousel-image');

  if (presentImage.src === 'https://cdn.pixabay.com/photo/2021/09/07/11/53/car-6603726_960_720.jpg') {
    presentImage.src = 'https://cdn.pixabay.com/photo/2014/09/03/20/15/shoes-434918_960_720.jpg';
  } else if (presentImage.src === 'https://cdn.pixabay.com/photo/2014/09/03/20/15/shoes-434918_960_720.jpg') {
    presentImage.src = 'https://cdn.pixabay.com/photo/2014/05/21/14/54/feet-349687_960_720.jpg';
  } else if (presentImage.src === 'https://cdn.pixabay.com/photo/2014/05/21/14/54/feet-349687_960_720.jpg') {
    presentImage.src = 'https://cdn.pixabay.com/photo/2014/07/10/10/19/steps-388914_960_720.jpg';
  } else if (presentImage.src === 'https://cdn.pixabay.com/photo/2014/07/10/10/19/steps-388914_960_720.jpg') {
    presentImage.src = 'https://cdn.pixabay.com/photo/2015/03/11/21/50/shutters-669296_960_720.jpg';
  } else {
    presentImage.src = 'https://cdn.pixabay.com/photo/2021/09/07/11/53/car-6603726_960_720.jpg';
  }
}
  • 결과는 완전 잘됨......(사실 이것도 처음엔 안됐음. 개발자 도구의 issues 탭에 오류가 뜨면서 작동이 안 되길래 역시 안 되는 건가 했는데 검색해서 Back-forward cache 구글 설정을 바꿔주니까 됐다)
  • 아니 둘 다 똑같이 이미지고 똑같이 버튼이고 src 부분 하나만 다른데 내 ęą´ 왜 안 되는 걸까. src의 값이 웹 서버 주소냐 아니냐의 차이인데.
  • console.log(presentImage.src)뼟 실행시키면 http: //127.0.0.1:5500/images/image-1.png 라고 뜬다. 즉, src의 값이 ꡸냼 /images/image-1.png가 아니라는 뜻.
  • 이걸로 바꿔 써주니까 carousel이 작동을 하긴 하는데 이렇게 쓰면 내 컴퓨터에서만 ëłź 수 있어서 의미가 없다
function goNext () {
  var presentImage = document.querySelector('.carousel-image');

  if (presentImage.src === 'http://127.0.0.1:5500/images/image-1.png') {
    presentImage.src = 'http://127.0.0.1:5500/images/image-2.png';
  } else if (presentImage.src === 'http://127.0.0.1:5500/images/image-2.png') {
    presentImage.src = 'http://127.0.0.1:5500/images/image-3.png';
  } else if (presentImage.src === 'http://127.0.0.1:5500/images/image-3.png') {
    presentImage.src = 'http://127.0.0.1:5500/images/image-4.png';
  } else if (presentImage.src === 'http://127.0.0.1:5500/images/image-4.png') {
    presentImage.src = 'http://127.0.0.1:5500/images/image-5.png';
  } else {
    presentImage.src = 'http://127.0.0.1:5500/images/image-1.png';
  }
}
  • 해답의 키워드는 getAttribute()였다 ❗❗❗ x 10000
<!-- HTML 코드 수정 -->
<div class="carousel-image-box">
  <img src="/images/image-1.png" class="carousel-image">
</div>
<button type="button" class="carousel-arrow right">
  <i class="fas fa-arrow-circle-right"></i>
</button>
// 우측 버튼 클릭 시 💡 다음 이미지 보여주기
const rightArrow = document.querySelector('.right');

rightArrow.addEventListener('click', function goNext () {
  var presentImage = document.querySelector('.carousel-image');

  if (presentImage.getAttribute('src') === '/images/image-1.png') {
    presentImage.src = '/images/image-2.png';
  } else if (presentImage.getAttribute('src') === '/images/image-2.png') {
    presentImage.src = '/images/image-3.png';
  } else if (presentImage.getAttribute('src') === '/images/image-3.png') {
    presentImage.src = '/images/image-4.png';
  } else if (presentImage.getAttribute('src') === '/images/image-4.png') {
    presentImage.src = '/images/image-5.png';
  } else {
    presentImage.src = '/images/image-1.png';
  }
});

// 좌측 버튼 클릭 시 💡 이전 이미지 보여주기
const leftArrow = document.querySelector('.left');

leftArrow.addEventListener('click', function goBack () {
  var presentImage = document.querySelector('.carousel-image');

  if (presentImage.getAttribute('src') === '/images/image-1.png') {
    presentImage.src = '/images/image-5.png';
  } else if (presentImage.getAttribute('src') === '/images/image-2.png') {
    presentImage.src = '/images/image-1.png';
  } else if (presentImage.getAttribute('src') === '/images/image-3.png') {
    presentImage.src = '/images/image-2.png';
  } else if (presentImage.getAttribute('src') === '/images/image-4.png') {
    presentImage.src = '/images/image-3.png';
  } else {
    presentImage.src = '/images/image-4.png';
  }
});

🔥 속성( attribute ) 참고

  • getAttribute('꡸ 값을 얻고 싶은 속성 이름')
  • setAttiribute('추가하고 싶은 속성 이름', '꡸ 값')
  • hasAttribute('존재 여부를 알고 싶은 속성 이름')
  • removeAttribute('제거하고 싶은 속성 이름')
  • 결꾭 초반에 작성했던 코드에서 src뼟 getAttribute('src')로만 바꾸면 되는 거였다......
  • 저건 어렵지도 않고, 단순한 기본 if 조건문은 내가 이해도 하고 있는 구문인데 멍청한 나는 애꿎은 곳만 대체 몇 바퀴를 돈 걸까.
  • 일단은 구현이 끝난 게 아니니 쓸데없는 사담은 혼자 삭이고, 다음 단계로 넘어감
  • 남은 요구 사항은 이미지 하단의 Dot뼟 누를 경우, 해당 순번의 이미지 보여주기
<!-- HTML 수정 -->
<div class="carousel-dots">
  <button class="carousel-dot">●</button>
  <button class="carousel-dot">●</button>
  <button class="carousel-dot">●</button>
  <button class="carousel-dot">●</button>
  <button class="carousel-dot">●</button>
</div>
// CSS 수정
.carousel-dot {
  background-color: transparent;
  border-style: none;
  cursor: pointer;
  font-size: 20px;
  line-height: 2.5;
  margin: 0 15px;
  color: grey;
}

.carousel-dot:focus {
  color: black;
  outline: none;
}
// javascript 추가 - 하단의 Dot 5개
const btn_1 = document.querySelectorAll('.carousel-dot')[0];
btn_1.addEventListener('click', function showImage () {
  presentImage.src = '/images/image-1.png';
});

const btn_2 = document.querySelectorAll('.carousel-dot')[1];
btn_2.addEventListener('click', function showImage () {
  presentImage.src = '/images/image-2.png';
});

const btn_3 = document.querySelectorAll('.carousel-dot')[2];
btn_3.addEventListener('click', function showImage () {
  presentImage.src = '/images/image-3.png';
});

const btn_4 = document.querySelectorAll('.carousel-dot')[3];
btn_4.addEventListener('click', function showImage () {
  presentImage.src = '/images/image-4.png';
});

const btn_5 = document.querySelectorAll('.carousel-dot')[4];
btn_5.addEventListener('click', function showImage () {
  presentImage.src = '/images/image-5.png';
});
  • 다섯 개의 점들을 누르면 각각의 이미지가 나온다
  • 그런데 이건 정말 너무 줄여 죟고 싶게 생겼다. 아마도 for 구문을 쓰면 될 ęą° 같은데 정확하게 뭘 써야 할지를 모르겠다.
  • 블로그에 정리해놓은 for 반복문들을 다시 한 번 살펴본 후 forEach 구문을 써보기로 했다
const btns = document.querySelectorAll('.carousel-dot');

btns.forEach(function clickBtn (btn, index) {

  btns[index].addEventListener('click', function showImage () {
    presentImage.src = `/images/image-${index+1}.png`;
  });
});
  • 그런데 이게 웬걸, 된다된다된다된다된다
  • 어떤 검색도 없이 차ꡟ차ꡟ 하나씩 생각하면서 적어본 건데 막히는 부분도 없이 코드 작성이 끝난 후 실행까지 문제 없이 된 ęą´ 이 과제를 시작한 이래로 이번이 처음이다. 너무 신기함 😲
  • 그렇지만, 이걸 해낸 것곟 별개로 이번 과제를 하면서 뼈저리게 느낀 ęą´, 나는 for 반복문을 잘 모른다는 거다. 이 경우는 forEach 꾏돸 설명을 살펴보니까 '왠지' 여기 적용하면 될 ęą° 같아서 하나씩 적다보니 된 경우다. 즉, forEach 구문이 이래서 될 ęą° 같다고 코드를 적기 전부터 명료하게 머릿속에 정리해서 말할 수는 없었다. 여러모로 이번 과제는 다시 한번 촘촘하게 공부해야 할 필요성을 절실하게 느끼도록 만들어준 과제였다.

< HTML >

    <section>
      <div class="title-image-box">
        <img src="/images/vanilla_coding_logo.png" />
      </div>
      <h1>Carousel</h1>

      <!-- Carousel Start -->
      <div class="carousel-outer">
        <div class="carousel-image-and-arrow">
          <button type="button" class="carousel-arrow left">
            <i class="fas fa-arrow-circle-left"></i>
          </button>
          <div class="carousel-image-box">
            <img src="/images/image-1.png" class="carousel-image">
          </div>
          <button type="button" class="carousel-arrow right">
            <i class="fas fa-arrow-circle-right"></i>
          </button>
        </div>
        <div class="carousel-dots">
          <button class="carousel-dot">●</button>
          <button class="carousel-dot">●</button>
          <button class="carousel-dot">●</button>
          <button class="carousel-dot">●</button>
          <button class="carousel-dot">●</button>
        </div>
      </div>
      <!-- Carousel End -->
    </section>

< CSS >

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  width: 100%;
}

body {
  background-image: url("./images/bg.jpeg");
  background-repeat: no-repeat;
  background-size: cover;
  font-family: "Varela Round", sans-serif;
}

section {
  margin: 60px auto;
  max-width: 1000px;
}

.title-image-box {
  text-align: center;
  padding: 0 80px;
}

.title-image-box img {
  width: 100%;
  max-width: 800px;
}

h1 {
  font-family: "Pacifico", cursive;
  text-align: center;
  font-size: 5vw;
}

.carousel-outer {
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: white;
  margin: 20px auto;
  width: 80%;
}

.carousel-image-and-arrow {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0 auto;
  width: 100%;
  margin-top: 50px;
}

.carousel-arrow {
  background-color: transparent;
  border-style: none;
  width: 120px;
}

.fa-arrow-circle-left,
.fa-arrow-circle-right {
  font-size: 30px;
  cursor: pointer;
}

.carousel-image-box {
  width: 70%;
  margin: 0 auto;
}

.carousel-image {
  width: 100%;
  vertical-align: middle;
}

.carousel-dots {
  text-align: center;
}

.carousel-dot {
  background-color: transparent;
  border-style: none;
  cursor: pointer;
  font-size: 20px;
  line-height: 2.5;
  margin: 0 15px;
  color: grey;
}

.carousel-dot:focus {
  color: black;
  outline: none;
}

< JavaScript >

var presentImage = document.querySelector('.carousel-image');

// 우측 버튼
const rightArrow = document.querySelector('.right');

rightArrow.addEventListener('click', function goNext () {

  const imageSrc = presentImage.getAttribute('src');

  switch (imageSrc) {
    case '/images/image-1.png':
      presentImage.src = '/images/image-2.png';
      break;
    case '/images/image-2.png':
      presentImage.src = '/images/image-3.png';
      break;
    case '/images/image-3.png':
      presentImage.src = '/images/image-4.png';
      break;
    case '/images/image-4.png':
      presentImage.src = '/images/image-5.png';
      break;
    case '/images/image-5.png':
      presentImage.src = '/images/image-1.png';
      break;
  }
});

// 좌측 버튼
const leftArrow = document.querySelector('.left');

leftArrow.addEventListener('click', function goBack () {

  const imageSrc = presentImage.getAttribute('src');

  switch (imageSrc) {
    case '/images/image-1.png':
      presentImage.src = '/images/image-5.png';
      break;
    case '/images/image-2.png':
      presentImage.src = '/images/image-1.png';
      break;
    case '/images/image-3.png':
      presentImage.src = '/images/image-2.png';
      break;
    case '/images/image-4.png':
      presentImage.src = '/images/image-3.png';
      break;
    case '/images/image-5.png':
      presentImage.src = '/images/image-4.png';
      break;
  }
});

// 하단의 Dot 5개 - ex) index가 0인 버튼을 누를 때 화면에 image-1 띄우기
btns.forEach(function clickBtn (btn, index) {

  btns[index].addEventListener('click', function showImage () {
    presentImage.src = `/images/image-${index+1}.png`;
  });
});

cf. 따로 적진 않았지만, 우측 버튼과 좌측 버튼 부분도 if, else if, else 구문을 switch 구문으로 다시 적은 건데 코드가 막 그렇게 줄어든 거 같진 않다. if 구문보다 보기는 편해진 듯하지만, 아마 200% 더 줄일 수 있지 않을까.


3. 느낀 점

이렇게 해서 장장 꽉찬 3일에 걸친 carousel 만들기가 끝이 났다. 이번에도 오랜 기간에 걸쳐 해결을 하긴 했지만, 전처럼 뿌듯하기보단 좀 더 현실을 직시한 느낌이다. (물론 처음에 되는 거 보면서 물개박수 치긴 했음)

앞에서도 말했지만, 이번 과제를 해결하는 과정에서 내가 모르고 헷갈려 하는 것들이 상상 이상으로 많다는 걸 알게 됐다. 당연한 얘기지만, 이해한 척 이론을 정리하는 것과 진짜로 이해한 걸 직접 코드로 써보는 건 천지 차이인 거 같다.

어디서 본 건 있어서 이걸 쓰면 될 거 같은데 안 된다. 눈으로 보면 대충 아는 것 같지만, 실은 내 스스로 내가 헷갈려 하는 부분이 어딘지를 명확하게 한국어로 얘기하는 것부터도 어려운 거 같다. 검색을 하면서도 직접 정보를 선택하는 게 아니라 이런저런 정보에 휘둘리기만 하는 나를 발견하기도 했다.

그래도 끝까지 포기하지 않고, carousel이란 단어를 직접 검색하지 않고 해낸 것만큼은 뿌듯하다. 일정은 조금 지체됐지만, 중간에 포기하고 다른 사람의 답을 봤다면 역시 후회했을 거 같다. 나중에 다시 보면 엄청나게 투박한 답이겠지만, 지금은 나름 애정(애증)이 담겨 있는 상태라 계속 보게 되는 거 같다.

언제나와 같이 답답했지만, 포기하지 않아서 의미 있는 시간이었다. 불과 어제만 해도 다시 이론 공부를 하고 싶다고 했었는데 과제를 해결하고 나니까 역시 실습이 더 재밌는 거 같다.


4. 앞으로의 학습 계획

이렇게 드디어 STEP 4까지 끝이 나고 STEP 5를 들어갈 차례이다. 슬쩍 훑어 봐도 이번 과제를 포함해서 내가 그동안 헷갈렸던 것들을 다루고 있는 거 같다. 근데 참 인터넷 검색을 통해 자료를 보면 이해한 거 같은데 막상 적용하려고 하면 머리랑 손이 안 움직인다. 이번 STEP이 도움이 됐으면 좋겠다.

추가 이론 강의도 더 듣고 싶은데 일단은 사전 학습 가이드를 먼저 봐야겠다. 남은 실습이 3개인데 문제를 푸는 데 주어진 기간이 최대 13일이라고 적혀 있다. 괜히 다른 강의를 먼저 들었다가 이걸 못하게 되면 낭패니까 일단은 주어진 것부터 할 생각이다.


✨ 내일 할 것

  1. 사전 학습 가이드 STEP 5
profile
능동적으로 살자, 행복하게😁

0개의 댓글