반응형
자바스크립트와 css를 사용해서 무한 슬라이드, requestAnimationFrame, cancelAnimationFrame
간단히 왼쪽에서 오른쪽으로 무한하게 움직이지만 해당 영역에 마우스를 가져가면 멈추고, 영역에서 나가면 다시 움직이는 슬라이드 효과를 만들어보자.
html
<div id="slide" v-cloak>
<!-- 마우스가 slide 되는 영역에 위치하면 멈추고, 나가면 다시 움직임 -->
<div class="slide_box" @mouseenter="slideMove(true)" @mouseleave="slideMove(false)">
<!-- 무한하게 가로로 slide 되는 영역(왼쪽에서 오른쪽으로) -->
<div class="slider_area" :style="'transform:translateX('+ slideinfo.leftx +'%)'">
<!--
slide 되는 영역의 컨텐츠가 있는 영역.
js에서 복제되어 하나 더 이어서 배치될 예정.
(예: <div class="slider_wrap"></div><div class="slider_wrap"></div>)
-->
<div class="slider_wrap">
<div class="exbox"></div>
<div class="exbox"></div>
<div class="exbox"></div>
<div class="exbox"></div>
</div>
</div>
</div>
</div>
css
/* slide가 되려고 컨텐츠들 가로 정렬 */
.slider_area{display:flex;}/* translateX가 0%가 되면 다시 -50%로 가도록 */
.slider_wrap{display:flex;}
js(vue)
const {createApp, ref, computed, onMounted} = Vue;
const slide = {
setup() {
// ref() 를 사용하면 js에선 .value로 찾아감(예: slideinfo.value.leftx). dom에는 .value 없음(예: slideinfo.leftx)
// reactive() 는 항상 .value 필요없음
const slideinfo = ref({
percent: 0,
aniId: null,
leftx: -50,// .slider_wrap이 하나 더 복제되어 이어 붙어서 slide가 무한히 되도록 .slider_area의 x위치를 -50% 로 이동
})
// 왼쪽에서 오른쪽으로 계속 이동
leftMove =() => {
slideinfo.value.leftx = -50 + (slideinfo.value.percent += 0.03);
slideinfo.value.aniId = slideinfo.value.percent && requestAnimationFrame(leftMove);
// slide 영역의 x위치가 0%보다 크고, %가 50보다 크면
if(slideinfo.value.leftx > 0 && slideinfo.value.percent > 50){
// 다시 0%에서 시작
slideinfo.value.percent = 0;
}
}
// 계속 움직이는 영역에
const slideMove = (bo) => {
// 마우스를 가져가면 멈춤
if(bo) {
cancelAnimationFrame(slideinfo.value.aniId);
}
// 마우스가 벗어나면 다시 움직임
else {
requestAnimationFrame(leftMove);
}
}
onMounted(() => {
// .slider_wrap 복제
let cloneSlider = document.querySelector(".slider_wrap").cloneNode(true);
// .slider_area에 복제된거 넣음(prepend : 앞에 붙임, append : 뒤에 붙임)
document.querySelector(".slider_area").append(cloneSlider);
// 왼쪽에서 오른쪽으로 계속 이동
requestAnimationFrame(leftMove);
})
return {
slideinfo, slideMove,
}
}
};
createApp(slide).mount("#slide");
- 끝 -
반응형
댓글