7개 레이어를 쌓아서 입체감이 느껴지는 페럴랙스 페이지 구현 예제
window의 크기가 조정되면 resize
이벤트가 발생합니다.
일부 이전 브라우저에서는 resize
모든 HTML 요소에 이벤트 핸들러를 등록할 수 있었다. onresize
속성 을 설정 하거나 addEventListener()
모든 요소에 핸들러를 설정하는 데 사용할 수 있다. 그러나 resize
이벤트는 window
객체에서만 발생한다(즉, 에서 반환됨 document.defaultView
). window
개체 에 등록된 핸들러만 resize
이벤트를 수신한다.
window.requestAnimationFrame()
메서드는 브라우저에 애니메이션을 수행하고 싶다고 알리고 브라우저가 다시 실행하기 전에 애니메이션을 업데이트하기 위해 지정된 함수를 호출하도록 요청한다. 이 메서드는 다시 실행하기 전에 호출할 인수로 콜백을 사용한다.
<main>
<div class="progress"><span class="progressBar"></span></div>
<section class="mainPage">
<div class="imageWrap">
<div class="parallax_image" id="parallax_0"></div>
<div class="parallax_image" id="parallax_1"></div>
<div class="parallax_image" id="parallax_2"></div>
<div class="parallax_image" id="parallax_3"></div>
<div class="parallax_image" id="parallax_4"></div>
<div class="parallax_image" id="parallax_5"></div>
</div>
</section>
<section class="subPage">
<div id="parallax_6"></div>
<div class="innerWrap">
<div class="contWrap">
</div>
</div>
</section>
</main>
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
overflow-x: hidden;
}
main {
position: relative;
}
main .progress {
position: fixed;
width: 100%;
height: 2px;
background-color: black;
z-index: 10000;
}
main .progress .progressBar {
position: fixed;
width: 0%;
background: #ffa600;
height: 2px;
z-index: 10001;
-webkit-transition: width .1s ease;
-o-transition: width .1s ease;
transition: width .1s ease;
}
section {
position: relative;
width: 100%;
}
section.mainPage {
background: -webkit-gradient(linear, left top, left bottom, from(#4b0220), to(#691c46));
background: -o-linear-gradient(#4b0220, #691c46);
background: linear-gradient(#4b0220, #691c46);
padding-bottom: 50px;
}
section.mainPage h1.title {
position: fixed;
text-align: center;
color: #fff;
font-size: 2.7rem;
padding-top: 20vh;
width: 400px;
left: calc(50% - 200px);
}
section.mainPage .imageWrap {
height: 1100px;
overflow-y: hidden;
}
section.mainPage .imageWrap .parallax_image {
position: fixed;
width: 100%;
height: inherit;
background-position: top center;
background-size: auto 100%;
background-repeat: no-repeat;
}
section.mainPage .imageWrap .parallax_image:nth-child(1) {
background-image: url(../images/main_0.png);
}
section.mainPage .imageWrap .parallax_image:nth-child(2) {
background-image: url(../images/main_1.png);
}
section.mainPage .imageWrap .parallax_image:nth-child(3) {
background-image: url(../images/main_2.png);
}
section.mainPage .imageWrap .parallax_image:nth-child(4) {
background-image: url(../images/main_3.png);
}
section.mainPage .imageWrap .parallax_image:nth-child(5) {
background-image: url(../images/main_4.png);
}
section.mainPage .imageWrap .parallax_image:nth-child(6) {
background-image: url(../images/main_5.png);
background-size: cover;
}
section.subPage {
background: -webkit-gradient(linear, left top, left bottom, from(#000), to(#691c46));
background: -o-linear-gradient(#000, #691c46);
background: linear-gradient(#000, #691c46);
}
section.subPage #parallax_6 {
position: relative;
background: url(../images/main_6.png) bottom center no-repeat;
background-size: auto 1100px;
height: 400px;
width: 100%;
top: -400px;
}
section.subPage .innerWrap {
position: relative;
margin: 0 auto;
padding: 500px 0;
width: 900px;
height: 4500px;
}
@media only screen and (max-width: 768px) {
section.subPage .innerWrap {
width: 100%;
}
}
let x = 0;
let y = 0;
let mx = 0;
let my = 0;
let speed = 0.03;
let scrollTop = 0;
let parallax_0, parallax_1, parallax_2, parallax_3, parallax_4, parallax_5, parallax_6, parallax_7;
window.onload = function () {
progressBar = document.getElementsByClassName("progressBar")[0];
parallax_0 = document.getElementById("parallax_0");
parallax_1 = document.getElementById("parallax_1");
parallax_2 = document.getElementById("parallax_2");
parallax_3 = document.getElementById("parallax_3");
parallax_4 = document.getElementById("parallax_4");
parallax_5 = document.getElementById("parallax_5");
parallax_6 = document.getElementById("parallax_6");
window.addEventListener('resize', stageResize, false);
window.addEventListener('mousemove', mouseMove, false);
window.addEventListener('scroll', scrollFunc, false);
stageResize();
loop();
}
function scrollFunc(e) {
scrollTop = document.documentElement.scrollTop;
// scroll값을 받아서 %로 바꿔서 per에 할당한디.
let per = Math.ceil(scrollTop / (_documentHum - _windowHNum) * 100);
// per에 할당한 값을 progressBar 너비값에 할당한다.
progressBar.style.width = per + "%";
// 스크롤을 하면 y값이 주어진 값만큼 움직인다.
parallax_0.style.transform = "translate3d(0px ," + scrollTop * .03 + "px , 0px"; // +는 아래로 내려감
parallax_1.style.transform = "translate3d(0px ," + -scrollTop * .03 + "px , 0px"; // -는 위로 올라감
parallax_2.style.transform = "translate3d(0px ," + -scrollTop * .12 + "px , 0px";
parallax_3.style.transform = "translate3d(0px ," + -scrollTop * .16 + "px , 0px";
parallax_4.style.transform = "translate3d(0px ," + -scrollTop * .22 + "px , 0px";
parallax_5.style.transform = "translate3d(0px ," + -scrollTop * .25 + "px , 0px";
}
//
function stageResize() {
// document 너비값을 구해서 _documentHum에 할당
_documentHum = document.body.offsetHeight;
// window 높이값을 구해서 _windowHNum에 할당
_windowHNum = window.outerHeight;
}
// 마우스가 움직이면 이미지도 움직이는 loop
function loop() {
// 마우스 가속도
mx += (x - mx) * speed;
my += (y - my) * speed;
// 이미지 4,5,6번은 마우스 움직임에 따라 주어진 값만큼 움직인다.
parallax_4.style.transform = "translate3d(" + mx / 140 + "px , " + -scrollTop * .22 + "px, 0px)";
parallax_5.style.transform = "scale(1.1) translate(" + mx / 50 + "px , " + -scrollTop * .25 + "px)";
parallax_6.style.transform = "scale(1.2) translate(" + mx / 20 + "px , " + -my / 20 + "px)";
window.requestAnimationFrame(loop);
}
function mouseMove(e) {
// window의 너비와 높이값을 구해서 /2 해주면 정가운데가 0이된다.
// 마우스를 오른쪽으로 가면 +고 왼쪽으로 가면 -이다.
x = (e.clientX - window.innerWidth / 2);
y = (e.clientY - window.innerHeight / 2);