0823 개발일지

Yesol Lee·2021년 8월 23일
0

AI스쿨_개발일지

목록 보기
42/57

학습내용

자바스크립트 주요기능 구현하기(1), (2): To-do, MouseAnimation, Scroll-top, Modal
github소스코드

To-do List

js-todo

  • 목표: 추가 버튼 클릭 시 input에 입력한 값을 할 일 리스트로 옮기고, 각 리스트 아이템의 삭제 버튼 누르면 삭제, 완료 버튼 누르면 완료 리스트 혹은 할 일 리스트로 이동

1. html, css 만들기

  • html 리스트 구조 만들어준 후 주석처리 함(js로 만들어 넣을거라서)
  • reset.css 활용함
  • text-indent: 들여쓰기(양수), 내어쓰기(음수), 기본값 0
header input {
    float: left;
    width: 100%;
    height: 50px;
    background-color: rgba(255,255,255,.3);
    border: 0;
    outline: none;

    color: #fff;
    font-size: 15px;

    text-indent: 18px;
}
  • input placeholder 글자색 바꾸기 (일부 브라우저에서만 지원)
header input::-webkit-input-placeholder {
    color: #fff;
}

2. 추가 버튼 클릭 시 input 내용 할일 리스트에 추가

  • input 태그 입력된 값은 value로 가져옴
  • input 비우기: form 태그 사용시에는 reset()있었지만 input은 value에 빈값 재할당
// add 버튼 객체 가져오기
var addBtn = document.getElementById('add');

// add 버튼 클릭 시 이벤트 
addBtn.addEventListener('click', function() {
    var value = document.getElementById('txt').value;

    // if문을 사용해서 value값이 있을 때를 구분해줌
    if(value) {
        addListTodo(value);
        document.getElementById('txt').value = '';
    }
});

3. 실제로 리스트에 태그 추가하는 메서드

function addListTodo(text) {
  	// 1. li 태그 넣을 ul 가져오기
    var list = document.getElementById('todo');
  
  	// 2. li 태그 만들고 text 삽입
    var item = document.createElement('li');
    item.textContent = text;

  	// 3. 버튼 감싸는 영역 만들기
    var buttons = document.createElement('div');
    buttons.classList.add('buttons');

  	// 4. 삭제, 완료 버튼 생성 및 이벤트리스너 붙이기
    var removeBtn = document.createElement('button');
    removeBtn.classList.add('remove');
    removeBtn.addEventListener('click', removeList);

    var completeBtn = document.createElement('button');
    completeBtn.classList.add('complete');
    completeBtn.addEventListener('click', completeList);

    // 5. 각 태그들 배치(조립)조립하기
    buttons.appendChild(removeBtn);
    buttons.appendChild(completeBtn);
    item.appendChild(buttons);

    // 6. 리스트의 최 상단에 아이템 삽입
  	// list.appendChild(item); // 가장 마지막에 삽입됨
    // childNodes[]로 리스트의 첫번째 자식 선택-> 그 앞에 삽입
    list.insertBefore(item, list.childNodes[0]);
};

삭제 버튼 이벤트 만들기

function removeList() {
    // this = 이벤트 발생하는 객체인 removeBtn
    // parentNode 활용해 부모의 부모인 li 태그 선택 
    var item = this.parentNode.parentNode;
    var parent = item.parentNode;

    parent.removeChild(item);
}

완료 버튼 이벤트 만들기

function completeList() {
    var item = this.parentNode.parentNode;
    var parent = item.parentNode;
    var id = parent.id;

    // 기존 리스트에서 삭제
    parent.removeChild(item);

    // 삼항연산자로 id값에 따라 target 영역 바꾸기
    var target = (id === 'todo') 
                ? document.getElementById('completed')
                : document.getElementById('todo');

    // 최신순 업데이트
    target.insertBefore(item, target.childNodes[0]);
}

Mouse Animation

  • 목표: 마우스 움직임을 따라 이미지가 움직이는 효과
    js-mouse-animation

1. html, css

  • html은 간단하게 화면 전체를 커버하는 영역과 그 안 사진을 넣을 영역으로 구성되고, 내부 사진 영역이 부모 태그보다 120% 큰 상태로 만들었다.
  • 사진 영역에 background로 사진을 채워주었다. left, top으로 이동시켜 네 방향 모두 화면보다 10% 큰 상태로 나가게 만들어주었다.
.page-back {
    position: absolute;
    width: 120%;
    height: 120%;

    background: url(bg.jpg) no-repeat;
    background-size: cover;
    background-position: center;
    
    left: -10%;
    top: -10%;
}

1. 필요한 객체 및 변수 가져오기

  • window.innerWidth: 브라우저 내부 너비
  • window.innerHeight: 브라우저 내부 높이
var pageContainer = document.querySelector('.page-container');
var pageBack = document.querySelector('.page-back');

var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;

2. 마우스 움직일 때 이벤트 추가

  • mousemove: 이벤트 종류 중 하나로 마우스 움직일 때마다 이벤트 일어남
  • mousemove를 이벤트객체 e로 받아서 마우스 현재 좌표를 나타내는 pageX, pageY 프로퍼티 사용 가능
  • 마우스 움직인 값을 축소해서 반영하는 x, y값 생성
var moveX = ((windowWidth/2) - e.pageX) * 0.1;
var moveY = ((windowHeight/2) - e.pageY) * 0.1;
  • 이미지 영역 움직이기: margin 등 cpu를 사용하는 속성보다 gpu를 사용하는 translate() 속성 사용하면 계산 분산되어 성능 개선됨
pageContainer.addEventListener('mousemove', function(e){
    var moveX = ((windowWidth/2) - e.pageX) * 0.1;
    var moveY = ((windowHeight/2) - e.pageY) * 0.1;

    pageBack.style.transform = `translate(${moveX}px, ${moveY}px)`;
});

Scroll

  • 목표: 스크롤 움직임에 따라 고정된 네비게이션의 배경색과 글자색이 바뀜
    js-scroll

1. html, css

  • transition: all: 클래스 변화로 인한 효과도 부드럽게 만들어 줌
nav {
    position: fixed;
    width: 100%;
    background-color: #000000;
    border-bottom: solid 1px rgba(0, 0, 0, .1);
    padding: 22px 100px;
    
    transition: all 0.5s;
}

2. 스크롤 이벤트 작성하기

스크롤 제어 3가지 방법 (같은 효과)

  1. window.addEventListener('scroll')
  2. window.onScroll = function () { ... }
  3. document.addEventListener('scroll')

1. 스크롤 일정 위치 이상 내려가면 색 변경

  • top 변수에 스크롤 좌표를 감지하는 여러 property를 or 연산자로 연결해준다. 브라우저마다 호환되는 속성이 다르기 때문이다.
  • top으로 가져온 스크롤 좌표값에 따라 미리 만들어 둔 active 클래스를 적용하거나 삭제해준다.
window.addEventListener('scroll', function() {
    var top = window.scrollY // explorer 제외 모든 브라우저
    || window.pageYOffset  // explorer 9 이상 가능
    || document.documentElement.scrollTop // explorer 8 이하 가능, chrome 불가
    || document.body.scrollTop; // 크롬, 사파리, 오페라, 엣지 사용 가능

    // 스크롤 위치 내려가면 nav class 추가해줌
    (top > 50) 
        ? fixedNav.classList.add('active')
        : fixedNav.classList.remove('active');
});

2. 스크롤 내려가는 상태/ 올라가는 상태에 따라 배경색 바꾸기

  • 기준 위치를 만들어 현재 스크롤 위치와 비교해 크거나 작은 것으로 현재 내려가는 중인지 올라가는 중인지 알아내기
var oldVal = 0; //기준점
window.addEventListener('scroll', function () {
    var newVal = window.scrollY
    || window.pageYOffset
    || document.documentElement.scrollTop 
    || document.body.scrollTop; 

    if(oldVal - newVal < 0) {
        fixedNav.classList.add('active');
    } 
    if(oldVal - newVal > 0) {
        fixedNav.classList.remove('active');
    }
    oldVal = newVal;
});

3. scroll 움직임 상태를 브라우저에서 받음 (권장하진 않음)

  • 이벤트리스너 첫번째 인자로 'wheel' 넣으면 scroll 움직임 상태를 브라우저에서 받을 수 있다. 그런데 파이어폭스에서는 해당 인자 대신 'DOMMouseScroll'이라는 인자를 사용해야 한다.
  • 브라우저마다 wheelDelta값이 있을수도 있고 없을수도 있어서 삼항연산자 사용
  • index에 저장한 wheelDelta (혹은 detail)값은 내려갈 땐 음수, 올라갈 땐 양수인 특징을 가졌다.
window.addEventListener('wheel', mouseWheelEvt);
window.addEventListener('DOMMouseScroll', mouseWheelEvt);

function mouseWheelEvt(e) {
    var index = e.wheelDelta ? e.wheelDelta : -e.detail;
    (index < 0)
        ? fixedNav.classList.add('active')
        : fixedNav.classList.remove('active');
};

4. 사용자가 접속한 브라우저 종류 알아내서 알맞은 이벤트리스너 인자 전달하기

  • navigator.userAgent: 접속한 브라우저 종류를 문자열로 리턴
  • navigator.userAgent.indexOf('Firefox'): 글자가 존재하면 위치값, 없으면 -1 리턴
var isFirefox = (navigator.userAgent.indexOf('Firefox')===-1) ? false : true;
var wheelEvt = isFirefox ? 'DOMMouseScroll': 'wheel';

window.addEventListener(wheelEvt, mouseWheelEvt);
function mouseWheelEvt(e) {
    var index = e.wheelDelta ? e.wheelDelta : -e.detail;

    (index < 0)
        ? fixedNav.classList.add('active')
        : fixedNav.classList.remove('active');
};
  • 목표: 버튼 클릭 시 모달창 띄우고 닫기 혹은 창 아닌 곳 클릭하면 모달창 닫기
    js-modal

1. html, css

  • Modal(모달): 레이어가 깔린 팝업창
  • visibility: hidden, visible 등의 속성값을 이용해 객체를 보이거나 안 보이게 할 수 있는 css 속성
  • visibility: hiddendisplay: none의 차이점: display는 객체 공간의 크기 인식 못해서 다른 객체가 땡겨지는데 visibility는 보이진 않지만 공간은 여전히 차지해서 레이아웃에 영향 주지 않는다.
  • 최초 상태는 안 보이게 하고 active인 경우에 보이도록 별도 클래스를 미리 만들어둔다.
.modal {
    position: fixed;
    visibility: hidden;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;

    opacity: 0;
    z-index: 999999;

    transition: all 0.5s;
}
.modal.active {
    visibility: visible;
    opacity: 1;
}
  • 모달창이 항상 창의 중심에 있도록 중앙정렬 공식 사용
.modal .modal-wrap {
    position: absolute;
    width: 500px;
    background-color: white;

    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

2. 버튼 누르면 모달창 보이게 하기

var btnModal = document.querySelector('.btn-modal');
var modal = document.querySelector('.modal');
var btnClose = document.querySelector('.modal .btn-close');

btnModal.addEventListener('click', function() {
    modal.classList.add('active');
});

3. 모달창 내 닫기 버튼 누르면 모달창 닫기

btnClose.addEventListener('click', function() {
    modal.classList.remove('active');
});

4. 모달창 밖을 클릭해도 모달창 꺼지게 하기

  • e 이벤트객체로 modal 영역 안에서 클릭한 영역의 태그를 반환하게 함
  • 클릭한 부분이 modal-layer인지 알기 위해 클릭한 태그의 클래스리스트에 contains를 사용함
modal.addEventListener('click', function(e) {
    var target = e.target; // modal 영역 안 클릭한 태그 반환
    var isLayer = target.classList.contains('modal-layer');

    if(isLayer) {
        modal.classList.remove('active');
    }
});

어려웠던 점

해결방법

소감

오늘은 자바스크립트를 이용해 자주 구현되는 기능들을 몇 가지 연습했다. 크로스 브라우징은 전혀 생각해보지 못했는데 배울 수 있어서 좋았다. 여러 다양한 웹디자인을 만들어 보고 싶다.

profile
문서화를 좋아하는 개발자

0개의 댓글