今回はGreenSock社が提供するJavaScriptアニメーションライブラリGSAPで
横スクロール、パララックス、時間差出現、ドラッグ操作などの要素を盛り込んだものを実装しました!
コピペしてすぐに実務で実装できるようにしております。ぜひ最後までご覧ください!
目次 非表示
1.実装イメージ
実装イメージは以下の通りです。
See the Pen 【GSAP】横スクロール+パララックス+時間差+ドラッグ操作=お洒落 by りょーすけ (@s_ryosuke_1242) on CodePen.
2.HTML
次にHTMLです。
ドラッグ操作を可能にするための要素が11行目にあります。(proxy => 代理、代わり)
<body>
<main>
<!-- SLIDER -->
<section class="description">
<div class="container">
<h2>途中から横スクロール</h2>
<p>横スクロール中はパララックス</p>
</div>
</section>
<div class="vertical-slider__wrap">
<div class="proxy"></div>
<section class="vertical-area teal">
<div class="img-wrap">
<div class="mask"></div>
<img src="https://ryo-sukeblog.net/wp-content/uploads/2022/04/sea.jpg" alt="" class="js-img">
<div class="heading-wrap"><h2>Beautiful World</h2></div>
</div>
</section>
<section class="vertical-area maroon">
<div class="img-wrap">
<div class="mask"></div>
<img src="https://ryo-sukeblog.net/wp-content/uploads/2022/04/cherry-blossoms.jpg" alt="" class="js-img img2">
<div class="heading-wrap"><h2>Sakura Nagashi</h2></div>
</div>
</section>
<section class="vertical-area olive">
<div class="img-wrap">
<div class="mask"></div>
<img src="https://ryo-sukeblog.net/wp-content/uploads/2022/04/scene.jpg" alt="" class="js-img img3">
<div class="heading-wrap"><h2>One Last Kiss</h2></div>
</div>
</section>
</div>
<section class="last-area">
<h2>横スクロール終了</h2>
</section>
<!-- END SLIDER -->
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/ScrollTrigger.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/Draggable.min.js"></script>
</body>
3.CSS
次にCSSです。
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.vertical-area h2{
color: white;
font-size: 56px;
width: 100%;
display: flex;
justify-content: center;
}
.vertical-area h2 span{
display: block;
}
.vertical-area .img-wrap{
width: 70%;
height: 80%;
position: relative;
overflow: hidden;
}
.vertical-area .img-wrap .mask{
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
background-color: rgba(0,0,0,.1);
z-index: 1;
}
.vertical-area .img-wrap img{
width: 130%;
height: 130%;
object-fit: cover;
}
.teal{
background-color:teal;
}
.maroon{
background-color: maroon;
}
.olive{
background-color: olive;
}
.last-area{
background-color: #222;
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.last-area h2{
color: white;
font-size: 40px;
}
.proxy{
position: absolute;
visibility: hidden;
}
4.JavaScript
最後にJavaScriptです。
HTMLのbodyタグの手前にも記述されていますがCDNで『ScrollTrigger』と『Draggable』を予めダウンロードしておきましょう
let sections = document.querySelectorAll(".vertical-area");
let scrollContainer = document.querySelector(".vertical-slider__wrap");
let images = gsap.utils.toArray(".js-img");
let heading = gsap.utils.toArray(".heading-wrap h2");
let scrollTween = gsap.to(sections, {
xPercent: -100 * (sections.length - 1),
ease: "none"
});
let horizontalScroll = ScrollTrigger.create({
animation: scrollTween,
trigger: scrollContainer,
pin: true,
scrub: 1,
// markers:true,
end: () => "+=" + scrollContainer.offsetWidth,
});
function txtSplit(el){//https://sinciate.co.jp/media/2999/
var content = el.textContent;
var text = content.trim();
var newHtml = "";
text.split("").forEach(function(v) {
newHtml += "" + v + "";
});
el.innerHTML = newHtml;
}
images.forEach((img, i) => {
gsap.to(img,{
scrollTrigger:{
trigger: img,
start:'top center',
end:'bottom center',
horizontal:true,
// markers:true,
scrub:.2,
containerAnimation:scrollTween,
},
x:-150,ease:"none"
});
});
heading.forEach((h, i) => {
txtSplit(h);
if(i === 0){
gsap.from(h.querySelectorAll('span'),{
scrollTrigger:{
trigger: h,
start:'top 10%',
// markers:true,
horizontal:true,
containerAnimation:scrollTween,
toggleActions:'play none none reverse'
},
stagger:{
each:0.02,
},
y:'30%',autoAlpha:0,ease:Power4.easeIn,duration:.4,
});
}else{
gsap.from(h.querySelectorAll('span'),{
scrollTrigger:{
trigger: h,
start:'10% center',
// markers:true,
horizontal:true,
containerAnimation:scrollTween,
toggleActions:'play none none reverse'
},
stagger:{
each:0.02,
},
y:'50%',autoAlpha:0,ease:Power4.easeIn,duration:.4,
});
}
});
// total scroll amount divided by the total distance that the sections move gives us the ratio we can apply to the pointer movement so that it fits.
var dragRatio = scrollContainer.offsetWidth / (window.innerWidth * (sections.length - 1));
var drag = Draggable.create(".proxy", {
trigger: scrollContainer,
type: "x",
onPress() {
this.startScroll = horizontalScroll.scroll();
},
onDrag() {
horizontalScroll.scroll(this.startScroll - (this.x - this.startX) * dragRatio);
}
})[0];