はてなブログ無料版: トップページを魅力的にカスタマイズする方法⑦
⑦カウントアップアニメーション
はてなブログ無料版のトップページを、自分好みのスタイルにカスタマイズする方法を紹介するシリーズの7回目です。
以下、今回の内容となります。
- カウントアップアニメーションの実装
- Intersection Observer(スクロール監視)によるイベントトリガー
今回は、数値をカウントアップするアニメーションの実装方法を紹介します。カウントアップのイベントトリガーには、Intersection Observerを利用しています。
振り返り
はてなブログ無料版でトップページをカスタマイズする方法について、これまで以下の内容を紹介して参りました。
① 基本設定、見出しの装飾、コンタクトへのリンクボタン
② Animate.cssによるスライドアニメーションとホバー効果1
③ Animate.cssによるスライドアニメーションとホバー効果2
④ Flickityによるカルーセルスライダーの導入
⑤ Animate.cssを使ったフリップアニメーションとポートフォリオのディスプレイ
⑥ GSAPによるカルーセルの実装
今回も引き続き、トップページのカスタマイズを紹介させていただきます。今回メインで紹介するのは、下記デモページにある見出し「What Do We Offer」のブロックにあたります。
デモページ
今回のカスタマイズ
Web Designing Enhance your online presence with visually stunning designs. Our creative solutions blend aesthetics and functionality for a seamless user experience tailored to your brand. App Development Turn ideas into reality with our experienced developers. From concept to deployment, we optimize apps for various platforms, ensuring a smooth and engaging user interface. Web Application Experience the future of online interaction with our innovative web applications. Streamline tasks, access information, and enhance communication through dynamic and interactive solutions.What Do We Offer
カスタマイズのポイント
data-target
属性とwidth
プロパティを紐付け、カウントアップによりライン伸長をアニメーション化しています。
またスクロールに応じたアニメーションにはIntersection Observerを利用し、メディアクエリによる画面幅に準じたレイアウトの最適化(レスポンシブ対応)も実装しています。
ライブラリのCDN
以下のCDNコードをheadなどに配置することによって、それぞれのライブラリが利用可能になります。CDNとは、Content Delivery Networkの略で、簡単に言うとインターネット経由でファイルを配信する仕組みのことです。
jQuery
<script src="//code.jquery.com/jquery-3.7.1.min.js"></script>
Font Awesome
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
jQueryはJavaScriptコードの簡素化に利用しています。
ソースコード
HTMLの構造
コードの解説
以下、コードを3つのブロックに分けて解説します:
このブロックは、異なるプログラミングスキルに対するパーセンテージバーを表示するためのコードです。各スキルには特定の背景色が割り当てられ、 このブロックは、各スキルに関する詳細情報を表示するためのコードです。各スキルにはアイコン、見出し、およびテキストが含まれており、それぞれのスキルに対する説明が提供されています。アイコンにはFont Awesomeを利用しています。 このブロックは、数値カウンターを表示するためのコードです。各カウンターアイテムにはアイコン、数値、およびテキストが含まれており、それぞれの項目に対する統計情報が表示されます。解説が開きます
<div class="special-wrap">
<div class="skills">
<dl>
<!-- HTMLスキル -->
<dt>HTML</dt>
<dd class="skill-percent html" style="background: #f06429" data-target="90"></dd>
<!-- CSSスキル -->
<dt>CSS</dt>
<dd class="skill-percent css" style="background: #2864f0" data-target="85"></dd>
<!-- 他のスキルも同様に続く -->
<!-- ... -->
</dl>
</div>
</div>
data-target
属性の数値は各パーセンテージを表します。
<div class="skill-details">
<!-- Web Designingに関する情報 -->
<div>
<span class="special-icons">
<i class="fa-regular fa-heart"></i>
</span>
<span>
<p class="special-heading">タイトル</p>
<p class="special-text">ディスクリプション</p>
</span>
</div>
<!-- App Developmentに関する情報 -->
<div>
<!-- アイコンとテキストのセット -->
</div>
<!-- Web Applicationに関する情報 -->
<div>
<!-- アイコンとテキストのセット -->
</div>
</div>
<div id="counter">
<div class="counter">
<!-- 各項目に関する情報 -->
<div class="counter-item">
<!-- アイコンと数値、テキスト(項目名)のセット -->
</div>
<!-- 各項目に関する情報 -->
<div class="counter-item">
<!-- アイコンと数値、テキスト(項目名)のセット -->
</div>
<!-- 同様に続く -->
<!-- ... -->
</div>
</div>
data-target
属性の数値は各カウンターの数値を表します。
CSS・JavaScriptコードを用いて、ここでdata-target
属性に指定した数値までカウントアップするアニメーションを適用します。
CSSスタイル
コードの解説
以下、コード内表記によるCSSコードの解説です:
margin、paddingの指定順は上 -> 右 -> 下 -> 左です。 text-transform属性は、大文字・小文字の表記を変更することができます。
解説が開きます
.special-wrap {
display: flex; /* フレキシブルボックスレイアウトを有効化 */
width: 1170px; /* コンテナの幅を指定 */
left: calc(50% - 585px); /* 水平方向に中央寄せ */
position: relative; /* 相対的な位置指定 */
}
/* 棒グラフ・スキル詳細のブロック幅を、それぞれ全体の50%に */
.skills, .skill-details {
width: 50%;
}
/* 内側に余白を追加 */
.skills {
padding: 20px;
}
/* 内側の左右に余白を追加 */
.skill-details {
padding: 0 20px;
}
/* バーの背景に水平ラインを設置 */
.skills dt:after {
content: "";
display: block;
width: 100%;
height: .5em;
background-color: #e0e0e0;
}
/* バーのスタイル */
.skills dd {
width: 0; /* デフォルト値を0に指定 */
height: .5em;
position: relative;
top: -.5em;
margin: 0;
}
width: 0
: HTMLのdata-target
属性で指定した数値まで、バーがアニメーションで拡がります。/* アイコンのスタイル */
.special-icons {
font-size: 45px;
margin: 10px 10px 0px 0px;
}
/* スキル詳細の見出しスタイル */
.special-heading {
text-transform: capitalize; /* 文字列をキャピタライズ(最初の文字だけ大文字に) */
letter-spacing: 1.5px;
font-weight: 700;
}
/* スキル詳細のテキストスタイル */
p.special-text {
color: #606060;
line-height: 1.4em;
margin: -1em 0 .46em;
font-size: .85em;
word-break: break-all; /* 英字を単語の途中で改行 */
}
#counter {
width: 100vw; /* ビューポートの100%の幅 */
position: relative;
left: calc(50% - 50vw); /* 水平方向に中央寄せ */
background: url(背景画像のURL); /* 背景画像の指定 */
background-repeat: no-repeat;
background-attachment: fixed; /* 背景画像を固定 */
background-size: cover;
background-position: 50% 78%;
}
/* カウンターの背景に半透明のレイヤーをかぶせる */
#counter::before {
background: rgba(0, 0, 0, .7);
content: "";
position: absolute;
width: 100%;
height: 100%;
}
/* 数値カウンターのコンテナスタイル */
.counter {
margin: 50px auto;
padding: 40px 0;
max-width: 1170px;
display: flex;
flex-wrap: wrap;
}
/* 各数値カウンターアイテムのスタイル */
.counter-item {
width: 25%;
padding: 10px;
text-align: center;
color: #fff;
position: relative;
}
/* アイコンスタイル */
.counter-item i {
font-size: 2em;
}
/* 数値のスタイル */
.counter-value {
font-size: 3em;
line-height: 1em;
font-weight: 700;
margin: .2em 0 .1em;
transition: all .3s linear;
font-family: 'Righteous'; /* Googleフォント */
}
/* 数値カウンターのテキストスタイル */
.counter .counter-text {
font-size: .88em;
text-transform: uppercase;
letter-spacing: .22em;
font-family: 'Montserrat'; /* Googleフォント */
}
/* ウィンドウ幅が1170px以下の場合のスタイル */
@media (max-width: 1170px) {
.special-wrap {
width: 100vw; /* 幅をブラウザ幅いっぱいに設定 */
left: calc(50% - 50vw); /* 水平方向に中央寄せ */
}
}
/* ウィンドウ幅が768px以下の場合のスタイル */
@media (max-width: 768px) {
.special-wrap {
flex-direction: column; /* 縦方向にスタックするように変更 */
width: 100%;
left: unset; /* 左位置をリセット */
}
.skills, .skill-details {
width: calc(100% - 40px); /* 左右に20pxずつの余白を持たせる */
}
.skill-details {
padding: 20px; /* スキル詳細の内側に余白を追加 */
}
.counter-item {
width: calc(50% - 20px); /* 数値カウンターの幅を調整 */
}
}
JavaScript
コードの解説
このJavaScriptコードは、jQueryを使用してスキルバー(skill-percent)および数値カウンター(counter-value)をアニメーション化するためのものです。3つのブロックに分け、コードを解説します:
"parseInt"は文字列を整数に変換します。
解説が開きます
$(function() {
$('.counter-value, .skill-percent').each(function() {
const target = parseInt($(this).data('target'), 10);
const animateFn = $(this).hasClass('counter-value') ? animateCounter : animateWidth;
new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
animateFn(entry.target, target);
entry.target.unobserve(entry);
}
});
}, { threshold: .5 }).observe(this);
});
});
$(function() {
」
$('.counter-value, .skill-percent').each(function() {
」
const target = parseInt($(this).data('target'), 10);
」
const animateFn = $(this).hasClass('counter-value') ? animateCounter : animateWidth;
」
new IntersectionObserver((entries) => { ... }, { threshold: .5 }).observe(this);
」
observer.unobserve(entry.target);
」
function animateWidth(element, target) {
let currentWidth = 0;
const step = Math.ceil(target / 50);
const interval = setInterval(() => {
currentWidth += step;
$(element).width(`${currentWidth}%`);
if (currentWidth >= target) {
clearInterval(interval);
$(element).width(`${target}%`);
}
}, 30);
}
function animateWidth(element, target) { ... }
」
let currentWidth = 0;
」
const step = Math.ceil(target / 50);
」
const interval = setInterval(() => { ... }, 30);
」
currentWidth += step;
」
$(element).width(
${currentWidth}%);
」
if (currentWidth >= target) { ... }
」
function animateCounter(element, target) {
let currentValue = 0;
const step = Math.ceil(target / 50);
const interval = setInterval(() => {
currentValue += step;
$(element).text(currentValue);
if (currentValue >= target) {
clearInterval(interval);
$(element).text(target);
}
}, 30);
}
function animateCounter(element, target) { ... }
」
let currentValue = 0;
」
const step = Math.ceil(target / 50);
」
const interval = setInterval(() => { ... }, 30);
」
currentValue += step;
」
$(element).text(currentValue);
」
if (currentValue >= target) { ... }
」
このコードは、Intersection Observerを使用して要素が画面内に表示されたときにアニメーションをトリガーし、バーの幅や数値カウンターを滑らかに増加させます。
アレンジ
背景画像の固定/スクロール
cssコードの65行目、background-attachment
プロパティの値を変更することにより、背景画像をページのスクロールのときに固定するか・一緒にスクロールさせるか指定できます。
#counter { /*前略*/ background-attachment: scroll; /* 背景画像を一緒にスクロール */ background-attachment: fixed; /* 背景画像を固定 */ background-attachment: local; /* 背景画像を要素内容に関して固定 */ /*前略*/ }
交差監視を継続する
JavaScriptコードの10行目、entry.target.unobserve(entry);
をコードから外すと、スクロールで一旦要素が画面外に消えて再び画面に表示されるたび、アニメーションイベントが発火します。
つまり、カウントアップを0からやり直します。
entry.target.unobserve(entry);
は、イベント発火後にIntersection Observerの監視を外す構文です。
おさらい
コードのまとめ
- jQuery CDN:
<script src="//code.jquery.com/jquery-3.7.1.min.js"></script>
- Font Awesome CDN:
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
- HTML: (GitHubサイトへ)
- CSS: (GitHubサイトへ)
- JavaScript: (GitHubサイトへ)
おわりに
以上、数値データに応じたカウントアップアニメーションと、Intersection Observerを使ったイベントトリガーの実装について解説しました。これらのテクニックを取り入れることで、ブログやサイトのビジュアル体験を向上させ、読者との魅力的なインタラクションを築くことができます。
今後のブログ運営において、より魅力的でユーザーフレンドリーなページを作り上げる一助となれば幸いです。
次回も引き続き、トップページのカスタマイズを紹介します(^^♪
これまでの記事
はてなブログ無料版: トップページを魅力的にカスタマイズする方法
① 基本設定、見出しの装飾、コンタクトへのリンクボタン
② Animate.cssによるスライドアニメーションとホバー効果1
③ Animate.cssによるスライドアニメーションとホバー効果2
④ Flickityによるカルーセルスライダーの導入
⑤ Animate.cssを使ったフリップアニメーションとポートフォリオのディスプレイ
⑥ GSAPによるカルーセルの実装