初めに
今回は、スクロールすると、ふわっと要素が出てくるアニメーションを実装しました。
スクロールすると「画像」「記事の閲覧と検索」「説明文」がふわっと出てきます。
こういうのが下に4つくらい続くイメージです。
ここを参考に実装しました
以下のyoutubeを見て実装しました。
私の記事は自分で忘れないようにまとめてるだけなので、
実装したいかたは以下の動画を見ていただくと良いかと思います。
また、youtubeで紹介されてるものと私のコードは完全一致しておらず、
所々変えていますのでご注意ください!!!
まずはHTMLから
homes/top.html.erb
#ひとまずコンテナーで囲む
<div class="container mt-5">
<h4 id="how_to_use" class="text-center">How to use</h4>
#全体をulで囲み、アニメーションひとつひとつはliタグで囲む
<ul class="contents">
#animationTargetはのちにJavascriptで使うのでスペルミス注意!
<li class="animationTarget">
#asset_pathは本番環境対応のために記載しています。img-fluidで画像もレスポンシブ対応
<%= image_tag asset_path("show2.jpg"),class:"img-fluid"%>
#テキスト全体をcontentsTextで囲みます。
<div class="contentsText">
#タイトル
<h2>記事の閲覧と検索</h2>
#説明文の箇所
<p>Postの一覧ページでは投稿記事の一覧が見れます。<br>
<strong>タグでの検索/ランキング/並び替え/検索</strong>ができます。<br>
<strong>検索機能(インクリメンタルサーチ)</strong>を使用して<br>
投稿を探しましょう。<br>
参考になった投稿には、いいねやコメントをしましょう</p>
</div>
#ここで1個目のアニメーションの塊終了。
</li>
<li class="animationTarget">
<%= image_tag asset_path("show3.png"),class:"img-fluid"%>
<div class="contentsText">
<h2>マイページ</h2>
<p><strong>Activity</strong>ではあなたのmy portでの活動をグラフにして表示します。<br>
記事にいいねがつくと<strong>TEU(ポイント)</strong>が溜まっていきます。</p>
</div>
</li>
<li class="animationTarget">
<%= image_tag asset_path("show4.png"),class:"img-fluid"%>
<div class="contentsText">
<h2>勉強会</h2>
<p>社内での<strong>勉強会</strong>の開催をお知らせできます。<br>
詳細ページから勉強会への参加、退出ができます。<br>
管理者はメンバーに<strong>メール</strong>での一斉通知が可能です。</p>
</div>
</li>
省略
</div>
続いてCSS
app/assets/stylesheets/homes.scs
#how_to_use{
color:rgba(70, 130, 180,.8);
font-family: Chalkduster, "Bradley Hand", Courier, "Segoe Print", sans-serif
}
li{
margin:0;
list-style:none;}
#子要素を親要素を基準に配置したいので親要素にはrelative記載します。
.contents li {
position: relative;
}
#最初のli以外にmargin-topを効かせます。これないとギュッとしてしまいます。
.contents li:not(:first-of-type){
margin-top: 50px;
}
#奇数のliタグの.contentsTextは右0!要するに一番右に配置ということです。
.contents li:nth-of-type(odd) .contentsText{
right: 0;
}
#偶数タグについてはflex-startを使用し左寄せです。この指定がないとpタグがずれます。
.contents li:nth-of-type(even) .contentsText{
align-items:flex-start;
}
#インライン要素なので、display:block;を指定しないとマージンききません。
.contents li:nth-of-type(even) .img-fluid{
display:block;
margin-left: auto;
}
#flex-direction:column;は上から下なので要素は縦に並びます。
#align-items:flex-end;で右よせ
#position:absolute;で上から○%の位置というのを指定します。
.contentsText{
display:flex;
flex-direction:column;
align-items:flex-end;
position:absolute;
top:30%;
}
#white-sapce:nowrap;で改行はしないようにします。
#opacity: 0;で表示されなくなります。
#transform: translateY(20px);は最初20px下に配置しておきます。x軸y軸のxyです。
#transition: 1s;1秒かけてにゅっと現れます。opacityに1秒かけます
.contents h2{
font-size:50px;
font-weight:bold;
white-sapce:nowrap;
background-color:rgba(135, 206, 250,.8);
padding:10px 20px;
border-radius:5px;
opacity: 0;
transform: translateY(20px);
transition: 1s;
}
.contents p{
line-height: 1.6;
font-size:15px;
max-width:500px;
padding:15px;
margin-top:30px;
border-radius:5px;
background-color:rgb(224, 255, 255);
opacity: 0;
transform: translateX(20px);
transition: 1s;
}
.img-fluid{
opacity: 0;
transform: translateX(-20px);
transition: 1s;
}
#transform:noneは下やら左に配置していたものを元に戻すという記述です。
#opacity:1で表示されます。
#クラスにshowをつけるのはjavascriptで行います。
.contents li.show h2,
.contents li.show p,
.contents li.show .img-fluid{
transform:none;
opacity:1;
}
Javascriptを書いていく
// 以下で、4つの要素を取得している
const targetElement = document.getElementsByClassName("animationTarget");
// 4件取得できる
// console.log(targetElement);
console.log("画面の高さ",window.innerHeight)
// 以下スクロールで検知します の記述
document.addEventListener("scroll",function(){
// 4件分上からの距離を取得する for文で回す
for (let i = 0; i < targetElement.length; i++){
// 上からの距離と、その要素がある程度たっしてから 6割くらい見えたら
const getElementDistance = targetElement[i].getBoundingClientRect().top + targetElement[i].clientHeight *.6
// console.log(getElementDistance);
// いまのブラウザの高さ取得
// if (i === 1){
// console.log(getElementDistance)
// }
if(window.innerHeight > getElementDistance) {
// これにより、表示されたanimation targetのクラスにshowがつく
targetElement[i].classList.add("show")
}
}
})
if(window.innerHeight > getElementDistance)
でクラスに
showをつけています。
これは、画面の高さ(スクロールしてきた長さ)が、ここで出てきてと指定した長さより
大きくなったらshowをつけます。