前言

近日长时间上网,眼睛负荷甚大,故想到了要略微调整以下显示器的亮度,但是不同网页的风格不一样,直接调整显示器的亮度不太妥当,于是便有了开发一个脚本专门来做这件事的想法。

说干就干

首先,调整亮度这件事,主要是依赖于CSS,那么通过CSS来调整亮度有几种方法呢?

在下才疏学浅,大概知道四种写法方法

  1. filter:brightness(0.8)
  2. opacity:0.8
  3. 遮罩层 rgba(0,0,0,0.2)
  4. 遮罩层 opacity:0.8

然后就是实践环节了,针对要对整个网页亮度进行调整这种需求

  1. filter不能胜任,filterbackground等属性存在一些影响,会遗留一些颜色不被调整
  2. opacity并非一个正确的方法,淡化以后不能保证背景是黑色的
  3. 遮罩层 rgba倒是一个不错的想法
  4. 遮罩层 opacityrgba的表现基本一致,调整后的像素色值完全一致,姑且可以认为是完全相同的

那么最终我们所需的CSS基本如下所示:

body::after{
    content:"";
    display:block;
    background-color:rgba(0,0,0,0.2);

    position:fixed;
    left:0;
    top:0;
    z-index:1000000;
    width:100%;
    height:100%;
    pointer-events: none;
}

动手编码

为了兼容大部分的网页,因此不能随意引入Jquery等库,不过使用原生的document.querySelector()也不错

前文我们也说了,调整亮度不只是要调整整体的亮度,还需要针对特定网页
因此需要用到一些跨页面的技术,这个没什么好说的,Tampermonkey本身提供了一些GM函数,允许做一些特殊的使用,比如基于浏览器上下文来存储数据。
那么首先,我们需封装一个gm对象,通过这个对象来存取配置数据。

    const Default_config={
        globalBrightness: 0.9,
        SingleConfigMap:{
            /* {
                    [window.location.host] : 0.9,
            }*/
        }
    }
        let gm = new class{
        constructor(){
            this.key = "mscststs-brightness";
            this.init();
        }
        init(){
            GM_registerMenuCommand(wordsMap.MenuCmd,()=>{
                eve.emit("Cmd-OpenMenu");
            });
            GM_addValueChangeListener(this.key,(name, old_value, new_value, remote)=>{
                eve.emit("SettingUpdated",new_value);
            });
        }
        getNowBrightness(){
            let config = this.getConfig();
            return config.SingleConfigMap[window.location.host] || config.globalBrightness;
        }
        getConfig(){
            //读取配置文件
            return GM_getValue(this.key,Default_config);
        }
        setConfig(value){
            GM_setValue(this.key,value);
        }
        setGlobalBrightness(value){
            let config = this.getConfig();
            config.globalBrightness = value;
            this.setConfig(config);
        }
        setHostBrightness(value,host = window.location.host){
            let config = this.getConfig();
            config.SingleConfigMap[host] = value;
            this.setConfig(config);
        }
    }();

通过这个gm模块我们就可以访问我们的配置了,在脚本初始化的时候只需要调用gm.getNowBrightness()即可拿到当前页面的亮度。

当然,如果当前页面使用的是默认亮度,而默认亮度又被其他页面修改了,当前页面就需要通过GM_addValueChangeListener()设置值被修改之后的回调

在这里面,我使用了eve,这个小型的EventBus库由我之前开发,正好用在这里,相关的代码:eve

那么接下来的事情就比较简单了,我们还需要一个设置页面,这个页面需要通过某些操作来打开,我这里使用的是GM_registerMenuCommand()来在Tampermonkey中注册一个菜单项。

当然,鼠标找到这个菜单项比较复杂,因此我也引入了一个快捷键:ctrl+鼠标左键双击

    body.addEventListener("dblclick",(e)=>{
        if(e.ctrlKey){
            eve.emit("Cmd-OpenMenu")
        }
    })

最后优化

为了保证body的内容完整,我还做了以下的一些优化

  1. 将style的注入方式改成prepend

    function Init(){
        if(CurrentBrightness && CurrentBrightness == gm.getNowBrightness()){
            //默认亮度未改变
        }else{
            CurrentBrightness = gm.getNowBrightness();
        }
        let div = document.querySelector("#helper_BrightnessCover");
        if(!div){
            div=document.createElement("div");
            div.id = "helper_BrightnessCover";
            body.prepend(div);
        }
        div.innerHTML = `
    <style>
    body::after{
    content:"";
    display:block;
    background-color:#000;
    opacity:`+(1-CurrentBrightness)+`;
    
    position:fixed;
    left:0;
    top:0;
    z-index:999999;
    width:100%;
    height:100%;
    pointer-events: none;
    }
    </style>
        `;
    }
  2. 将rgba更改为opacity。
    根据我的观察,rgba在网页加载卡顿的时候,会出现分块渲染的问题,在鼠标移动的时候会有大量的闪烁,这个问题目前还非常难以复现,疑似是Chrome的内核渲染问题,但是据说修改为Opacity可以解决该问题,遂修改之
  3. 亮度设置的注入方式,设置选项一定不是在页面加载以后就注入的,这会影响页面的结构,应当是接收到打开菜单事件同时,创建div节点并且挂载到DOM上,然后为菜单添加一些事件绑定来实时更新当前页面的亮度之类的都是一些没营养的代码,可以回头慢慢看。

结语

在开发这个脚本的过程中也遇到了很多难以解决的问题,比如ctrl+i无法绑定的问题,一开始我尝试使用ctrl+i作为唤出菜单的快捷键,遇到了一些问题,在上一篇中提到了一下。

在脚本开发之前和开发之后,我都曾在英语分类检索了一下,未找到类似的脚本,但是Chrome应用市场上倒是有不少功能近似的项目(实际上只需要作为一个脚本就足以实现功能了)

为了造福国外观众,特地根据浏览器语言,为脚本设置了两个语言的自动切换

    function isCN(){
        let lang = navigator.language||navigator.userLanguage;//常规浏览器语言和IE浏览器
        if(lang.indexOf('zh')>=0){
            return true;
        }else{
            return false;
        }
    }
    
    const CN_wordsMap = {
        MenuCmd:"打开亮度调整菜单",
        settingsTitle:"亮度调整",
        setAsDefault:"设为默认亮度",
        closeSettingWindow:"关闭设置窗口",
        DeafultSetText:"网页默认亮度已被设置为",
    }
    const EN_wordsMap = {
        MenuCmd:"Brightness adjustment menu",
        settingsTitle:"Brightness adjustment",
        setAsDefault:"Set As Default Brightness",
        closeSettingWindow:"Close the settings window",
        DeafultSetText:"The default brightness has been set to "
    }
    
    const wordsMap = isCN()?CN_wordsMap:EN_wordsMap;

然后顺便用Google翻译把使用说明翻译了一份,添加到英语语种下(还好GreasyFork原生支持多语言)

网页亮度调整脚本地址