Chapter 04

機能実装編

gia
gia
2022.02.08に更新

ディレクトリ構成

実装してしまった後に知ったけど、ポップアップさせる html ファイルは popup.html, そのとき実行される js ファイルは popup.js とするみたいな慣習があるらしい。なので、それに揃えるなら、popup-dialog.html → popup.html, index.js → popup.js とした方がよさそう。

自分はもう実装してしまっているので、記事の中では、popup-dialog.html と index.js になっている。

src
 ├ icon/
  ├ index.js
 ├ manifest.json
 ├ popup-dialog.html
 └ style.css

拡張機能アイコンがクリックされたら画面端にポップアップでサムネイルを表示する機能の実装

ポップアップダイアログを表示する

ポップアップダイアログの html を記述

// popup-dialog.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>youtube thumbnails getter</title>
</head>
<body>
  <div>youtube thumbnails getter</div>
  <div>
    <div>thumbnail</div>
    <img
      src="https://cdn.pixabay.com/photo/2021/03/02/01/07/cyberpunk-6061251_960_720.jpg"
      alt="サムネイル"
      width="450px"
    >
  </div>
</body>
</html>

ポップアップ表示させるために manifest.json で html を指定する

// manifest.json

{
  // アプリ名称
  "name": "youtube thumbnails getter",
    // アプリバージョン
  "version": "0.0.1",
    // manifest.json のバージョン
	"manifest_version": 3,
  // アプリの詳細
  "description": "chrome extension to get youtube thumbnails",
    // タブの取得権限 
  "permissions": ["tabs"],
  "action": {
    // 拡張機能のアイコンをクリックした時にポップアップ表示される html ファイルを指定
    "default_popup": "popup-dialog.html"
  },
    // 作者名称
  "author": "gia_sorairo"
}
  • まだ拡張機能を chrome を追加していないなら拡張機能を追加
    • 拡張機能追加手順 → はじめての chrome 拡張機能開発 - hello world 編
  • すでに拡張機能を追加済みならコードの変更を反映させるために拡張機能を再読み込み

いいかんじ🎉

開いている youtube の動画のサムネイルを取得する機能の実装

いまはサムネイル部分の画像をダミーで表示させているので、開いているページによって動的にサムネイルが変化するようにしたい。

方針

開いているページの URL を取得する機能の実装

index.js を作成して、popup-dialog.html から読み込む

// popup-dialog.htlm

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>youtube thumbnails getter</title>
</head>
<body>
  <div>youtube thumbnails getter</div>
  <div>
    <div>thumbnail</div>
    <img
      src="https://cdn.pixabay.com/photo/2021/03/02/01/07/cyberpunk-6061251_960_720.jpg"
      alt="サムネイル"
      width="450px"
    >
  </div>
  // ここを追加
  <script src="./index.js"></script>
</body>
</html>

開いているページの URL を取得する

URL は chrome.tabs.query という関数で取得できる

// index.js

chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
  const { url } = tabs[0];
	console.log('url : ', url);
});

拡張機能を更新

youtube の動画ページに遷移

拡張機能のコンソールで開いているタブの URL が取得できているか確認してみる

  • 拡張機能のコンソールの開き方
    • 拡張機能のアイコンを右クリック
    • ポップアップを検証をクリック

ちゃんと URL が取得できているのをコンソールで確認できる

ちゃんと取得できてる💪

開いているページの URL から動画の ID を取得する

https://www.youtube.com/watch?v={ 動画id } の文字列から、動画 id の文字列だけを取り出す処理を実装する

// index.js

/** 動画の id を取得する処理 */
const getVideoId = (url) => {
  const { search } = new URL(url);
  const params = new URLSearchParams(search);
  if (params.has('v')) {
    return params.get('v');
  }
  return '';
}

chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
  const { url } = tabs[0];
  const videoId = getVideoId(url);

  console.log('url : ', url);
  console.log('videoId : ', videoId);
});

拡張機能を更新

youtube の動画ページを開く

拡張機能のコンソールを開く

ちゃんと動画の id を取得することが確認できた💪

サムネイルの URL を取得する機能の実装

サムネイルの URL の構造は https://img.youtube.com/vi/{ 動画の id }/{ 画像の type }.jpg で動画の id についてはもう取得できているので、画像の type を指定すればいい

画像の type には次の値が入る

  • default
    • 標準クオリティのサムネイル(120x90)
  • mqdefault
    • 中クオリティのサムネイル(320x180)
  • hqdefault
    • 高クオリティのサムネイル(480x360)
  • sddefault
    • HQ動画の標準クオリティのサムネイル(640x480)
    • 昔の動画だと取得できない場合がある
  • maxresdefault
    • FULLHDのクオリティのサムネイル(1920x1080)
    • 昔の動画だと取得できない場合がある
// index.js

/** 動画の id を取得する処理 */
const getVideoId = (url) => {
  const { search } = new URL(url);
  const params = new URLSearchParams(search);
  if (params.has('v')) {
    return params.get('v');
  }
  return '';
}

/**
 * サムネイルの url を作成する関数
 * 
 * default: 標準クオリティのサムネイル(120x90)
 * mqdefault: 中クオリティのサムネイル(320x180)
 * hqdefault: 高クオリティのサムネイル(480x360)
 * sddefault: HQ動画の標準クオリティのサムネイル(640x480)
 * maxresdefault: FULLHDのクオリティのサムネイル(1920x1080)
 */
const getThumbnailUrl = (videoId, thumbnailType) => {
  if (videoId
  && thumbnailType === 'default'
  || thumbnailType === 'mqdefault'
  || thumbnailType === 'hqdefault'
  || thumbnailType === 'sddefault'
  || thumbnailType === 'maxresdefault') {
    return `https://img.youtube.com/vi/${videoId}/${thumbnailType}.jpg`;
  }
  return '';
};

chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
  const { url } = tabs[0];
  const videoId = getVideoId(url);
  const thumbnailUrl = getThumbnailUrl(videoId, 'hqdefault');

  console.log('url : ', url);
  console.log('videoId : ', videoId);
  console.log('thumbnailUrl : ', thumbnailUrl);
});

拡張機能を更新

youtube の動画ページを開く

コンソールで確認

ちゃんと取得できてる🎉

コンソールに表示されているサムネイルの URL をクリックして遷移するときんちと画像が表示される🎉

取得したサムネイルの URL を DOM に反映させる機能の実装

popup-dialog.html が読み込まれた後に、img 要素を取得して、サムネイルの URL を img 要素の src 属性にセットしてやればよさそう。

実装

まず popup-dialog.html の img タグを取得できるようにするために、img タグに id を定義しておく

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>youtube thumbnails getter</title>
</head>
<body>
  <div>youtube thumbnails getter</div>
  <div>
    <div>thumbnail</div>
    <img
      id="youtube-thumbnail-getter-thumbnail-img"
      src="https://cdn.pixabay.com/photo/2021/03/02/01/07/cyberpunk-6061251_960_720.jpg"
      alt="サムネイル"
      width="450px"
    >
  </div>
  <script src="./index.js"></script>
</body>
</html>
// index.js

/** 動画の id を取得する処理 */
const getVideoId = (url) => {
  const { search } = new URL(url);
  const params = new URLSearchParams(search);
  if (params.has('v')) {
    return params.get('v');
  }
  return '';
}

/**
 * サムネイルの url を作成する関数
 * 
 * default: 標準クオリティのサムネイル(120x90)
 * mqdefault: 中クオリティのサムネイル(320x180)
 * hqdefault: 高クオリティのサムネイル(480x360)
 * sddefault: HQ動画の標準クオリティのサムネイル(640x480)
 * maxresdefault: FULLHDのクオリティのサムネイル(1920x1080)
 */
const getThumbnailUrl = (videoId, thumbnailType) => {
  if (videoId
  && thumbnailType === 'default'
  || thumbnailType === 'mqdefault'
  || thumbnailType === 'hqdefault'
  || thumbnailType === 'sddefault'
  || thumbnailType === 'maxresdefault') {
    return `https://img.youtube.com/vi/${videoId}/${thumbnailType}.jpg`;
  }
  return '';
};

/**
 * DOM に thumbnail を表示する関数
 * 
 * elementId 要素のid
 * thumbnailUrl サムネイルのURL
 */
const displayThumbnail = (elementId, thumbnailUrl) => {
  const imgElement = window.document.getElementById(elementId);
  if (imgElement) {
    imgElement.setAttribute('src', thumbnailUrl);
  }
}

/** didmount */
window.addEventListener('load', () => {
  chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
    const { url } = tabs[0];
    const videoId = getVideoId(url);
    const thumbnailUrl = getThumbnailUrl(videoId, 'hqdefault');
    displayThumbnail('youtube-thumbnail-getter-thumbnail-img', thumbnailUrl);
  
    console.log('url : ', url);
    console.log('videoId : ', videoId);
    console.log('thumbnailUrl : ', thumbnailUrl);
  });
});

拡張機能を更新

youtube の動画ページに移動

拡張機能のアイコンをクリックしてポップアップダイアログを表示

開いているページの動画のサムネイルが表示された🎉🎉🎉

最低限の機能実装完了🎉

おつかれさまでした🥤

参考資料