WordPressフルサイト編集機能の活用例(季節を演出)

WordPressブロックテーマで紅葉が舞う演出を実装します
*(注意)ウェブページの読み込み時間は遅くなってしまいます

目次
  1. はじめに
  2. 実装の手順
  3. コードとカスタマイズについて

はじめに

「ブロックテーマ」で利用可能な「フルサイト編集機能」は、ウェブサイトのヘッダーやフッター、サイドバーなど、従来のテーマでは制限されていた部分にも簡単に手を加えることができます
この機能により、管理画面のエディターを使用して、これらのエリアを直感的にカスタマイズできます

HTMLブロックは、ウェブページ上の任意の場所にコードを追加することができるので、今回は通常ほとんどのテンプレートで使用される「ヘッダーテンプレートパーツ」にコードを追加しました

ちなみに、この紅葉のビジュアルはSVGのパスを利用しています。このコード内のパスの部分を変更することで、季節やテーマに合わせた様々な形状、例えば桜の花びらなどに応用することが可能です

また、ユーザーがコンテンツに集中できるように、ページをスクロールすると紅葉の舞いが消え、ページの一番上まで戻ると再び表示されるように実装しました

実装の手順

  1. WordPressのダッシュボードにログイン
  2. 左側のサイドバーから「外観」⇨「エディター」を選択
  3. 「ヘッダーテンプレートパーツ」の一番下に「HTMLブロック」を追加します

コードをコピーしてHTMLブロックに貼り付けて下さい

コーピー用のコード

<div id="leaves"></div>  
<div class="target-class"></div> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.8.0/p5.min.js"></script>
<script defer>
  const target = document.querySelector('.target-class');
  const callback = function(entries, observer) { 
    entries.forEach(entry => {
      if (!entry.isIntersecting) {
        document.body.classList.add('hidden-class');
      } else {
        document.body.classList.remove('hidden-class');
      }
    });
  };
  const observer = new IntersectionObserver(callback);
  observer.observe(target);
  
 const svgPath=`d="
  M 29.06 32.88
  L 31.03 30.96
  L 33.13 26.74
  L 33.35 26.23
  L 33.59 25.87
  L 33.97 25.64
  L 37.15 23.55
  L 40.18 21.38
  L 40.74 21.20
  L 41.24 21.25
  L 43.03 21.73
  L 43.60 21.73
  L 49.95 19.89
  L 50.94 20.60
  L 50.92 20.79
  L 50.31 22.97
  L 49.41 26.68
  L 49.64 29.13
  L 49.74 29.57
  L 49.65 30.06
  L 48.78 31.89
  L 45.30 36.07
  L 43.29 38.17
  L 40.51 39.84
  L 38.91 40.17
  L 33.80 41.45
  L 31.11 43.08
  L 30.96 43.39
  L 31.29 43.34
  L 35.61 41.99
  L 38.90 42.09
  L 39.67 42.34
  L 40.02 42.46
  L 43.07 42.22
  L 45.90 42.02
  L 47.84 43.77
  L 48.63 44.17
  L 52.93 43.83
  L 53.58 44.09
  L 53.76 44.77
  L 53.68 44.99
  L 49.62 50.39
  L 44.66 53.58
  L 40.07 54.48
  L 39.65 54.63
  L 39.50 55.07
  L 39.58 55.72
  L 39.78 56.20
  L 39.86 56.60
  L 39.55 56.88
  L 39.20 57.00
  L 37.76 56.96
  L 31.61 55.25
  L 23.82 52.95
  L 17.99 52.33
  L 16.88 52.75
  L 16.21 53.72
  L 15.05 57.48
  L 14.48 58.19
  L 13.58 58.31
  L 13.21 58.22
  L 12.47 57.73
  L 12.62 56.86
  L 18.96 47.78
  L 26.68 40.45
  L 26.82 40.23
  L 26.77 40.09
  L 26.76 40.08
  L 26.61 39.97
  L 26.42 40.02
  L 17.65 47.11
  L 15.66 49.12
  L 15.60 49.16
  L 15.41 48.99
  L 15.84 43.73
  L 15.05 39.35
  L 14.28 36.21
  L 14.18 33.45
  L 14.68 31.05
  L 15.92 28.96
  L 16.30 28.71
  L 16.77 28.74
  L 17.46 28.98
  L 17.97 28.99
  L 18.25 28.57
  L 18.56 26.86
  L 18.98 24.85
  L 20.23 22.26
  L 22.03 19.61
  L 22.39 19.29
  L 22.84 19.15
  L 24.73 18.47
  L 27.15 16.77
  L 29.89 14.87
  L 29.96 14.84
  L 30.84 14.84
  L 31.44 15.48
  L 32.23 20.50
  L 31.15 25.02
  L 31.15 26.09
  L 31.03 28.94
  L 28.98 32.77
  L 28.92 32.91
  L 29.06 32.88
  Z"`   
 const drawSVGPath = (p5, pathData) => {
  const commands = pathData.match(/[a-df-zA-DF-Z][\d.,\s-]*/g);
  p5.beginShape();
  for (let command of commands) {
    const [cmd, ...params] = command.split(/[ ,]/).filter(Boolean);
    const args = params.map(Number);
    if (cmd === "M") {
      p5.vertex(...args);
    }
    else if (cmd === "C") {
      p5.bezierVertex(args[0], args[1], args[2], args[3], args[4], args[5]);
    }
    else if (cmd === "Q") {
      const [x1, y1, x2, y2] = args;
      const cp1x = x1 + (1 / 3) * (x2 - x1);
      const cp1y = y1 + (1 / 3) * (y2 - y1);
      const cp2x = x1 + (2 / 3) * (x2 - x1);
      const cp2y = y1 + (2 / 3) * (y2 - y1);
      p5.bezierVertex(cp1x, cp1y, cp2x, cp2y, x2, y2);
    }
    else if (cmd === "L") {
      p5.vertex(...args);
    }
    else if (cmd === "Z" || cmd === "z") {
      p5.endShape(p5.CLOSE);
    }
  }
}  

  const leaves = (p) => {
      let petals = [];
      const NUM = p.windowWidth > 600 ? 80 : 30;
      class Leaves {
        constructor() {
          this.hue = p.random(10, 50);
          this.alpha = p.random(0.6, 0.9);
          this.size = 50;
          this.xRadius = p.random(10, 20);
          this.base = p.random(p.width);
          this.vPos = p.createVector(this.base, p.random(p.height));
          this.vAngle = p.createVector(p.random(360), p.random(360));
          this.vVelocity = p.createVector(1, 4);
          this.scale = p.random(0.4, 0.8);
        }
        move() {
          this.vAngle.add(this.vVelocity);
          this.vPos.x = this.base + this.xRadius * p.cos(p.radians(this.vAngle.y));
          this.vPos.y += this.vVelocity.y;
          if (this.vPos.y > p.height + this.size) {
            this.vPos.y = -this.size;
          }
        }
        display() {
          p.fill(this.hue, 100, 95, this.alpha);
          p.push();
          p.translate(this.vPos.x, this.vPos.y);
          p.rotate(p.radians(this.vAngle.x));
          p.scale(this.scale);
          drawSVGPath(p, svgPath); 
          p.pop();
        }
      }
      p.setup = () => {
        p.createCanvas(p.windowWidth, p.windowHeight).parent('leaves')
        p.frameRate(30);
        p.colorMode(p.HSB);
        p.noStroke();
        for (let i = 0; i < NUM; i++) {
          petals.push(new Leaves());
        }
      };
      p.draw = () => {
        p.clear();
        petals.forEach((petal) => {
          petal.display();
          petal.move();
        });
      };
      p.windowResized = () => {
        p.resizeCanvas(p.windowWidth, p.windowHeight);
        petals = [];
        for (let i = 0; i < NUM; i++) {
           petals.push(new Leaves());
         }
      };
    };

    if (!document.body.classList.contains('hidden-class')) {
      new p5(leaves);
    }   
 </script>
 <style>
 body.hidden-class #leaves {
    display: none;
  }
 #leaves {
   position: fixed;
   top: 0;
   left: 0;  
   height: 100vh;
   width: 100vw;
   z-index:1000;
   pointer-events: none;
   }  
 </style>

コードとカスタマイズについて

このコードは、p5.jsライブラリを利用して、動的なエフェクトを実現しています

ポイントになるようなコードについてコメントを追加しているので、カスタマイズの参考にして下さい
*注意:コードは省略しているのでこちらのコピペは利用できません

<!-- 紅葉が表示される領域 -->
<div id="leaves"></div>  

<!-- スクロールに反応して紅葉を制御するための要素 -->
<div class="target-class"></div> 

<!-- p5.jsライブラリの読み込み -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.8.0/p5.min.js"></script>

<script>
  // .target-classがビューポート内にあるかどうかを監視するための設定
  const target = document.querySelector('.target-class');
  const callback = function(entries, observer) { 
    entries.forEach(entry => {
      if (!entry.isIntersecting) {
        // .target-classがビューポート外にある時にbodyタグにhidden-classを追加
        document.body.classList.add('hidden-class');
      } else {
        // .target-classがビューポート内にある時にhidden-classを削除
        document.body.classList.remove('hidden-class');
      }
    });
  };
  const observer = new IntersectionObserver(callback);
  observer.observe(target);

  // svgPathの定義(図形・紅葉の形) *パスの部分を変更はここで
  const svgPath = `省略...`;

  // SVGパスを描画する関数
  const drawSVGPath = (p5, pathData) => {
  //  省略...
}  

  // 図形(紅葉)の描画とアニメーションの設定  *別途
  const leaves = (p) => {
    // 省略...
  };

  // bodyタグにhidden-classクラスがない場合に紅葉アニメーションを起動
  if (!document.body.classList.contains('hidden-class')) {
    new p5(leaves);
  }   
</script>

<!-- 紅葉のスタイル設定 -->
<style>
  /* hidden-classがbodyタグにある時は紅葉を非表示にする */
  body.hidden-class #leaves {
    display: none;
  }
  /* 紅葉の表示領域のスタイル設定 */
  #leaves {
    position: fixed;
    top: 0;
    left: 0;  
    height: 100vh;   /* 画面の高さいっぱい */
    width: 100vw;     /* 画面の横幅いっぱい */
    z-index: 1000;  
    pointer-events: none;
  }  
</style>

図形(紅葉)の描画とアニメーションの設定
カスタマイズの参考に
const leaves = (p) => {// 省略…};

const leaves = (p) => {
  let petals = [];

  // 紅葉の数(ウィンドウの幅600pxより大きい場合80個、小さい場合30個)
  const NUM = p.windowWidth > 600 ? 80 : 30; 

  class Leaves {
    constructor() {
      // 紅葉の色の設定(色相0から360の範囲、透明度0から1の範囲)
      this.hue = p.random(10, 50); // 色相の範囲(紅葉の色)
      this.alpha = p.random(0.6, 0.9); // 透明度(明るさ)

      // 紅葉の動きの設定
      this.size = 50; //表示位置の調整用
      this.xRadius = p.random(10, 20); // 水平方向の動きの範囲
      this.base = p.random(p.width); 

      // 紅葉の位置と角度の初期化
      this.vPos = p.createVector(this.base, p.random(p.height));
      this.vAngle = p.createVector(p.random(360), p.random(360));
      this.vVelocity = p.createVector(1, 4); // 移動速度(水平、垂直)

      // 紅葉のスケール(サイズの変化)
      this.scale = p.random(0.4, 0.8);
    }

    // 紅葉の移動処理
    move() {// 省略...}
    // 紅葉の描画処理
    display() {// 省略...}
  }

  // p5.jsのセットアップ(初期化)
  p.setup = () => { // 省略... };

  // 描画処理
  p.draw = () => {// 省略...};

  // ウィンドウサイズ変更時の処理
  p.windowResized = () => {// 省略...};

パスの部分を変更する場合について
const svgPath = `省略...;`

SVGパスデータを取り込んで、p5.jsを使用してウェブページ上に描画します
使用している関数は M 、L、C、Q、Zなどのコマンドで構成されていますが、全てに対応しているわけではないので、できるだけシンプルなパスを使用して下さい

//桜の花びらの例 
//サイズや色を変更すれば使えると思います
const svgPath = `d="
  M 42.24 28.02
  L 42.55 27.97
  L 42.71 27.91
  L 42.82 27.78
  L 50.74 14.15
  L 51.35 13.70
  L 52.10 13.84
  L 52.10 13.84
  L 52.15 13.87
  L 56.41 17.85
  L 60.01 22.61
  L 63.06 28.15
  L 65.64 34.75
  L 67.55 41.93
  L 68.76 49.77
  L 69.15 57.57
  L 68.73 64.75
  L 67.77 69.89
  L 66.15 74.99
  L 60.92 85.59
  L 53.04 96.49
  L 43.31 106.54
  L 42.46 106.87
  L 41.60 106.55
  L 33.27 98.28
  L 26.30 89.46
  L 21.09 80.60
  L 17.61 71.72
  L 16.06 64.21
  L 15.59 56.09
  L 16.17 47.66
  L 17.81 39.26
  L 20.29 31.65
  L 23.69 24.60
  L 27.73 18.70
  L 32.57 13.75
  L 32.64 13.70
  L 33.40 13.55
  L 34.03 14.01
  L 42.05 27.93
  L 42.15 28.02
  L 42.24 28.02
  Z"`