[拯救上班族的 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

那我们明天见


<<:  Unity与Photon的新手相遇旅途 | Day5-灯光介绍、粒子效果

>>:  [Day16] - 利用 direflow.io 将 React Component 转换成 Web Component

未来流通产业情报站,资料团队分工厘清

每一次的重要决策,都左右着後面的行为发展,非常棒的产业蓝图关键链 跨足零售产业,电商产业,物流产业,...

Day 06 - Snapshots

本篇重点 Snapshots 介绍与属性说明 VS Code 查看Function参数内容 Snap...

Day3 安装渗透测试用的作业系统- Kali Linux 和 Parrot OS

上图为常见的虚拟机软件 VirtualBox 与 VMWare Player 比较与常见渗透测试的...

那些被忽略但很好用的 Web API / FullScreen

一起来延伸视野,迎接更大的画面吧! 今天要介绍的 FullScreen API 会被忽略的原因可能...

【Day1】Introduction

About Me 嗨,大家好, 首先来个简单的自我介绍,我是Chilla。 目前是个还在学校蹲的小菜...