본문 바로가기
씹덕티스토리에코딩의등장이라

유투바이오(js동작)

by 희쨩 2024. 4. 3.

 

Html 구조.. 길다

더보기
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- <meta name="viewport" content="width=1004"> -->
  <meta name="format-detection" content="telephone=no">
  <meta name="description" content="일상 속에 스며든 데이터기반 맞춤형 헬스케어 파트너. 우리는 맞춤형 헬스케어로 모두의 건강한 삶을 당연하게 만듭니다.">
  <meta property="og:type" content="website">
  <meta property="og:url" content="http://ossamuiux.com/test/">
  <meta property="og:title" content="유투바이오">
  <meta property="og:description" content="일상 속에 스며든 데이터기반 맞춤형 헬스케어 파트너. 우리는 맞춤형 헬스케어로 모두의 건강한 삶을 당연하게 만듭니다.">
  <title> U2Bio</title>
  <link rel="icon" href="images/common/favicon.ico">
  <link rel="apple-touch-icon-precomposed" href="images/common/favicon.jpg">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link rel="stylesheet" href="css/common.css?v=<?php echo time(); ?>">
  <link rel="stylesheet" href="css/main.css?v=<?php echo time(); ?>">
  <script src="js/ui-common.js?v=<?php echo time(); ?>"></script>
</head>
<body>
  <div id="skip_navi">
    <a href="#container">본문바로가기</a>
  </div>
  <div id="wrap">
    <header id="header">
      <div class="inner">
        <h1 class="logo">
          <a href="index.html">
            <span class="blind">유투바이오</span>
          </a>
        </h1>
        <nav class="gnb_wrap">
          <ul class="gnb">
            <li>
              <a href="/about/greeting.do">기업 소개</a>
              <ul class="depth2">
                <li><a href="/about/greeting.do">인사말</a></li>
                <li><a href="/about/management.do">주요 경영진</a></li>
                <li><a href="/about/missionVision.do">미션과 비전</a></li>
                <li><a href="/about/history.do">연혁</a></li>
                <li><a href="/about/location.do">오시는 길</a></li>
              </ul>
            </li>
            <li>
              <a href="/products/sampleCheck.do">제품 및 서비스</a>
              <ul class="depth2">
                <li><a href="/products/sampleCheck.do">검체검사 서비스</a></li>
                <li><a href="/products/digitalHealthcare.do">Digital Healthcare<br>Platform (IT)</a></li>
                <li><a href="/products/biotechnology.do">Bio-Technology<br>Platform (BT)</a></li>
              </ul>
            </li>
            <li>
              <a href="/investment/financial.do">투자정보</a>
              <ul class="depth2">
                <li><a href="/investment/financial.do">재무 정보</a></li>
                <li><a href="/investment/corporate.do">기업공시</a></li>
                <li><a href="/investment/inquiry.do">투자 문의</a></li>
                <li><a href="#">주주공고</a></li>
              </ul>
            </li>
            <li>
              <a href="#">미디어센터</a>
              <ul class="depth2">
                <li><a href="#">보도자료</a></li>
                <li><a href="#">E카달로그</a></li>
              </ul>
            </li>
            <li>
              <a href="/recruitment/organization.do">채용정보</a>
              <ul class="depth2">
                <li><a href="/recruitment/organization.do">U2Bio 조직</a></li>
                <li><a href="/recruitment/idealTalent.do">U2인재상</a></li>
                <li><a href="/recruitment/humanReliance.do">U2 HR (Human Reliances)</a></li>
                <li><a href="/recruitment/recruitmentInquiry.do">채용 문의</a></li>
              </ul>
            </li>
          </ul>
        </nav>
        <div class="lang_wrap">
          <button class="lang_btn" type="button">KOR</button>
          <ul class="lang">
            <li><a href="#">KOR</a></li>
            <li><a href="#">ENG</a></li>
          </ul>
          <button type="button" class="open_btn">
            <span class="blind">메뉴열기</span>
            <i></i>
            <i></i>
            <i></i>
          </button>
        </div>
        <aside class="m_gnb_wrap">
          <ul class="m_gnb">
            <li>
              <a href="/about/greeting.do">기업 소개</a>
              <ul class="depth2">
                <li><a href="/about/greeting.do">인사말</a></li>
                <li><a href="/about/management.do">주요 경영진</a></li>
                <li><a href="/about/missionVision.do">미션과 비전</a></li>
                <li><a href="/about/history.do">연혁</a></li>
                <li><a href="/about/location.do">오시는 길</a></li>
              </ul>
            </li>
            <li>
              <a href="/products/sampleCheck.do">제품 및 서비스</a>
              <ul class="depth2">
                <li><a href="/products/sampleCheck.do">검체검사 서비스</a></li>
                <li><a href="/products/digitalHealthcare.do">Digital Healthcare<br>Platform (IT)</a></li>
                <li><a href="/products/biotechnology.do">Bio-Technology<br>Platform (BT)</a></li>
              </ul>
            </li>
            <li>
              <a href="/investment/financial.do">투자정보</a>
              <ul class="depth2">
                <li><a href="/investment/financial.do">재무 정보</a></li>
                <li><a href="/investment/corporate.do">기업공시</a></li>
                <li><a href="/investment/inquiry.do">투자 문의</a></li>
                <li><a href="#">주주공고</a></li>
              </ul>
            </li>
            <li>
              <a href="#">미디어센터</a>
              <ul class="depth2">
                <li><a href="#">보도자료</a></li>
                <li><a href="#">E카달로그</a></li>
              </ul>
            </li>
            <li>
              <a href="/recruitment/organization.do">채용정보</a>
              <ul class="depth2">
                <li><a href="/recruitment/organization.do">U2Bio 조직</a></li>
                <li><a href="/recruitment/idealTalent.do">U2인재상</a></li>
                <li><a href="/recruitment/humanReliance.do">U2 HR (Human Reliances)</a></li>
                <li><a href="/recruitment/recruitmentInquiry.do">채용 문의</a></li>
              </ul>
            </li>
          </ul>
        </aside>
      </div>
    </header>
    <main id="container">
      <section class="main_slider">
        <h2 class="blind">메인 슬라이더</h2>
        <img class="pc_img" src="images/visual1.jpg" alt="">
        <img class="m_img" src="images/m_visual1.jpg" alt="">
      </section>
    </main>
  </div>
</body>
</html>

 

 

스크롤 내리면 헤더가 변함 (옆에 depth2들 무시)

 

css에서 fixed로 넣어줌

더보기
#header.fixed {
  background: #fff;
  box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
#header.fixed .logo a {
  background: url(../images/logo.svg) no-repeat left top / 100%;
}
#header.fixed .gnb>li>a {
  color: var(--txt-color-600)
}
#header.fixed .lang_wrap .lang_btn {
  background: #f7f7f7;
  color: var(--txt-color-600);
  border-color: #f7f7f7;
}
#header.fixed .lang_wrap .lang_btn::after {
  background: #000;
}

 

js

더보기
  window.addEventListener('scroll', function () {
    // 세로스크롤바의 위치값
    let _scrollY = window.scrollY;
    if (_scrollY > 0) {
      header.classList.add('fixed');
    } else {
      header.classList.remove('fixed');
    }
  });

 

 

그 전에

js 맨 위에

window.addEventListener('DOMContentLoaded', function () {

 

를 넣어 주어야 함

제이쿼리 개발방식에선 js 파일을 head 하단에 연결하여 연결된 js 파일 확인이 용이하도록 함

근데 아직 제이쿼리 아니고 js 파일이 html보다 위에 연결되어 있으므로 ui 로직구현시 DOMContentLoaded 이벤트를 반드시 넣어야 함

 

addEventListener('scroll') 많이 씀

window.scrollY < 세로 스크롤바의 위치값

스크롤바 위치 그냥은 모르니까 let 함수 써서 넣어 줘야 함

add는 fixed라는 클래스를 추가해 줌 (위에 css에 넣은 거)

스크롤바 위치가 0으로 되면 remove(제거)로 원래대로 돌아오게 함

 

 

 

 


누르면 아래 펼쳐침 : 버튼 토글

 

css

더보기
#header .lang_wrap {
  position: absolute;
  right: 20px;
  top: 50%;
  transform: translateY(-50%);
}
#header .lang_wrap .lang_btn {
  height: 34px;
  border: 1px solid #fff;
  border-radius: 17px;
  width: 82px;
  background: none;
  text-align: left;
  padding: 0 16px;
  color: #fff;
  display: inline-flex;
  align-items: center;
  gap: 0 7px;
  transition: all 0.2s;
}
#header .lang_wrap .lang_btn::after {
  content: '';
  display: inline-block;  
  width: 7px;
  height: 6px;
  -webkit-mask: url(../images/arrow_down.svg) no-repeat;
  mask: url(../images/arrow_down.svg) no-repeat;
  background: #fff;
  transition: all 0.2s;
}
#header .lang_wrap.on .lang_btn {
  background: #f7f7f7;
  color: var(--txt-color-600);
  border-radius: 17px 17px 0 0;
  border-color: #f7f7f7;
}
#header .lang_wrap.on .lang_btn::after {
  transform: rotate(180deg);
  background: #000;
}
#header .lang_wrap.on .lang {
  max-height: 80px;
}
#header .lang_wrap .lang {
  position: absolute;
  left: 0;
  top: 34px;
  background: #f7f7f7;
  width: 82px;
  border-radius: 0 0 17px 17px;
  max-height: 0;
  overflow: hidden;
  transition: all 0.2s;
}
#header .lang_wrap .lang a {
  display: block;
  font-size: 16px;
  color: var(--txt-color-400);
  line-height: 40px;
  padding: 0 16px;
}

.on 함수를 써서 js로 동작

 

드롭다운 애니메이션 (누르면 밑으로 쫙 나오는 거)

max-height: 가장큰높이

로 해야 함 (메뉴의 높이가 다르므로)

그래서 누르기 전에는 

max-height: 0을 해놓고

누르면 max-height:80px으로 설정

 

 

더보기
  document
    .querySelector('#header .lang_btn')
    .addEventListener('click', function () {
      document.querySelector('#header .lang_wrap').classList.toggle('on');
    });

lang_btn 안에 lang도 있는데 그냥 lang_wrap부모 한 번에 클릭해서 전부 on 되게 하기 toggle 클래스 사용 

toggle은 누르면 껐다켰다 하는 기능이라 헤더처럼 add remove가 아님

 

 

모바일 메뉴

클릭하면 햄버거가 x로 변하고 초록색 버튼으로

 

css 코드

더보기
#header .open_btn {
    display: inline-flex;
    width: 34px;
    height: 34px;
    border: 1px solid #fff;
    border-radius: 50%;
    background: none;
    /* 인라인블럭 사이는 4px 간격이 있음(자간때문에) */
    margin-left: 16px;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 3px 0;
  }
  #header .open_btn i {
    width: 14px;
    height: 2px;
    background:#fff;
    border-radius: 2px;
    transition: all 0.2s;
  }
  #header .open_btn.on {
    background: #7FD1A6;
    border:none;
  }
  #header .open_btn.on i {
    transform: translate(0px,5px) rotate(135deg);
  }
  #header .open_btn.on i:nth-of-type(2) {
    transform: scaleX(0);
  }
  #header .open_btn.on i:nth-of-type(3) {
    transform: translate(0,-5px) rotate(-135deg);
  }

인라인 블럭 인라인 플랙스 사이는 4px 간격이 있음 자간 때문에

그래서 margin 20 넣어야 하는 거 16으로 넣어줌

display block이나 flex로 하면 kor버튼이랑 모바일 버튼 떨어지기 때문에 일렬로 되게 inline flex 넣음

 

transfrom: translate(0, 5px) rotate(135deg)

누르면 -가 / 으로 바뀌는 거, 회전하고 이동하면 회전한 값을 기준으로 이동되기 때문에 회전 전부터 위치를 잡고 돌리는 편이 좋음

 

그리고 nth-of-type()

html에서 이미 위에 span이 있어서 그냥 nth-child 하면 span까지 같이 묶인다 그래서 of type으로 같은 태그끼리만 비교할 수 있게,

2번째 거는 width를 0으로 하면 왼쪽으로 줄어드는데

그렇게 하지 않고 가운데로 사라지게 scaleX(0)을 하면 된다

 

그리고 역시 .on함수를 걸고 js에서 동작하게 함

 

더보기
// 모바일메뉴
  // 이벤트핸들러 안에서 this는 이벤트가 연결된 요소를 의미
  document
    .querySelector('#header .open_btn')
    .addEventListener('click', function () {
      this.classList.toggle('on');
    });

 

전부 다 window.addEventListener('DOMContentLoaded', function() {

 안에 들어있는 거임

 

그리고 addEventListener의 이벤트핸들러에서 화살표 함수 안 쓰는 이유

화살표함수의 this는 생성시 바깥쪽으로 잡힘 그래서 저 위에 있는 window가 됨

아래처럼 하면 눌러도 작동이 안 됨

  // 화살표함수의 this는 함수생성시점에서 바깥부모함수의 this와 일치
  // 바깥쪽 window 이벤트핸들러가 부모함수이므로 this는 window임
  // document.querySelector('#header .open_btn').addEventListener('click', () => {
  //   this.classList.toggle('on');
  // });

 

화살표함수는 내장메서드의 콜백함수로만 사용

scroll, resize, load등의 이벤트 window에서 사용

click, mouseenter, mouseleave 등은 요소에서 사용

 

 

 

동일 요소를 여러곳에서 사용시 변수에 넣어서 사용함

 

무슨 말이냐면 이것처럼

const header = document.querySelector('#header');

  // header fixed
  window.addEventListener('scroll', function () {
    // 세로스크롤바의 위치값
    let _scrollY = window.scrollY;

    if (_scrollY > 0) {
      header.classList.add('fixed');
    } else {
      header.classList.remove('fixed');
    }
  });

 

원래는 document.querySelector('#header')를 classList 앞마다 썼는데 이러면 귀찮으니까

맨 위에 const header로 아예 변수를 만들어서

여러번 쓸 때 그냥 변수 이름만 넣어도 동작되게끔

 

 

요소 선택할 때는 querySelector 또는 getElemenById


 

 

 

타이머 함수

 

더보기
// 타이머함수
// 콘솔에 1초마다 10까지 출력하시오(setInterval, clearInterval)
// let cnt = 0;
// const intervalId = setInterval(() => {
//   cnt++;
//   console.log(cnt);
//   if (cnt === 10) {
//     clearInterval(intervalId);
//   }
// }, 1000);
// 화면에 5부터 0까지 카운트 보여주고 네이버로 이동하기
window.addEventListener('DOMContentLoaded', function () {
  function showCount(cnt, el, url) {
    const countEl = document.querySelector(el);
    countEl.innerHTML = cnt;
    const intervalId = setInterval(() => {
      cnt--;
      countEl.innerHTML = cnt;
      if (cnt === 0) {
        clearInterval(intervalId);
        location.href = url;
      }
    }, 1000);
  }
  showCount(10, '.count', 'http://google.com');
});

 

 

 

10초 뒤 구글 페이지로 이동함

 

페이지 이동 코드

window.location.href = 'http://~'

window는 생략 가능

 

일정 시간마다 실행되어야 하는 로직작성시에 사용함

setInterval, clearInterval

clearInterval로 멈출 때 interval 고유값이 필요한데 모르니까 변수로 넣어 줘야 함

 

const intervalId = setInterval( () => {} 이런식으로

그리고 

if (cnt === 10) // 10 됐을 때 {

clearInterval(intervalId);

 이런 식으로 멈춤

 

1000은 1초

 

setTimeout() 일정시간 후 한번만 실행


 

 

 

성적 산출 프로그램

 

window.addEventListener('DOMContentLoaded', function () {
  // 함수이므로 다른 버튼 클릭시 실행가능, 다른파일에서 호출하는 함수가 아니므로 내부함수로 구현
  function getScore() {
    // id 요소선택, 탐색속도가 좀더 빠름
    let kor = parseInt(document.getElementById('score1').value);
    let eng = parseInt(document.getElementById('score2').value);
    let mat = parseInt(document.getElementById('score3').value);

    // 입력값이 빈칸이거나 문자인 경우 return으로 함수실행종료
    if (isNaN(kor) || isNaN(eng) || isNaN(mat)) {
      alert('점수를 입력하시오');
      return;
    }

    // if(!isNaN(kor) && !isNaN(eng) && !isNaN(mat)){
    let avg = (kor + eng + mat) / 3;
    let pass = avg >= 60 ? '합격' : '불합격';

    let msg = '국어점수: ' + kor + '<br>';
    msg += '영어점수: ' + eng + '<br>';
    msg += '수학점수: ' + mat + '<br>';
    msg += '평균점수: ' + avg.toFixed(2) + '<br>';
    msg += '합격여부: ' + pass;

    document.querySelector('.main_score .message').innerHTML = msg;
  }

  // else {
  // alert
  // }
  // }

  // 함수명을 이벤트핸들러로 전달하여 콜백함수 실행
  document
    .querySelector('.main_score .result_btn')
    .addEventListener('click', getScore);
});

 

입력 값은 맨 앞에 parserInt를 넣어 주면 정수 숫자타입으로 변경

Number 써도 되는데 문자 있으면 안 됨 parseInt는 string도 됨

 

isNaN 은 값이 NaN인지 확인하는 함수

그래서 숫자가 아닌 빈칸이나 문자를 넣으면 NaN이 나오게 되고, Nan이 나오면 alert로 점수를 입력하라 메세지를 띄운 뒤에 함수 종료 (return으로 하면 종료됨)

평균점수 avg.에 toFixed(2)는 소수점 자리 출력

2라고 써서 소수점 2자리까지 출력되게 함

평균 저수가 33.33333333이면 33.33

60점이면 60.00 이런 식으로

그리고 반올림된다

 

.innerHTML 은 속성

메서드(함수) 괄호잇어야됨, 객체 안에 만들어진 함수

속성은 = 써서 대입하면 됨

 

 

 

 

안 쓰면 alert 때문에 이렇게 뜬다

 

 

재귀함수도 있음

5! 10! 이런 거 할 때

// 재귀함수: 함수내부에서 자신을 다시 호출함
function factorial(num) {
  if (num === 1) {
    return 1;
  }

  return num * factorial(num - 1);
}
let result3 = factorial(10);
console.log(result3);

 

'씹덕티스토리에코딩의등장이라' 카테고리의 다른 글

jquery  (0) 2024.04.12
유투바이오 메인 비주얼 부분들  (0) 2024.04.11
LG그룹 IR 정보 (테이블)  (0) 2024.04.01
자바스크립트  (0) 2024.04.01
애니메이션  (0) 2024.03.28

댓글