iT邦幫忙

2021 iThome 鐵人賽

DAY 5
1
自我挑戰組

只不過是想強迫自己定時喝個水有必要那麼麻煩嗎之我想寫一個 Chrome Extension 強迫我喝水系列 第 5

[拯救上班族的 Chrome 擴充套件] 你渴望貓咪嗎?那就把貓咪插入到每個頁面吧!

Hi 大家好
經過之前兩篇

想必你已經知道該如何將訊息傳遞給彼此,
還有擴充套件之間的三角關係。

今天就來實作一個簡單的功能關於把圖片插入到每個頁面和插入的圖片刪除的功能,

先看成果

來實作吧

實作 Chrome extension 超簡單 UI

以下是我們需要的

  • 一個插入圖片的按鈕
  • 一個移除插入圖片按鈕
<!DOCTYPE html>
<html>
  <head>
    <!-- <link rel="stylesheet" href="button.css"> -->
  </head>
  <body>
    <button id="injectImg">Inject</button>
    <button id="removeImg">Remove</button>
    <script src="js/popup.js"></script>
  </body>
</html>

實作一個用來跟 background.js 溝通的 popup.js

  • 告訴 background 說要插入圖片囉
  • 告訴 background 說要移除圖片囉
const injectImg = document.getElementById('injectImg');
const removeImg = document.getElementById('removeImg');

injectImg.addEventListener('click', () => {
  chrome.runtime.sendMessage({ event: 'injectImg' });
});

removeImg.addEventListener('click', () => {
  chrome.runtime.sendMessage({ event: 'removeImg' });
});

實作一個 background.js

這邊要做的是去告訴所有頁面(content script)說,插入圖片或是移除圖片。

  • 發送訊息給所有 tab 說要插入圖片
  • 發送訊息給所有 tab 說要移除插入的圖片
async function getAllTabs() {
  const queryOptions = { };
  const tabs = await chrome.tabs.query(queryOptions);
  return tabs;
}

async function sendMessageToAllTabs(actionObject) {
  const tabs = await getAllTabs();
  for (let i = 0; i < tabs.length; i += 1) {
    chrome.tabs.sendMessage(tabs[i].id, actionObject);
  }
}

chrome.runtime.onMessage.addListener(async (request, _sender, _sendResponse) => {
  try {
    switch (request.event) { // 收到訊息解析要做的事情是什麼
      case 'injectImg':
        await sendMessageToAllTabs({ action: 'injectImg' });
        break;
      case 'removeImg':
        await sendMessageToAllTabs({ action: 'removeImg' });
        break;
      default:
        console.log('not match event')
    }
  } catch (e) {
    console.error(`error is :${e}`);
  }
});

實做一個 content script

  • 收到要插入圖片時操作 DOM 去新增和實作放大縮小的scirpt
  • 收到要刪除圖片時操作 DOM 去刪除該圖片
    const defaultImg = 'https://media.giphy.com/media/BzyTuYCmvSORqs1ABM/giphy.gif';
    
    function injectImg(imageURL = defaultImg) {
      const drinkPleaseDiv = document.createElement('div');
      document.body.appendChild(drinkPleaseDiv);
      drinkPleaseDiv.id = 'drinkPlease';
      drinkPleaseDiv.style = 'z-index:2147483647; position:fixed; width: 100%; height:100vh; top:0;';
      drinkPleaseDiv.insertAdjacentHTML('afterbegin', `<img src="${imageURL}" id="img" style="width: 100px;height: 100px; display: flex; max-width: 100%; align-items: center; margin:auto;">`);
    }
    
    function removeImg() { 
      const drinkDiv = document.getElementById('img');
      drinkDiv.remove();
    }
    
    // 放大和縮小圖片
    function zoomImg(increaseSize = 100, increaseSpeed = 100, MaxSize = 1300, MinSize = 100) {
      const img = document.getElementById('img');
      let i = increaseSize;
      return setInterval(() => {
        if (parseFloat(img.style.width) > MaxSize || parseFloat(img.style.height) > MaxSize) i *= -1;
        if (parseFloat(img.style.width) < MinSize || parseFloat(img.style.height) < MinSize) i *= -1;
        img.style.width = `${`${parseFloat(img.style.width) + (i)}`.toString()}px`;
        img.style.height = `${`${parseFloat(img.style.height) + (i)}`.toString()}px`;
      }, increaseSpeed);
    }
    
    chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
      switch (message.action) { // 解析收到訊息的動作
        case 'injectImg':
          injectImg();
          zoomImg();
          sendResponse('inject image success');
          break;
        case 'removeImg':
          removeImg();
          sendResponse('remove image success');
          break;
        default:
          sendResponse('no match');
      }
    });
    
    

定義 mainifest.json 相關設定, 權限和檔案位置

{
    "name": "No drinking no working",
    "description": "No drinking no working!",
    "version": "1.0",
    "manifest_version": 3,
    "background": {
      "service_worker": "js/background.js"
    },
    "permissions": [
      "tabs"
      ],
    "action": {
      "default_popup": "popup.html",
      "default_icon": "/images/drip.png"
    },
    "content_scripts": [
      {
        "matches": ["<all_urls>"], // 這邊需要所有頁面都受到我的擴充所用到
        "js": ["js/contentScript.js"]
      }
    ]   
}

以上是今天的簡單實作分享
你可能會有疑惑
如果新開的頁面不就要在插入一次?

對,所以明天可能會分享關於 local storage 的部分,當使用者打開任何頁面時,可以去存取狀態的並且做一些壞壞的事情。xDD

那我們明天見


上一篇
[拯救上班族的 Chrome 擴充套件] Chrome Extention 的訊息傳接球
下一篇
[拯救上班族的 Chrome 擴充套件] 當朋友問我說,為什麼我的頁面怎麼開都是貓咪,你有頭緒嗎? 我 __ __ 怎麼會知道。
系列文
只不過是想強迫自己定時喝個水有必要那麼麻煩嗎之我想寫一個 Chrome Extension 強迫我喝水6

尚未有邦友留言

立即登入留言