210903 개발일지

📌 학습한 내용


전체 코드 : 💾

To-do List

: 입력된 값을 리스트에 추가하고, 삭제 버튼으로 삭제, 완료 버튼으로 리스트 하단으로 이동

1. html, css로 디자인

  • reset.css 로 디폴트값들 초기화

  • text-indent : 값이 양수이면 들여쓰기, 값이 음수이면 내어쓰기 적용, 디폴트값은 0

  • html파일에서 <li>는 주석처리

  • <inpu>placeholder 디자인 (일부 브라우저에서만 지원 -> prefix 넣어주기)

header input::-webkit-input-placeholder {
	color: #ffffff;
}

2. add버튼 클릭 시 리스트에 추가

// add 객체에 접근
var addBtn = document.getElementById('add'); 

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

	// if 문으로 입력된 값이 있는 경우/없는 경우 분기처리
	if(value) {
		addListTodo(value);
		document.getElementById('txt').value = "";
	}
});
  • .value<input>에 입력된 값 가져옴

  • (입력된 값을 리스트로 추가한 후에,) <input>창 비워주기
    (1) <form> 안에 <input>이 존재할 때, reset()메서드 사용해 이전 상태로 돌려주기
    (2) <input> 사용 시, getElementById<input>영역에 value지정 후, 빈 문자열 재할당 ✔

3. 입력된 값 리스트에 추가

function addListTodo(text) {

	// 함수 호출 시, todo 영역을 가져오고 <li> 생성
	var list = document.getElementById('todo');
	var item = document.createElement('li');
	// <input>에 입력한 글자를 `<li>`의 값으로 할당
	item.textContent = text;

	// 버튼 영역을 감싸는 <div class="buttons"> 생성 
	var buttons = document.createElement('div');
	buttons.classList.add('buttons');

	// 리스트 삭제/완료 버튼 생성
	var remove = document.createElement('button');
	remove.classList.add('remove');
 	// removeList 이벤트와 연동
	remove.addEventListener('click', removeList); 

	var complete = document.createElement('button');
	complete.classList.add('complete');
 	// completeList 이벤트와 연동
	complete.addEventListener('click', completeList);

	// 조립 (안쪽에서 부터 바깥쪽으로)
	buttons.appendChild(remove);
	buttons.appendChild(complete);
	item.appendChild(buttons);

	// 가장 마지막에 입력한 값이 리스트의 최상단에 위치되게 하기
	// childNodes[0] - 가장 먼저 나오는 <li>?의 위치(인덱스)
	list.insertBefore(item, list.childNodes[0]);
}
  • createElement() : 인수로 넣은 html 태그를 만들어 반환

  • 부모.insertBefore() : 첫 번째 인수로 삽입할 요소를 전달, 해당 요소가 들어갈 위치

4. remove 버튼 클릭 시, 리스트에서 삭제

// 1. 클릭한 영역의 <li> 삭제
// 2. 클릭한 영역 가져오기

function removeList() {
	// this = remove 객체
 	// parentNode를 활용해 remove 객체의 부모의 부모인 <li> 선택
	var item = this.parentNode.parentNode; 
	var parent = item.parentNode;  // <ul> 선택

	parent.removeChild(item);
}
  • .parentNode : 해당 요소의 부모태그를 반환

4. complete 버튼 클릭 시, 리스트 하단으로 이동

function completeList() {

	var item = this.parentNode.parentNode;
	var parent = item.parentNode;
	
	var id = parent.id;
	// 삼항 연산자 사용 -> <li>가 어떤 <ul>안에 있는가에 따라 달라짐
	var target = (id === 'todo')
			? document.getElementById('completed')
			: document.getElementById('todo');

	// 삭제 기능
	parent.removeChild(item);

	// 최신 값을 최상단에 배치
	target.insertBefore(item, target.childNodes[0]);
}

*.id : 해당 요소의 id의 속성값 반환 프로퍼티

Mouse Animation

: 마우스의 움직임에 따라 이미지가 이동

1. html, css로 디자인

.page-container {
	position: fixed;
	width: 100%;
	height: 100%;
	background-color: #ffffff;
}

.page-back {
	position: absolute;
	height: 120%;
	width: 120%;  
    /* 자식의 크기가 부모보다 더 크게 만들어줌 */

	left: -10%;
	top: -10%;
	background-size: cover;
	background-position: center;
	background-image: url(bg.jpg);
}
  • 상하좌우 모든 영역에 10% 만큼 화면보다 크게 설정

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

// 필요한 요소 및 객체 호출
var pageContainer = document.querySelector('.page-container');
var pageBack = document.querySelector('.page-back');

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

// 이벤트 추가
pageContainer.addEventListener('mousemove', function(e) {

	// 마우스의 현재 좌표를 가져오기 위해 이벤트 객체 e 활용 -> pageX, pageY
	// console.log('e.pageX', e.pageX);
	// console.log('e.pageY', e.pageY);

	// 마우스 좌표값 수치를 축소한 x, y 값을 생성
	var moveX = ((windowWidth / 2) - e.pageX) * 0.1;
	var moveY = ((windowHeight / 2) - e.pageY) * 0.1;
	// 해당 수치를 이용해 background-back 이 움직이는 효과 생성

	pageBack.style.marginLeft = moveX + "px";
	pageBack.style.marginTop = moveY  + "px";
  
  	// 템플릿 리터럴 사용 가능
  	pageBack.style.marginLeft = `${moveX}px`;
	pageBack.style.marginTop = `${moveY}px`;
})
  • mousemove : addEvenetListener의 첫 번째 인자 중 하나, 마우스 움직임이 있을 때
  • window.innerWidth : 화면(브라우저) 안쪽의 width값 반환
  • window.innerHeught : 화면(브라우저) 안쪽의 height값 반환
  • 움직임이 있는 애니메이션은 gpu를 활용하는 transform, translate 속성을 사용하는 것이 성능면에서 효율적(css3) -> 부드러운 애니메이션 동작 처리
  • margin, top 등은 연산을 처리하는 cpu를 활용
pageBack.style.transform = `translate(${moveX}px, ${moveY}px)`;

Scroll Top

: 스크롤 동작에 따라, 상단 네비게이션의 배경색과 글자색 변경

1. html, css 디자인

nav {
	position: fixed;
	width: 100%;
	background-color: #000000;

	border-bottom: solid 1px rgba(0, 0, 0, .1);

	padding: 22px 100px;
	transition: all 0.5s;

	display: flex;
	justify-content: space-between;
	align-items: center;
}
  • transition: all : 모든 속성이 transition 효과를 갖게 된다.

2. 스크롤 시, 이벤트 추가

스크롤 접근 방법 (모두 같은 효과를 담당)

  1. window.addEventListener('scroll')
  2. winddow.onscroll = function () {스크롤 발생시 동작되는 기능}
  3. document.addEventListener('scroll')

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

// 스크롤 감지 property
window.addEventListener('scroll', function () {
	var top = window.scrollY // explore 제외 모든 브라우저 지원
		|| window.pageYOffset // explore 9 이상부터 지원
		|| document.documentElement.scrollTop // explore 8 이하 가능, chrome x
		|| document.body.scrollTop // chrome, safari, opera, edge 가능
    
    // 스크롤 위치가 내려갈 때, .active 클래스 추가
    // 한 줄짜리 if문은 삼항연산자 사용
	(top > 50)
		? fixedNav.classList.add('active')
		: fixedNav.classList.remove('active');
});
  • top 변수를 생성해 스크롤 좌표를 감지하는 여러 property를 ||(or 연산자, vertical bar)로 연결해줌 -> 브라우저마다 호환되는 속성이 다르기 때문(크로스 브라우징)

  • <nav> 영역이 자연스럽게 fade in/out 되는 이유는 transition: all을 css에 미리 적용했기 때문

방법2. 스크롤이 내려가는 상태/올라가는 상태인지에 따라 색 변경

  • 기존 스크롤 위치로 기준점을 잡고, 기준점에 스크롤의 현재 위치를 빼준 결과값에 따라 스크롤의 상태를 구분
var fixedNav = document.querySelector('nav');

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. 브라우저가 스크롤의 상태 파악 (권장 x)

  • 이벤트 객체 e를 사용해 e.wheelDelata 값이 양수냐 음수냐에 따라, 현재 스크롤이 내려간 상태인지 올라간 생태인지를 파악할 수 있다.

(참고 사이트: https://cometome1004.tistory.com/63)

var fixedNav = document.querySelector('nav');

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');
}
  • 브라우저마다 wheelDelta의 존재여부가 다르기 때문에 삼항연산자를 사용

  • 단 해당 코드는 Firefox에서는 동작하지 x -> addEvenetListern의 첫 번째 인자로 DOMMouseScroll을 넣어줘야 한다.

접속한 브라우저의 종류를 파악해 EventListner의 첫 번째 인자값 구분

  • navigator.userAgent : 현재 접속한 브라우저의 종류를 문자열로 반환

  • .indexOf() : 문자열에서 사용 가능한 메서드, 인자로 받은 값이 존재하면 해당 글자의 좌표값을 , 존재하지 않으면 -1을 반환

var isFirefox = (navigator.userAgent.indexOf('Firefox') !== -1);
var wheelEvt = isFirefox ? 'DOMMousScroll' : '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');
};

Modal

: 버튼 클릭 시 (반투명한 레이어가 깔려있는 팝업창) modal창을 띄우고, 닫기 버튼 혹은 창이 아닌 곳을 클릭하면 modal 창이 닫히는 효과

1. html, css로 디자인

<해당 객체를 보이거나 보이지 않게 처리하는 css속성>

  • visibility: hidden <-> visible; : 영역은 차지한 상태로 사용자 눈에만 보이지 않음.
  • display: none <-> block : 공간의 크기를 인식하지 x, 보이지도 않고 해당 공간도 존재하지 않게 됨, 삭제의 개념
.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;
}
  • visibility: hidden;으로 최소상태에서의 modal창을 숨김 처리 하고, .active 클래스를 삽입했을 시 보이는 형태로 넣어준다.

2. 버튼 클릭시 modal창 띄우기

// 필요한 객체 불러오기
var btnModal = document.querySelector('.btn-modal');
var modal = document.querySelector('.modal');
var btnClose = document.querySelector('.modal .btn-modal');

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

3. Close 버튼 클릭시 modal창 닫기

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

4. modal창 외부 클릭 시, modal 창 닫기

  • e.target : 이벤트 발동 시, 참조된 태그 반환
  • .contains : 문자열 포함 여부 확인
modal.addEventListener('click', function(e) {
	var target = e.target; 
  	// 클릭한 영역에 'modal-layer'가 포함되어 있다면 작동
	var isLayer = target.classList.contains('modal-layer');

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

📌 학습내용 중 어려웠던 점


📌 해결방법


📌 학습소감


반복해서 작업하다 보니 자주 쓰는 객체와 메서드는 눈에 익었다. 확실히 처음 실습때 보다 따라가는 속도도 빨라졌고, 약간이지만 디자인도 넣을 수 있을 정도로는 여유가 생긴 것 같다. 😊

좋은 웹페이지 즐겨찾기