もうあと少しで2023年も終わり、2024年が近づいてきたころ。

ついに自分でchrome拡張機能を作ることができました!

休みで時間ができて(やらなきゃいけないことはあるが)、やりたいことも見つかったので1日使って作りました!


それはImageViewerです!

別に公開もしていないローカルなchrome拡張機能に勝手に名前を付けただけですが。

pcで画像を見るとき、余計な文字があったりして見にくい時がありますよね。

あと画像を自動でゆっくり見たいのに、画像が変な配置のためにマウスの自動スクロールで見れないことも。

そんな時使えるのがこのImageViewerです。

webページから画像以外の要素を非表示にして画像を縦に並べなおし、自動スクロール機能で画像を自動で見ることができます。


まあ作ったといっても、ほとんどchatGPTが書いたんですけどね。

chromeの拡張機能を作ってみたい 教養ばななのブログ

2か月前にchrome拡張機能やjsの基礎的な部分を多少学びはしましたが、やっぱり知らない機能が多く、その使い方も0から調べるのは面倒くさい。

chatGPTに聞いたら8割方合っているコードを書いてくれて、エラーを吐いた部分を自分で調べて書き直した感じです。

本当に便利ですよね。

マニアックな機能を実装しようとしたり、おおざっぱな指示だと存在しない関数を使ってきたりはしますが、今回のような単純な機能なら大丈夫でした。


一応コードを残しておきます。

構成は以下の通りです。

manifest.json
{
    "name":"ImageViewer",
    "description":"webサイトを画像のみにし、自動スクロールすることができます。",
    "version":"1.0.0",
    "manifest_version":3,
    "action":{
        "default_icon":{
            "32":"images/icon32.png"
        },
        "default_popup":"popup.html"
    },
    "content_scripts":[
        {
            "matches":["<all_urls>"],
            "js":[
                "js/content.js",
                "js/jquery-3.6.0.js"
            ]
        }
    ]

}
popup.html
<html>
<head>
    <meta charset="UTF-8">
    <script src="js/jquery-3.6.0.js"></script>
    <script src="js/popup.js"></script>
    <link rel="stylesheet" href="css/popup.css">
</head>
<body>
    <h1>Menu</h1>
    <button id="showImage">画像のみ表示</button>
    <br>
    <input type="number" id="scrollSpeed" style="width:3em" value="1"></input>
    <button id="autoScroll">自動で下スクロール</button>
    <button id="stopScroll">stop</button>
</body>

</html>
js/popup.js
$(function(){
    // popup内のボタンがクリックされたときの処理
    $("#showImage").on("click", function(){
        // content scriptにメッセージを送信
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, {action: "showImageFunc"});
        });
    });

    $("#autoScroll").on("click", function(){
        const scrollSpeed = parseInt($('#scrollSpeed').val());
        // content scriptにメッセージを送信
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, {action: "autoScrollFunc", scrollSpeed:scrollSpeed});
        });
    });

    $("#stopScroll").on("click", function(){
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, {action: "autoScrollFunc", scrollSpeed:0});
        });
    });
});
js/content.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.action === "showImageFunc") {
      showImageFunc();
  }else if(request.action === "autoScrollFunc"){
      const scrollSpeed=request.scrollSpeed;
      autoScrollFunc(scrollSpeed);
  }
});

function showImageFunc() {
  var $imageContainer = $("<div id='imageContainer' style='display: flex; flex-direction: column;align-items: center;'></div>");

  // body直下の全ての子要素を非表示にする
  $("body > *:not(#imageContainer)").hide();
  const images = document.querySelectorAll('img');
  images.forEach((img) => {
      const imgElement = document.createElement('img');
      // 画像サイズを適切に調整するスタイルを追加
      imgElement.style.maxWidth = '50%';
      imgElement.style.height = 'auto';

      imgElement.src = img.src;
      $imageContainer.append(imgElement);
  });
  $("body").append($imageContainer);
}

var scrollInterval;
function autoScrollFunc(scrollSpeed){
  const scrollTime=20;
  if(scrollInterval)clearInterval(scrollInterval);
  scrollInterval = setInterval(autoScroll, scrollTime);

  function autoScroll(){
      const scrollTop = document.documentElement.scrollTop;
      const pageHeight = document.body.scrollHeight-window.innerHeight;
      if (scrollTop+10 >= pageHeight) {
          clearInterval(scrollInterval);
      }
      //console.log(scrollTop,pageHeight);
      window.scrollBy(0, scrollSpeed);
  }
}

js/jquery-3.6.0.js (jqueryのサイトからダウンロード)

css/popup.css
body{
    min-width:300px;
}


今回特に勉強になったのは、popup.jsからcontent.jsにメッセージを送って受け取る方法ですね。
前やったチュートリアルにもあったかもしれませんが、ただ写経しているだけじゃ頭に残りませんね。
popup.htmlに3つのボタンと1つの数字の入力を作って、ボタンが押されたときにpopup.jsからcontent.jsの関数を呼ぶとともに数字を渡す処理をしました。
ボタンを一つ作って渡し方をchatGPTに書いてもらったら、後の2つは同じようにできました。
自動スクロールの実装は少し時間がかかりました。
途中、何回もボタンを押すとスクロールが加速して止まらなくなってしまったんですよね。
setIntervalが重複したのが原因だったんですが、setIntervalのidを保存する変数をグローバル変数にしてもう一度呼び出されても値を保持するようにして解決しました。
コード書くのがうまい人はどうやって対処するんですかね。
ちなみにこれはchatGPTの3つ目くらいの案ですw

デザインがそっけなかったり、機能も少ないですが、自分にとって実用的な拡張機能を初めて作ることができてよかったです。