3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Chrome 拡張開発入門】会社 HP のカーソルエフェクトをシンプルにしてみた 🪄

Last updated at Posted at 2025-04-02

はじめに

みなさん、弊社のホームページをご覧になったことはありますか?

かっこいいです 🌟

ただ、カーソルのパーティクルが人魂みたいで、寝る前に暗い部屋で見るとちょっと怖いです 👻

人魂.png

「じゃあ、見るのやめておこうかな...」と思ったあなた!ちょっと待って!✋

「ちょっと怖がりなあなたにお届けする弊社 HP」 ということで、カーソルのパーティクルを無効化する Chrome 拡張を真心込めて作りました 🔨(ただ Chrome 拡張を作りたかっただけです)

Edge でも動きます。

成果物 🏁

今回作った Chrome 拡張は必要最小限な構成です。

↓ ディレクトリ構成

swhp-chrome-extension/
├── disable-particle.js
└── manifest.json

↓ 設定ファイル

manifest.json
{
  "manifest_version": 3,
  "name": "swhp-chrome-extension",
  "version": "1.0",
  "description": "SW社ホームページでマウスカーソルに付与されたパーティクルを無効にする",
  "permissions": ["activeTab"],
  "content_scripts": [
    {
      "matches": ["https://www.skywill.jp/*"],
      "js": ["disable-particle.js"],
      "run_at": "document_start"
    }
  ]
}

↓ 実際に動かすプログラム(エントリーポイント)

disable-particle.js
document.addEventListener('DOMContentLoaded', () => {
  // ParticleJSは描画するためのコンテナをmyCanvasに追加している
  // myCanvasをDOMツリーから削除すればパーティクルを無効化できる
  const myCanvas = document.getElementById('myCanvas');
  if (myCanvas) {
    myCanvas.remove();
  }

  // パーティクルのために非表示にされていたカーソルを表示する
  document.body.style.cursor = 'default';

  const links = document.querySelectorAll('a');
  const pointer = document.getElementById('POINTER');

  // aタグにmouseenterしたらPOINTERを表示、mouseleaveしたら非表示にする
  // styleの各属性はオリジナルと同じものを設定する
  links.forEach((link) => {
    link.addEventListener('mouseenter', () => {
      pointer.style.visibility = 'inherit';
      pointer.style.opacity = '1';
      pointer.style.transform = 'translate(-50%, -50%) scale(1.5, 1.5)';
    });

    link.addEventListener('mouseleave', () => {
      pointer.style.visibility = 'hidden';
      pointer.style.opacity = '0';
      pointer.style.transform = 'translate(-50%, -50%) scale(1, 1)';
    });
  });

  let mouseX = 0;
  let mouseY = 0;

  // マウスカーソルの動きに合わせてPOINTERを追従する
  window.addEventListener('mousemove', (event) => {
    mouseX = event.clientX;
    mouseY = event.clientY;

    // POINTERが表示されているとき、マウスカーソルの位置に追従させる
    if (pointer.style.visibility === 'inherit') {
      pointer.style.left = `${mouseX}px`;
      pointer.style.top = `${mouseY + window.scrollY}px`;
    }
  });

  // スクロール時にもPOINTERを追従する
  window.addEventListener('scroll', () => {
    if (pointer.style.visibility === 'inherit') {
      pointer.style.top = `${mouseY + window.scrollY}px`;
    }
  });
});

拡張機能の読み込み方 🧑‍🏫

拡張機能を作ったら...

デベロッパーモードを ON にして、

デベロッパーモード.png

ここのボタンをポチッと押すと、Mac なら Finder、Windows ならエクスプローラーが立ち上がって自作の拡張機能を読み込めます。

読み込む.png

インポートするのは、以下の swhp-chrome-extension フォルダです。

↓ ディレクトリ構成(再掲)

swhp-chrome-extension/
├── disable-particle.js
└── manifest.json

開発を進めて再読み込みしたいときは、ここのリロードボタンを押せば反映してくれます。
対象ページ(弊社 HP)のリロードも忘れずに!

更新する.png

ポイント 💡

この拡張機能でやっていることは大きく以下の 2 つです。

  1. マウスカーソルのパーティクルを無効化する
  2. リンクをホバーした時のポインタアニメーションを復活させる

1. マウスカーソルのパーティクルを無効化する 🙅

開発者ツールの Sources タブを探検してみたら、パーティクルには ParticleJS というライブラリが使われていることがわかりました。

スクリーンショット 2025-04-01 23.08.51.png

ParticleJS では canvas 要素を用意し、そこにパーティクルを描画するためのコンテナを追加しています。(公式の実装例)
そして、内部的に window にイベントリスナーを登録しているようです。

実際、canvas くんがいました!

canvas.png

本来であれば、mousemove イベントにバインドされたリスナーを取得して removeEventListener したいところですが、拡張機能側からイベントリスナーにアクセスするのは難しいです 😵‍💫
それならいっそ canvas を消しちゃえ!💥

disable-particle.js
// ParticleJSは描画するためのコンテナをmyCanvasに追加している
// myCanvasをDOMツリーから削除すればパーティクルを無効化できる
const myCanvas = document.getElementById('myCanvas');
if (myCanvas) {
  myCanvas.remove();
}

これでパーティクルがいなくなります。ゴーストバスターズ!

いなくなったパーティクルの代わりに、マウスカーソルを復活させてあげましょう。

disable-particle.js
// パーティクルのために非表示にされていたカーソルを表示する
document.body.style.cursor = 'default';

2. リンクをホバーしたときのポインタアニメーションを復活させる 🏋️

無事 ParticleJS の活躍の舞台(canvas)を破壊したわけですが、同時にポインタアニメーションも壊れます 🤯

  • リンクにホバーしたときのポインタアニメーションが効かなくなる
  • ポインタがカーソルの動きに追従しなくなる

仕方がないので、これらの処理を自分で書きます ✍️

リンクにホバーしたときのポインタアニメーション

開発者ツールの Elements タブを観察すると、mouseenter したときと mouseleave したときで、visibility, opacity, transform の値が変わるとわかります。

mouseenter したとき

ポインタアニメーションスタイル.png

mouseleave したとき

パーティクルスタイル.png

それぞれのイベントが配信されたとき、3 つの属性に適切な値を設定してあげることでアニメーションが復活します 💪

disable-particle.js
const links = document.querySelectorAll('a');
const pointer = document.getElementById('POINTER');

// aタグにmouseenterしたらPOINTERを表示、mouseleaveしたら非表示にする
// styleの各属性はオリジナルと同じものを設定する
links.forEach((link) => {
  link.addEventListener('mouseenter', () => {
    pointer.style.visibility = 'inherit';
    pointer.style.opacity = '1';
    pointer.style.transform = 'translate(-50%, -50%) scale(1.5, 1.5)';
  });

  link.addEventListener('mouseleave', () => {
    pointer.style.visibility = 'hidden';
    pointer.style.opacity = '0';
    pointer.style.transform = 'translate(-50%, -50%) scale(1, 1)';
  });
});

ポインタをカーソルの動きに追従させる

mousemove イベント、scroll イベントが配信されたとき、ポインタが表示されていたら、マウスカーソルの座標に移動させます。

disable-particle.js
let mouseX = 0;
let mouseY = 0;

// マウスカーソルの動きに合わせてPOINTERを追従する
window.addEventListener('mousemove', (event) => {
  mouseX = event.clientX;
  mouseY = event.clientY;

  // POINTERが表示されているとき、マウスカーソルの位置に追従させる
  if (pointer.style.visibility === 'inherit') {
    pointer.style.left = `${mouseX}px`;
    pointer.style.top = `${mouseY + window.scrollY}px`;
  }
});

// スクロール時にもPOINTERを追従する
window.addEventListener('scroll', () => {
  if (pointer.style.visibility === 'inherit') {
    pointer.style.top = `${mouseY + window.scrollY}px`;
  }
});

動作確認

パーティクルが消えて、マウスカーソルが表示されているし、

マウスカーソル.png

リンクにホバーすると、ポインタが表示される!

ポインタアニメーション.png

いい感じ!!!!!

おわりに

Chrome 拡張は、サクッと作れるのがよいですね!
「これ、もうちょっとこうだったらいいのに!」と思ったとき、気軽に作ってみるのもアリかも 🤔

楽しい拡張機能ライフを!🚀

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?