console
/**
* 黑暗模式检测器
*
* 与其他类似脚本不同,本脚本不只检测 `@media(prefer-color-scheme)`
* 同时检测注入样式表(大部分的黑暗模式扩展和某些浏览器的做法),浏览器默认
* 样式(例如 <meta name="color-scheme" /> 以及 自带“背景色/前景色”),
* 非正常渲染(QQ浏览器 / UC浏览器 / Chrome 的强制夜间模式)。
*
* 这些选项不会通过 `@media(prefer-color-scheme)` 体现出来,但是有
* 时会带来麻烦。
*
* 受检测原理所限,请尽量提前加载这个脚本,以使它工作。
*
*/
(function () {
var i;
// 初始化 CSS 测试锚点元素
var textarea = document.createElement("textarea");
var p = document.createElement("p");
var canvas = document.createElement("canvas");
var img = document.createElement("img");
var defaultStyle = {
position: "absolute",
padding: "0",
border: "0",
width: "0",
height: "0",
outline: "none"
}
for (i in defaultStyle) {
//textarea.style[i] = defaultStyle[i];
//p.style[i] = defaultStyle[i];
}
document.body.appendChild(textarea);
document.body.appendChild(p);
document.body.appendChild(canvas);
// 检测结果
var Result = {
"PREFER_COLOR_SCHEME_DARK": "prefer-color-scheme-dark",
"FORCE_COLOR": "force-color",
"SUGGEST_COLOR": "suggest-color",
"CSS_FILTERS": "filters",
"FORCE_RENDER": "force-render"
}
// 检测器
var detectors = [
function detectPrefer(cb) {
// 查看用户喜好
if (window.matchMedia) {
return cb(window.matchMedia(
"(prefers-color-scheme: dark)"
).matches ? Result.PREFER_COLOR_SCHEME_DARK : false);
}
return cb(false);
},
function detectCSS(cb) {
// 查看默认样式表
// 这里不特别区分是浏览器样式表还是注入样式表。
// 扩展插入的 CSS ,你难道能动?
if (window.getComputedStyle) {
var curStyle = window.getComputedStyle(textarea);
var foreLight = extractLight(curStyle.color);
var backLight = extractLight(curStyle.backgroundColor);
curStyle = window.getComputedStyle(p);
var foreLight2 = extractLight(curStyle.color);
if (foreLight < backLight || foreLight2 < backLight) return cb(false);
// 现在一定是 CSS 层面能检测到的颜色差异。检测是不是
// !important 过的
// 都宁愿创建一个 <style> ,但有可能引起误会。
p.style.backgroundColor = "white";
p.style.color = "black";
foreLight = extractLight(curStyle.color);
backLight = extractLight(curStyle.backgroundColor);
if (foreLight > backLight) {
cb( Result.FORCE_COLOR);
} else {
cb(Result.SUGGEST_COLOR);
}
return;
}
cb(false);
},
function detectRender(cb){
img.src = "";
}
];
function extractLight(cssRgbStr) {
// 事实上工作在 LAB 色彩空间
var reg = /^[rgba(,) ]+([-0-9.]+)[(,) ]+([-0-9.]+)[(,) ]+([-0-9.]+)[(,); ]+/i;
var regRes = reg.exec(cssRgbStr);
if (!regRes) {
throw new Error("不规范的 CSS 颜色字符串。");
}
var r = +regRes[1], g = +regRes[2], b = +regRes[3];
// RGB -> XYZ, 只用 Y 分量
var y = 0.2126729 * r + 0.7151522 * g + 0.0721750 * b;
// 所有公式都在 [0,1] 下工作
y = y / 255;
if (y > 216 / 24389) {
return 116 * Math.pow(y, 1 / 3) - 16;
} else {
return 116 * (12 / 841 * y + 4 / 29) - 16;
}
}
var result = false;
function doDetect(res) {
if(res) {
console.log(res);
return;
}
try {
var fn = detectors[0];
if(!fn) return doDetect("light");
detectors.shift();
fn(doDetect);
} catch (e) {
console.error(e);
throw e;
}
}
window.onload = function () {
setTimeout(doDetect, 300);
}
})();
正在检测您的浏览器颜色配置......