スクロールアクションを『GSAP』というJavaScriptライブラリの『ScrollTrigger』を使用して実装してみました。スクロールに合わせてテキストや画像が表示されます。
まずはデモサイトをご覧ください。
今回は、スクロールに合わせて、テキストを左から徐々に表示させたり、画像を下からフワッと表示させるアニメーションをかけてみました。
アニメーション毎のソースコード
テキストが左から右へ徐々に表示される
CSSの「clip-path」を使用して、「GSAP」の「ScrollTrigger」でclassの付け替えを行なっています。
HTML
/**html**/
<div class="ttl">
<h2 class="ttl__clip">ScrollTrigger</h2>
<span class="ttl__clip__line"></span>
</div>
Scss
/**scss**/
$color-bg:linear-gradient(133deg, rgba(250,246,246,1) 0%, rgb(223, 223, 223) 50%, rgb(196, 196, 196) 100%);
$color-bg02: linear-gradient(133deg, rgb(70, 70, 70) 0%, rgb(19, 19, 19) 50%, rgb(0, 0, 0) 100%);
$color-white: #fff;
@mixin media($breakpoint:md){
@media #{map-get($breakpoint-up,$breakpoint)}{
@content;
}
}
$breakpoint-up: (
'bp760':'screen and(max-width:760px)',
)!default;
.ttl {
display: table;
margin-left: 5%;
position: relative;
&__clip {
position: relative;
display: inline-block;
font-size: clamp(3rem, 4vw ,7rem);
transition: clip-path .6s cubic-bezier(0.18, 0.06, 0.23, 1) .2s;
clip-path: inset(0 100% 0 0);
padding: 0 12px 8px 0;
&__line {
height: 2px;
background-color: #000;
width: 0;
display: block;
opacity: 0;
position: absolute;
bottom: 0;
left: 0;
&.slid__open {
width: 100%;
opacity: 1;
transition: all .4s cubic-bezier(0.18, 0.06, 0.23, 1) 0s;
}
}
&.slid__open {
clip-path: inset(0);
}
}
}
JavaScript
繰り返し使えるように、「forEach」を使っています。
/**js**/
// テキストを徐々に表示させる
gsap.registerPlugin(ScrollTrigger);
const ttl__clips = document.querySelectorAll('.ttl__clip');
ttl__clips.forEach((ttl__clip, index) => {
gsap.to(ttl__clip, {
scrollTrigger: {
trigger: ttl__clip,
start: 'top-=300 center+=100',
end: 'top top-=100',
}
});
ScrollTrigger.create({
trigger:ttl__clip,
id: index+1,
start: 'top center+=300',
end: 'top top-=100',
once: true,
toggleClass: {
targets: ttl__clip,
className: 'slid__open',
},
});
});
const ttl__clip__lines = document.querySelectorAll('.ttl__clip__line');
ttl__clip__lines.forEach((ttl__clip__line, index) => {
gsap.to(ttl__clip__line, {
scrollTrigger: {
trigger: ttl__clip__line,
start: 'top center+=300',
end: 'top top',
}
});
ScrollTrigger.create({
trigger:ttl__clip__line,
id: index+1,
start: 'top center+=300',
end: 'top top',
once: true,
toggleClass: {
targets: ttl__clip__line,
className: 'slid__open',
},
});
});
テキストがスクロールに合わせて横に動く
スクロールに合わせて左右に横移動します。
HTML
/**html**/
<section class="scroll">
<div class="scroll__wrap">
<p class="scroll__x">GSAPSCROLLGSAPSCROLLGSAPSCROLLGSAPSCROLLGSAPSCROLL</p>
</div>
<p class="fade__img"><img src="images/shapelined-_JBKdviweXI-unsplash.jpg" alt=""></p>
</section>
Scss
/**scss**/
$color-bg:linear-gradient(133deg, rgba(250,246,246,1) 0%, rgb(223, 223, 223) 50%, rgb(196, 196, 196) 100%);
$color-bg02: linear-gradient(133deg, rgb(70, 70, 70) 0%, rgb(19, 19, 19) 50%, rgb(0, 0, 0) 100%);
$color-white: #fff;
@mixin media($breakpoint:md){
@media #{map-get($breakpoint-up,$breakpoint)}{
@content;
}
}
$breakpoint-up: (
'bp760':'screen and(max-width:760px)',
)!default;
/*背景テキスト*/
.scroll {
overflow: hidden;
padding-top: 20%;
padding-bottom: 20%;
&__wrap {
p {
font-size: clamp(8rem, 15vw, 16rem);
font-weight: 900;
color: #ebe9e9;
opacity: 0.1;
-webkit-text-stroke: 1px #000;
}
}
}
JavaScript
/**js**/
// 背景テキストがスクロールに合わせて左へ動く
gsap.fromTo( '.scroll__x', {
x: "-15.1797px",
},
{
x: '-1603.18px',
scrollTrigger: {
trigger: '.scroll',
start: 'top center+=300' ,
end: 'bottom top',
scrub: 0.8,
}
}
);
背景がスクロールに合わせて左から右へ広がって表示される
HTML
/**html**/
<div class="scroll__bg">
<span class="scroll__cover"></span>
</div>
Scss
/**scss**/
$color-bg:linear-gradient(133deg, rgba(250,246,246,1) 0%, rgb(223, 223, 223) 50%, rgb(196, 196, 196) 100%);
$color-bg02: linear-gradient(133deg, rgb(70, 70, 70) 0%, rgb(19, 19, 19) 50%, rgb(0, 0, 0) 100%);
$color-white: #fff;
@mixin media($breakpoint:md){
@media #{map-get($breakpoint-up,$breakpoint)}{
@content;
}
}
/*背景徐々に表示*/
.scroll__bg {
position: relative;
padding: 32px 0 48px;
display: flex;
justify-content: space-between;
@include media(bp760) {
display: block;
padding: 15% 0;
}
.scroll__cover {
position: absolute;
top: 0;
left: 0;
z-index: -1;
background: $color-bg02;
transform-origin: left;
width: 100%;
height: 100%;
}
.fade__img {
width: 50%;
margin-right: 5%;
margin-top: 10%;
@include media(bp760) {
margin-left: 5%;
margin-right: 0;
width: 90%;
}
img {
width: 100%;
height: auto;
}
}
}
JavaScript
/**js**/
// 背景が徐々に表示
gsap.fromTo('.scroll__cover', {
x: "0",
scaleX: 0,
scaleY: 1,
},
{
x: '0',
scaleX: 1,
scrollTrigger: {
trigger: '.scroll__bg',
start: 'top-=350 center+=100',
end: 'bottom-=400 center+=100',
scrub: 0.5,
once: true,
}
}
)
//下から画像フェードイン
const fadeUps = document.querySelectorAll('.fade__img');
fadeUps.forEach((fadeUp, index) => {
gsap.fromTo(fadeUp, {
autoAlpha: 0,
y:20,
},
{
autoAlpha: 1,
y: 0,
scrollTrigger: {
trigger: fadeUp,
start: 'top center+=100',
end: 'top top',
// toggleActions: "play pause resume reverse",
}
});
ScrollTrigger.create({
trigger: fadeUp,
id: index+1,
start: 'top center+=100',
end: 'top top',
once: true,
// toggleActions: "play pause resume reverse",
});
})
// 背景が徐々に表示
gsap.fromTo('.scroll__cover', {
x: "0",
scaleX: 0,
scaleY: 1,
},
{
x: '0',
scaleX: 1,
scrollTrigger: {
trigger: '.scroll__bg',
start: 'top-=350 center+=100',
end: 'bottom-=400 center+=100',
scrub: 0.5,
once: true,
}
}
)
//下から画像フェードイン
const fadeUps = document.querySelectorAll('.fade__img');
fadeUps.forEach((fadeUp, index) => {
gsap.fromTo(fadeUp, {
autoAlpha: 0,
y:20,
},
{
autoAlpha: 1,
y: 0,
scrollTrigger: {
trigger: fadeUp,
start: 'top center+=100',
end: 'top top',
// toggleActions: "play pause resume reverse",
}
});
ScrollTrigger.create({
trigger: fadeUp,
id: index+1,
start: 'top center+=100',
end: 'top top',
once: true,
// toggleActions: "play pause resume reverse",
});
})
テキストを1文字ずつしたから徐々に表示させる
HTML
/**html**/
<div class="text__up">
<span class="text__up__js">S</span>
<span class="text__up__js">c</span>
<span class="text__up__js">r</span>
<span class="text__up__js">o</span>
<span class="text__up__js">l</span>
<span class="text__up__js">l</span>
<span class="text__up__js">T</span>
<span class="text__up__js">r</span>
<span class="text__up__js">i</span>
<span class="text__up__js">g</span>
<span class="text__up__js">g</span>
<span class="text__up__js">e</span>
<span class="text__up__js">r</span>
</div>
<div class="text__up text__up__02">
<span class="text__up__js">S</span>
<span class="text__up__js">c</span>
<span class="text__up__js">r</span>
<span class="text__up__js">o</span>
<span class="text__up__js">l</span>
<span class="text__up__js">l</span>
<span class="text__up__js">T</span>
<span class="text__up__js">r</span>
<span class="text__up__js">i</span>
<span class="text__up__js">g</span>
<span class="text__up__js">g</span>
<span class="text__up__js">e</span>
<span class="text__up__js">r</span>
</div>
Scss
/**scss**/
//一文字ずつしたから表示
.text__up {
display: flex;
justify-content: center;
margin: 15% auto 16px;
overflow: hidden;
span {
display: block;
font-size: 3.5rem;
font-weight: bold;
letter-spacing: 0.04em;
}
&__02 {
margin: 0 auto 25%;
span {
font-size: 1.8rem;
}
}
}
JavaScript
/**js**/
//一文字ずつしたから表示
const text__ups = document.querySelectorAll('.text__up__js');
text__ups.forEach((text__up, i) => {
gsap.fromTo(text__up, {
opacity:0.1,
y: '110%',
},
{
opacity:1,
y: 0,
duration: 0.7,
delay: i * 0.03,
scrollTrigger: {
trigger: '.text__up',
start: 'top center+=300',
end: 'top center+=300',
once: true,
}
},
)
});
画像を下からフワッとスケールしながら表示させる
HTML
/**html**/
<div class="flower">
<div class="flower__img flower__img__01 js-fadeup">
<img src="images/pink.jpg" alt="">
</div>
<div class="flower__img flower__img__02 js-fadeup">
<img src="images/yellow.jpg" alt="">
</div>
<div class="flower__img flower__img__03 js-fadeup">
<img src="images/blue.jpg" alt="">
</div>
</div>
<div class="grid__img">
<div class="grid__img__item grid__img__item__01">
<img src="images/hito01.jpg" alt="">
</div>
<div class="grid__img__item grid__img__item__02">
<img src="images/hito02.jpg" alt="">
</div>
<div class="grid__img__item grid__img__item__03">
<img src="images/hito03.jpg" alt="">
</div>
<div class="grid__img__item grid__img__item__04">
<img src="images/hito04.jpg" alt="">
</div>
<div class="grid__img__item grid__img__item__05">
<img src="images/hito05.jpg" alt="">
</div>
</div>
Scss
/**scss**/
/*画像が下から表示される*/
.flower {
padding: 22% 0;
background-color: $color-white;
&__img {
width: 58.04688%;
position: relative;
&:nth-child(even) {
margin: 15% 0 15% auto;
}
&__02 {
width: 41.25%;
}
&__03 {
width: 48.125%;
margin: {
left: 8%;
};
}
}
}
.grid__img {
position: relative;
display: block;
background-color: $color-white;
padding-top: 50%;
padding-bottom: 20%;
&__item {
position: absolute;
display: block;
overflow: hidden;
&::after {
content: "";
width: 100%;
height: 102%;
background-color: $color-white;
position: absolute;
top: 0;
left: 0;
transition: transform 1.5s cubic-bezier(0.215, 0.61, 0.355, 1) 0.5s;
transform: translate3d(0, 0%, 0);
}
&.js-after {
&::after {
transform: translate3d(0, -102%, 0);
}
img {
opacity: 1;
transform: scale(1);
}
}
img {
width: 100%;
height: 100%;
display: block;
opacity: 0;
transform: scale(1.3);
transition: transform 1.8s cubic-bezier(0.215, 0.61, 0.355, 1) 1s, opacity 1.2s cubic-bezier(0.473, 0.427, 0, 0.993) 0.8s;
object-fit: cover;
}
&__01 {
top: 0;
left: 8.28125%;
width: 25.46875%;
}
&__02 {
width: 42.8125%;
left: -9.0625%;
top: 26.25%;
height: 35%;
}
&__03 {
width: 27.5%;
left: 35%;
top: 0;
height: 74%;
}
&__04 {
width: 25.46875%;
right: 10.78125%;
top: 6.58824%;
}
&__05 {
width: 36.4%;
right: 0;
top: 33.17647%;
}
}
}
.js-fadeup {
position: relative;
overflow: hidden;
&::after {
content: "";
width: 100%;
height: 102%;
background-color: $color-white;
position: absolute;
top: 0;
left: 0;
transition: transform 1.5s cubic-bezier(0.215, 0.61, 0.355, 1) 0.5s;
transform: translate3d(0, 0%, 0);
}
&.js-after {
&::after {
transform: translate3d(0, -102%, 0);
}
img {
opacity: 1;
transform: scale(1);
}
}
img {
width: 100%;
height: auto;
display: block;
opacity: 0;
transform: scale(1.3);
transition: transform 1.8s cubic-bezier(0.215, 0.61, 0.355, 1) 1s, opacity 1.2s cubic-bezier(0.473, 0.427, 0, 0.993) 0.8s;
}
}
JavaScript
/**js**/
// 画像を下から表示させる
const jsFadeUps = document.querySelectorAll('.js-fadeup');
jsFadeUps.forEach((jsFadeUp, index) => {
gsap.to(jsFadeUp, {
scrollTrigger: {
trigger: jsFadeUp,
start: 'top-=200 bottom',
end: 'bottom top',
scrub: true,
}
});
ScrollTrigger.create({
trigger: jsFadeUp,
start: 'top-=200 bottom',
end: 'bottom top',
id: index+1,
once: true,
toggleClass: {
targets: jsFadeUp,
className: 'js-after',
}
})
})
const gridItems = document.querySelectorAll('.grid__img__item');
gridItems.forEach((gridItems, index) => {
gsap.to(gridItems, {
scrollTrigger: {
trigger: gridItems,
start: 'top bottom',
end: 'bottom top',
scrub: true,
}
});
ScrollTrigger.create({
trigger: gridItems,
start: 'top bottom',
end: 'bottom top',
id: index+1,
once: true,
toggleClass: {
targets: gridItems,
className: 'js-after',
}
})
})