はてなブログ無料版: トップページを魅力的にカスタマイズする方法⑦

⑦カウントアップアニメーション

はてなブログ無料版のトップページを、自分好みのスタイルにカスタマイズする方法を紹介するシリーズの7回目です。

以下、今回の内容となります。

  • カウントアップアニメーションの実装
  • Intersection Observer(スクロール監視)によるイベントトリガー

今回は、数値をカウントアップするアニメーションの実装方法を紹介します。カウントアップのイベントトリガーには、Intersection Observerを利用しています。

affordable design product
https://pixabay.com/users/geralt-9301/

振り返り

はてなブログ無料版でトップページをカスタマイズする方法について、これまで以下の内容を紹介して参りました。

基本設定、見出しの装飾、コンタクトへのリンクボタン
Animate.cssによるスライドアニメーションとホバー効果1
Animate.cssによるスライドアニメーションとホバー効果2
Flickityによるカルーセルスライダーの導入
Animate.cssを使ったフリップアニメーションとポートフォリオのディスプレイ
GSAPによるカルーセルの実装


今回も引き続き、トップページのカスタマイズを紹介させていただきます。今回メインで紹介するのは、下記デモページにある見出し「What Do We Offer」のブロックにあたります。

デモページ

デモページを見る

今回のカスタマイズ

What Do We Offer
HTML
CSS
jQuery
SCSS
JavaScript
PHP
XML

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.

Projects Completed
Happy Customers
Cups Of Coffee
Awards


カスタマイズのポイント

data-target属性とwidthプロパティを紐付け、カウントアップによりライン伸長をアニメーション化しています。

またスクロールに応じたアニメーションにはIntersection Observerを利用し、メディアクエリによる画面幅に準じたレイアウトの最適化(レスポンシブ対応)も実装しています。

developer.mozilla.org

ライブラリの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の構造

コードはこちら(GitHubサイトへ)

コードの解説

以下、コードを3つのブロックに分けて解説します:

解説が開きます

  1. スキルセット表示のコードブロック:
<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属性の数値は各パーセンテージを表します。


  1. スキルに関する詳細情報のコードブロック:
<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>

このブロックは、各スキルに関する詳細情報を表示するためのコードです。各スキルにはアイコン、見出し、およびテキストが含まれており、それぞれのスキルに対する説明が提供されています。アイコンにはFont Awesomeを利用しています。

fontawesome.com


  1. 数値カウンターのコードブロック:
<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スタイル

コードはこちら(GitHubサイトへ)

コードの解説

以下、コード内表記によるCSSコードの解説です:

解説が開きます

  1. 棒グラフ・スキル詳細のコンテナ:
.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;
}

margin、paddingの指定順は上 -> 右 -> 下 -> 左です。


/* スキル詳細の見出しスタイル */
.special-heading {
    text-transform: capitalize; /* 文字列をキャピタライズ(最初の文字だけ大文字に) */
    letter-spacing: 1.5px;
    font-weight: 700;
}

text-transform属性は、大文字・小文字の表記を変更することができます。

  • capitalize: 最初の文字だけ大文字
  • uppercase: すべて大文字
  • lowercase: すべて小文字

developer.mozilla.org

/* スキル詳細のテキストスタイル */
p.special-text {
    color: #606060;
    line-height: 1.4em;
    margin: -1em 0 .46em;
    font-size: .85em;
    word-break: break-all; /* 英字を単語の途中で改行 */
}


  1. 数値カウンターのコンテナ:
#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フォント */
}

fonts.google.com

fonts.google.com


  1. メディアクエリ:
/* ウィンドウ幅が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

コードはこちら(GitHubサイトへ)

コードの解説

このJavaScriptコードは、jQueryを使用してスキルバー(skill-percent)および数値カウンター(counter-value)をアニメーション化するためのものです。3つのブロックに分け、コードを解説します:

解説が開きます

  1. Intersection Observerの設定:
$(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);
    • 各要素の"data-target"属性から目標値(アニメーションの最終値)を取得
  • const animateFn = $(this).hasClass('counter-value') ? animateCounter : animateWidth;
    • 要素が".counter-value"クラスを持っている場合は関数"animateCounter"を、そうでない場合は"animateWidth"を選択
  • new IntersectionObserver((entries) => { ... }, { threshold: .5 }).observe(this);
    • Intersection Observerを新しく作成して要素が画面内に表示されたかどうかを監視し、特定の閾値(50%)でアニメーションを開始
  • observer.unobserve(entry.target);
    • 発火後に、Intersection Observerの監視を外す

"parseInt"は文字列を整数に変換します。


  1. width変更アニメーション関数:
  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) { ... }
    • width変更アニメーション関数の定義。
  • let currentWidth = 0;
    • 現在のwidthを初期化。
  • const step = Math.ceil(target / 50);
    • 目標値までのステップを計算し、50ステップでアニメーションを完了するように設定。
  • const interval = setInterval(() => { ... }, 30);
    • 一定間隔(30ミリ秒)ごとにアニメーションを更新するためのインターバルを設定。
  • currentWidth += step;
    • 現在のwidthをステップ数だけ増加。
  • $(element).width(${currentWidth}%);
    • 要素のwidthを現在のwidthに更新。
  • if (currentWidth >= target) { ... }
    • 目標値に到達したら、インターバルをクリアして最終値を要素に設定。


  1. 数値カウンターアニメーション関数:
  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);
    • 目標値までのステップを計算し、50ステップでアニメーションを完了するように設定。
  • const interval = setInterval(() => { ... }, 30);
    • 一定間隔(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; /* 背景画像を要素内容に関して固定 */
/*前略*/
}

www.osaka-kyoiku.ac.jp

交差監視を継続する

JavaScriptコードの10行目、entry.target.unobserve(entry);をコードから外すと、スクロールで一旦要素が画面外に消えて再び画面に表示されるたび、アニメーションイベントが発火します。

つまり、カウントアップを0からやり直します。

entry.target.unobserve(entry);は、イベント発火後にIntersection Observerの監視を外す構文です。

おさらい

コードのまとめ

おわりに

以上、数値データに応じたカウントアップアニメーションと、Intersection Observerを使ったイベントトリガーの実装について解説しました。これらのテクニックを取り入れることで、ブログやサイトのビジュアル体験を向上させ、読者との魅力的なインタラクションを築くことができます。

今後のブログ運営において、より魅力的でユーザーフレンドリーなページを作り上げる一助となれば幸いです。

次回も引き続き、トップページのカスタマイズを紹介します(^^♪

これまでの記事

はてなブログ無料版: トップページを魅力的にカスタマイズする方法

基本設定、見出しの装飾、コンタクトへのリンクボタン
Animate.cssによるスライドアニメーションとホバー効果1
Animate.cssによるスライドアニメーションとホバー効果2
Flickityによるカルーセルスライダーの導入
Animate.cssを使ったフリップアニメーションとポートフォリオのディスプレイ
GSAPによるカルーセルの実装