前端仔尝试开发的浏览器插件(页面亮度调节)

前端仔尝试开发的浏览器插件(页面亮度调节)

浏览器亮度调理

支撑调整浏览器中某个页面的亮度;而不需求调整整块屏幕的亮度。

前端仔测验开发的浏览器插件(页面亮度调理)

gif图中的是自己开发的 塔防小游戏 感兴趣能够玩玩,要是喜爱能够给个star Github

前言

作为一名小前端,想着浏览器插件技能要求也只需:html,css,js,就萌生了开发一个简略插件试试水的想法,权当丰厚技能了。这是第一次测验开发的浏览器插件比较粗陋,轻喷。

运用场景

  1. 当你觉得某个页面太亮的时分,有些时分的页面是一片白色等浅色布景的,会让你觉得很刺眼,如果运用暗色主题的插件,又会影响到页面其他地方的款式。

  2. 当你的页面在做正经作业(摸鱼)时,你能够把这个标签页提出来,敞开该插件,把亮度调低,这样就能让他人从其他视点难以看到你该页面中的内容。(屏幕其他地方还是亮的,一般人的眼睛都会被亮的地方所招引)

插件运用方法

下载该文件的压缩包,地址点这儿

前端仔测验开发的浏览器插件(页面亮度调理)

然后翻开 办理扩展插件,或者在浏览器地址中直接输入: chrome://extensions/

前端仔测验开发的浏览器插件(页面亮度调理)

选择解压后的压缩包的文件夹就能够直接运用了。

前端仔测验开发的浏览器插件(页面亮度调理)

插件开发流程

思路

在浏览器页面中设置 fixed 定位一个盒子上去,运用 boxShadow 作为遮罩层,调理 rgab(0,0,0,opacity) 中的透明度作为调理亮度。

结构

写一个插件结构其实很简略(没触摸前我还以为会很麻烦),要是没什么特别需求,其实只需求一个 js 文件和一个 manifest.json 的配置文件就能够了。

前端仔测验开发的浏览器插件(页面亮度调理)

配置 json

创建 manifest.json 文件

{
  "name": "browser-mask",
  "description": "Provide a mask layer for the browser.",
  "version": "1.0.1",
  "manifest_version": 3,
  "action": {
    "default_title": "浏览器遮罩层",
    "default_popup": "src/popup.html",
    "default_icon": "images/icon.png"
  },
  "icons": {
    "16": "images/icon.png"
  },
  "permissions": ["storage", "scripting", "activeTab"]
}

最上面三个特点跟 package.json 相同没什么好说的。

  • manifest_version: 这个是 manifest 的版别,2版别的不支撑上架了Chrome了。

  • action.default_title: 配置右上角图标标题(鼠标hover就能看到)。

  • action.default_popup: 点击右上角图标翻开的那个弹出层页面。

  • action.default_icon: 右上角图标。

  • icons: 这个是办理扩展插件页面中的图标。浏览器地址输入: chrome://extensions/ 直接进入

  • permissions: 敞开一些 api 的权限。分别是:storage 敞开缓存api;scripting 是敞开往页面注入 script 代码的api;activeTab 用于敞开标签页api。

popup.js (首要代码)

这是该插件的首要款式了。

前端仔测验开发的浏览器插件(页面亮度调理)

html css 没什么好说的,跟正常写一个网页那样。

js 也和写原生大体相同,仅仅需求注意一些 api 的运用,以及注意变量的效果域等。

插件开端履行

首要查看内存中是否有 opacity 字段,没有就赋值,有的话就给进展条和进展文本赋值。至于这儿为什么要用 storage 除了需求缓存之前的值外,还有其他原因,openMask 中会介绍到。

/** 初始的透明度 */
const INIT_OPACITY = 40;
const progress = document.querySelector('#progress')
const progressValue = document.querySelector('#progressValue')
// ... 其他的一些缓存值,不多叙述了
chrome.storage.sync.get('opacity', ({ opacity: opa }) => {
  if(!opa) {
    chrome.storage.sync.set({ opacity: INIT_OPACITY })
  } else {
    progress.value = opa
    progressValue.textContent = opa
  }
});

翻开遮罩层

点击翻开按钮,获取到的 tab 就是当时浏览器激活选中的标签页面,然后给这个标签页履行 executeOpenMask 注入履行函数 。

// #open 是翻开按钮的 id 
const openBtn = document.querySelector('#openBtn')
openBtn.addEventListener('click', async () => {
  const tabId = await getTabId();
  const isOpen = await getStorageSync('isOpen')
  if(!isOpen) { // 翻开mask
    executeOpenMask(tabId)
  } else { // 封闭mask
    chrome.scripting.executeScript({
      target: { tabId },
      func: closeMask,
    });
  }
  openBtn.textContent = isOpen ? '翻开' : '封闭'
  chrome.storage.sync.set({isOpen: !isOpen})
})
/** 获取当时点击的tabId */
async function getTabId() {
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  return tab.id
}
/** 获取storage */
function getStorageSync(key) {
  return new Promise((resolve) => {
    chrome.storage.sync.get(key, (item) => {
      resolve(item[key])
    })
  })
}

executeOpenMask

获取 maskInfo(用于存放一些遮罩层的信息,用于缓存而已),往当时标签页中注入 openMask 履行函数,已经传递 maskInfo 参数;再注入 mask.css 的css代码,感兴趣能够直接看源码,就不占文章篇幅了。

/** 注入翻开 mask 的代码 */
async function executeOpenMask(tabId) {
  const maskInfo = await getStorageSync('maskInfo')
  // 获取当时激活的tab的id,注入履行 func
  chrome.scripting.executeScript({
    target: { tabId }, 
    // 这儿是传递给 func 的参数
    args: [maskInfo], 
    func: openMask
  });
  chrome.scripting.insertCSS({
    target: { tabId },
    // 这儿的途径要按项目根目录开端
    files: ['src/mask.css'] 
  });
  if(maskInfo.isMove) {
    setTimeout(() => {
      chrome.scripting.executeScript({
        target: { tabId },
        args: [maskInfo],
        func: openMaskMove,
      });
    }, 10);
  }
}

openMask

翻开遮罩层,这儿需求从 storage 中读取 opacity;css 中通过 var(--opacity) 就可获取到值。

/* mask.css */
#maskWrap {
  box-shadow: 50vmax 50vmax 0 50vmax rgba(0, 0, 0, var(--opacity, 0.4));
}
function openMask(maskInfo) {
  chrome.storage.sync.get('opacity', ({ opacity }) => {
    const maskWrap = document.createElement('div')
    maskWrap.setAttribute('id', 'maskWrap')
    maskWrap.style.transform = `translate(${maskInfo.x}px, ${maskInfo.y}px)`
    // 给 maskWrap 增加变量
    maskWrap.style.setProperty('--size', 22)
    maskWrap.style.setProperty('--opacity', opacity / 100)
    document.body.appendChild(maskWrap)
  });
}

由于 openMask 是注入的一个函数,存在效果域的问题,是无法读取到外部界说的 opacity。不要问我怎么知道的,由于我刚开端就是这样写的…

// 这种方法是不正确的,无法运用
let opacity = 40;
function openMask() {
  const maskWrap = document.createElement('div')
  maskWrap.style.setProperty('--opacity', opacity / 100)
  // ....
}

增(减)亮度

增加亮度就是监听增加按钮的点击事情,点击时获取 storage,然后调用 changeOpacity 函数(用来设值和改动界面ui的)即可。

document.querySelector('.add').addEventListener('click', () => {
  chrome.storage.sync.get('opacity', ({ opacity }) => {
    changeOpacity(opacity + 10)
  });
})

首要是修改当时 popupdom 的进展条和进展条的值,然后新的设置 storage

接着就是修改标签页中的亮度(遮罩层透明度),注入一个触发的函数。

function changeOpacity(newOpacity) {
  let opacity = Math.min(Math.max(Math.round(newOpacity), 0), 100);
  progress.value = opacity
  progressValue.textContent = opacity
  chrome.storage.sync.set({ opacity })
  chrome.tabs.query({ active: true, currentWindow: true }).then(([tab]) => {
    chrome.scripting.executeScript({
      target: { tabId: tab.id },
      args: [opacity],
      func: injectChangeOpacity,
    });
  })
}
function injectChangeOpacity(opacity) {
  const maskDiv = document.querySelector('#mask')
  if(maskDiv) {
    maskDiv.style.boxShadow = `0 0 0 100vmax rgba(0, 0, 0, ${opacity / 100})`
  }
}

拖动进展条,遮罩层移动等操作就根本仅仅js的知识了,只需求加些拖动等的事情监听就好了,跟浏览器插件知识关系不大,这儿就不一一叙述了,想知道的话能够看源码

至此这个粗陋的插件,大体内容就这些了。

待处理的问题

  1. 当翻开遮罩后,改写页面不会重新翻开遮罩,需求点击封闭再重新翻开,(记载每个页面对应遮罩是否翻开)。

  2. 移动遮罩层时需求完善宽高问题(目前选用100vmax(浏览器可见区域宽高的最大值))。

  3. 遮罩层需求支撑缩放,可控制来遮罩页面固定区域。

由于本人刚触摸,不太熟悉浏览器插件的技能,第1点完成起来有点困难;

关于2,3点,由所以选用 box-shadow 来遮罩页面的,宽高的不同调整 box-shadow 暂时没什么思路。