const cssEl = document.createElement('style') cssEl.innerHTML = ` html.cye-enabled { filter: contrast(0.96) brightness(0.9) invert(1); } html.cye-enabled img { filter: brightness(0.9) invert(1); } `; document.head.appendChild(cssEl); document.documentElement.classList.add('cye-enabled'); processing
很简单对不对。其实就是给 documentElement 添加一个样式类,相应的,也就是添加个反色滤镜(让亮色变成暗色)。
不想让img图片变成反色而导致肉眼无法识别,则可以再通过滤镜反转回来。
1.让是否开启“护眼模式”可控4.如何监听系统主题色调变化
(() => { const cssEl = document.createElement('style') cssEl.innerHTML = ` html.cye-enabled { background: #fff; /* 如果有自己的背景色,那么去掉这行 */ filter: contrast(0.96) brightness(0.9) invert(1); } html.cye-enabled img { filter: brightness(0.9) invert(1); } html.cye-enabled body { filter: none !important; /* 防止三方浏览器插件等重复的护眼样式生效 */ } `; document.head.appendChild(cssEl); // 堆代码 duidaima.com // document.documentElement.classList.add('cye-enabled'); /***** 一些JS设置逻辑 ****/ // 护眼模式 const getLV = (k) => JSON.parse(localStorage.getItem(k)); const setLV = (k, v) => localStorage.setItem(k, JSON.stringify(v)); let cyeMediaQueryList = null; try { cyeMediaQueryList = window.matchMedia('(prefers-color-scheme: dark)'); cyeMediaQueryList.addListener(setDocCyeByLS); // 通过浏览器API监听系统层面的主题模式配置变换 } catch(e) { console.warn('当前环境可能不支持 matchMedia'); } window.setCyeFilter = (enabled, contrast, brightness) => { setLV('cyeEnabled', enabled); // true 开启护眼模式,false 关闭护眼模式,2 跟随系统主题是否黑暗模式动态设定 setLV('cyeContrast', contrast); // 对比度,可微调视觉效果 setLV('cyeBrightness', brightness); // 亮度,可微调视觉效果 // 护眼模式为“开启”或“跟随系统”且系统是开启的 const isOpen = enabled === true || (enabled == 2 && cyeMediaQueryList && cyeMediaQueryList.matches); const { classList } = document.documentElement || {}; classList && classList[isOpen ? 'add' : 'remove']('cye-enabled'); if (!isOpen) return; const sss = document.styleSheets; if (!sss) return; let csss = null; for (let i = 0; i < sss.length; i++) { const cssi = sss[i]; if (cssi && cssi.ownerNode && cssi.ownerNode.id == 'ghdef') { csss = cssi; break; } } if (!csss) return; const ruls = csss.rules; if (!ruls) return; let clsObj = null; for (let j = 0; j < ruls.length; j++) { const rulj = ruls[j]; if (rulj && rulj.selectorText === 'html.cye-enabled') { clsObj = rulj; break; } } if (!clsObj) return; clsObj.style.filter = 'contrast(' + contrast + ') brightness(' + brightness + ') invert(1)'; return true; }; // 根据本地存储,判断是否开启护眼模式 function setDocCyeByLS() { setCyeFilter( getLV('cyeEnabled'), getLV('cyeContrast') || 0.96, getLV('cyeBrightness') || 0.9 ); }; setDocCyeByLS(); })()