html
과css
만으로 만들었던 자기소개 페이지🤨
'자바스크립트 배우면 이것도 만들고 저것도 만들고...'
마음속으로 다짐했던 자바스크립트 기능을 넣어보기로 했다.
html이랑 css만 할 때는 편했지? 자바스크립트를 사용하자 에러가 나는 내 웹 페이지..
제발 움직여줘 강아ㅈ..아니 사이트야....
처음 자기소개 페이지를 만들 때 다른 벨로그 글들을 보며 참고하면서 가장 적용해보고 싶었던 타이핑 효과! html
과 css
만으로 이루어진 정적인 페이지에 타이핑 효과로 동적인 움직임을 만들고 싶었다.
그런데 3줄이나 되는 메인 페이지 텍스트에 효과를 구현해내는 것은 쉽지 않았다.(여러 번의 실패와 구글링으로 터득(?)하긴 했지만..)
구현 내용
- 타이핑 애니메이션 구현
- 타이핑 줄바꿈 적용
- 글자를 따라오는 커서 제작
const content = "안녕하세요.\n제 이름은 김영현 입니다.\n소통하는 개발자가 되고 싶어요!"
// 타이핑 하고싶은 텍스트 작성
const text = document.getElementById("dynamic");
let index = 0;
let txt = "";
function typing(){
if(index < content.length){
txt += content[index];
text.innerText = txt;
index++
}
}
setInterval(typing,320);
원래 처음에 let txt="";
을 통해 빈문자열을 선언하지 않고 진행했지만 왜인지 텍스트 내에 띄어쓰기가 없어진 채로 타이핑이 되었다. 오기로 구글링을 한 결과, https://stackoverflow.com/questions/47768523/empty-spaces-are-ignored-by-the-innertext-property 사이트에서 해답을 찾을 수 있었다!
💡 새롭게 알게된 내용
innerText
,textContent
그리고innerHTML
의 차이점
textContent
: textContent의 값은 식별자 노드의 내부 콘텐츠를 text/plain 으로 파싱한 결과. 즉, 해당 요소 내부의 원시 텍스트(raw text) 이다. 그래서 다른 프로퍼티들에 비해 파싱이 빠르다.innerText
: innerText의 값은 텍스트가 최종적으로 (화면에) 렌더링 된 모습, 예를 들어 내용 숨김이나 줄바꿈 같이 의도적인 스타일링이 들어간 후의 모습이 된다.(그래서 텍스트 내 줄바꿈이 적용됐던 것!)innerHTML
: innerHTML의 값은 가져온 텍스트에 포함된 태그를 인식하여 태그를 적용시킨 후 문자를 보여준다.
**innerHTML
은 성능상 좋지 않고 XSS 공격에도 취약하므로 innerHTML은 사용하지 않는 것이 좋다.
정확히 말해서 Back-to-top
버튼이다. 여러 웹 사이트를 볼 때 사이트 하단에 고정되어 있는 Top버튼은 '클릭'시에 사이트 최상단으로 이동하게 된다. 자바스크립트를 통해 상단까지 부드럽게 스크롤이 되는 효과를 구현했다. 하지만 Top버튼에 쓴 방법 외에 다른 방법을 찾긴 했다.(적용 효과 3번에서 계속 📌)
구현 내용
- 사이트 스크롤 2/3 지점부터 서서히 나타나는 Top버튼 구현
- 커서를 올렸을 때 바뀌는 버튼 모양
- 부드러운 스크롤 구현
//top버튼 만들기
let btt = document.getElementById('back-to-top'),
docElem = document.documentElement, //documentElement는 다큐먼트 자체를 가져온다.
offset,
scrollPos,
docHeight;
//문서 높이 구하기
docHeight = docElem.scrollHeight; // 문서 자체 높이를 docHeight에 넣어준다.
if(docHeight !== 0){
offset = docHeight / 1.5 ;
}
//스크롤 이벤트 만들기
window.addEventListener('scroll', function(){
scrollPos = docElem.scrollTop;
btt.className = (scrollPos > offset) ? 'visible' : '';
/* if문을 이런식으로 줄인다.
if(scrollPos > offset){
btt.className = 'visible';
}else{
btt.className = '';
}
*/
});
// 클릭하면 천천히 스크롤 만들기
btt.addEventListener('click',function(ev){
ev.preventDefault(); //`ev`를 통해서 전에 있던 링크속성을 가져오고 `.preventDefault`를 통해 속성을 막는다.
// docElem.scrollTop = 0;
scrollToTop();
})
function scrollToTop(){
// 일정시간 마다 할 일 = setInterval(할 일,시간)
// 할 일 = function(){실제로 할 일}
// 윈도우 스크롤이 0이 아닐때 window.scrollBy(0,-55);
// 스크롤 0이면 setInterval을 멈춰야 한다 = clearInterval(멈추려는 이름)
let scrollInterval = setInterval(function(){
if(scrollPos !== 0){
window.scrollBy(0,-100);
}else{
clearInterval(scrollInterval);
}
},15);
}
#back-to-top{
font-family: "GmarketSansMedium";
font-size: 1em;
position: fixed;
bottom: 11.7em;
right: 2.5em;
background-color: #eaeaea;
box-shadow: 0 0 0.4em 0 rgba(0, 0, 0, .25);
color: #383838;
border-radius: 5px;
padding: 0.8em;
text-transform: uppercase;
transition: all .3s;
cursor: pointer;
font-weight: 600;
display: inline-block;
opacity: 0;
}
#back-to-top:hover{
font-family: "GmarketSansbold";
background-color: #fff;
color: #4a86ff;
padding: 0.8em 2.5em;
}
#back-to-top.visible{
opacity: 1;
}
CSS에서 :hover
에 padding값을 바꾸면 커서를 올렸을 시 버튼 크기가 바뀌게 된다.
이전에 올렸던 자기소개 페이지 썸네일을 보면 화살표안에 GO!버튼이 있다. 시간문제로 완성하지 못한 버튼을 구현했다.
구현 내용
- GO!버튼 구현
- 버튼 클릭 시 about 타켓으로 이동
- 부드러운 스크롤 구현
let goBtn = document.getElementById("go");
aBtn = document.getElementById("menu-about"),
gBtn = document.getElementById("menu-goal"),
cBtn = document.getElementById("menu-contact");
// go버튼 뿐 만아니라 다른 menu버튼에도 똑같이 부드러운 스크롤을 적용.
goBtn.addEventListener('click',function(ev){
ev.preventDefault();
document.getElementById('about').scrollIntoView({behavior: "smooth", block: "start"})
});
aBtn.addEventListener('click',function(ev){
ev.preventDefault();
document.getElementById('about').scrollIntoView({behavior: "smooth", block: "start"})
});
gBtn.addEventListener('click',function(ev){
ev.preventDefault();
document.getElementById('goal').scrollIntoView({behavior: "smooth", block: "start"})
});
cBtn.addEventListener('click',function(ev){
ev.preventDefault();
document.getElementById('contact').scrollIntoView({behavior: "smooth", block: "start"})
});
아까 Top버튼에서 부드러운 스크롤을 위해 썼던 함수보다 훨씬 간단하게 자바스크립트 내장 함수인 .scrollIntoView
를 사용하여 구현했다.
💡 새롭게 알게된 내용
scrollIntoView
?
scrollIntoView()는 특정 요소를 기준으로 스크롤을 이동시킨다.element.scrollIntoView(); element.scrollIntoView(alignToTop); // Boolean parameter element.scrollIntoView(scrollIntoViewOptions); // Object parameter
이처럼 3개의 문법이 존재하는데
첫번째로 어떤 파라미터도 사용하지 않고 사용하거나
두번째로 Boolean 파라미터(true/false)를 사용하거나
(true는 요소의 상단, false는 요소의 하단을 기준으로 한다.)
세번째로 options 오브젝트를 넣어서 사용한다.문법
- behavior : 전환 에니메이션 정의 (auto || smooth)
- block : 수직 정렬 (start || center || end || nearest)
- inline : 수평 정렬 (start || center || end || nearest)
페이지 내에 있던 goal 요소들에 slide기능
을 구현해보기로 했다. 웹 사이트에서 진행하는 이벤트나 업데이트 소식이 슬라이드로 넘어간다. JQuery가 아닌 JS만으로만 구현해보려고 노력했다!✨
구현 내용
- 왼쪽 오른쪽 버튼 제작
- 끝까지 갔을 시 더이상 넘어가지 않고 다시 되돌아오기
let slides = document.querySelector(".goal-boxes"),
// `slides`는 left값을 바꿔줄 용도.
slide = document.querySelectorAll(".goal-boxes li"),
currentIdx = 0,
// 버튼을 눌렀을 때 순서를 만들어줘야 함.
slideCount = slide.length,
// 마지막인지 구분하기 위해 개수도 있어야 함.
slideWidth = 300,
slideMargin = 30,
prevBtn = document.getElementById("prev"),
// 이전 버튼
nextBtn = document.getElementById("next");
// 다음 버튼
slides.style.width = (slideWidth + slideMargin) * slideCount - slideMargin + 'px';
// 슬라이드의 width에 margin값을 더한거에 슬라이드의 개수를 곱한다음 마지막 마진크기를 빼줌.
// 문자열로 `px`을 붙여줘야 함.
function moveSlide(num){
slides.style.left = -num * 330 + 'px';
// 슬라이드의 left값을 330씩 옆으로 움직여야 함.
// -num을 해줘야 오른쪽에서 왼쪽으로 이동 가능.
currentIdx = num;
}
nextBtn.addEventListener('click', function(ev){
ev.preventDefault();
nextBtnClick();
});
prevBtn.addEventListener('click', function(ev){
ev.preventDefault();
prevBtnClick();
});
function nextBtnClick(){
if(currentIdx < slideCount - 3){
moveSlide(currentIdx + 1);
console.log(currentIdx);
}else{
moveSlide(0);
}
};
function prevBtnClick(){
if(currentIdx > 0){
moveSlide(currentIdx - 1);
console.log(currentIdx);
}else{
moveSlide(slideCount - 3);
}
};
멀티 슬라이드를 구현하기 위해 CSS내 goal 박스들의 스타일을 전부 flex에서 position:absolute로 바꿔주었다.(flex에서 구현할 방법은 없을까 궁금하다..나중에 꼭 찾아보기로)
prev, next 버튼을 클릭할 시 330px씩 양 옆으로 움직이게 되고 함수 내에 else문을 통해 더이상 움직이지 않고 초기화되도록 하였다.
💡 마치며
여러가지 자바스크립트 기능을 구현하면서 '역시 나는 아직 병*이다' 라는 생각이 점점 더 커졌다. 자바스크립트 내에서 코드를 통해 내가 하고싶은(또는 누군가가 하고싶은) 이벤트를 구현하는 게 얼마나 어려운 지를 새삼 깨닫게 된다.
무작정 innerHTML 사용했었는데, 새로운 사실 알게 됐어요! 감사합니다!!✨