Dark Mode+

Sketchful dark theme improvements

目前为 2020-07-29 提交的版本。查看 最新版本

// ==UserScript==
// @name        Dark Mode+
// @match       https://sketchful.io/
// @grant       none
// @version     1.2
// @description Sketchful dark theme improvements
// @author      bebell
// @run-at      document-end
// jshint esversion: 6
// @namespace   https://gf.qytechs.cn/users/281093
// ==/UserScript==

let grayCanvas = localStorage.grayCanvas
    ? JSON.parse(localStorage.grayCanvas)
    : true;
const pageHTML = document.querySelector("html");
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
const themes = document.querySelector("#menuSettingsTheme");
const settingsContainer = document.querySelector(
    "#menuSettings > div.row.justify-content-center > div"
);
const styleRules = [
    ".dark .table { color: white !important; }",
    ".table { color: black !important; }",
    ".dark { background-color: #1d1f22 !important; }",
    ".dark .table th, html.dark .table thead, html.dark .table td { border-color: #454d55 !important; }",
    ".table th, .table thead, .table td { border-color: #dee2e6 !important; }",
    ".dark .table.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(255,255,255,.05)!important; }",
    ".table.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(0,0,0,.05)!important; }",
    ".dark #gameChatList li:not(.chatAdmin) b { color: #BBB }",
    "#gameChatList li:not(.chatAdmin) b { color: black }",
    ".dark .gameAvatarRank { color: #148FA2 }",
    ".dark #gameWinners li b { color: white !important }",
    ".dark .gameSticky { color: white !important }",
    "#gameSticky font { color: black!important }",
    ".dark #gameSticky font { color: #eee!important }",
];

const sheet =
    window.document.styleSheets[window.document.styleSheets.length - 1];
styleRules.forEach((rule) => sheet.insertRule(rule));

let btn;
let stored = localStorage.dark;
let darkMode = stored
    ? JSON.parse(stored)
    : JSON.parse(localStorage.getItem("settings")).dark;

if (darkMode) pageHTML.classList.add("dark");
else pageHTML.classList.remove("dark");

canvas.style.filter = darkMode
            ? `brightness(${localStorage.canvasBrightness})` || ""
            : "";

themes.onchange = (e) => {
  	if (e.target.value === "Dark" && !grayCanvas) {
		pageHTML.classList.add("dark");
	  	e.stopImmediatePropagation();
	}
};

document.querySelector("#menu > div.menuNav > ul > li:nth-child(5) > a").onclick = () => {
  	themes.value = darkMode ? "Dark" : "Light";
};

function darkClassObserver(mutations, observer) {
    for (let mutation of mutations) {
        if (mutation.attributeName !== "class") return;
        darkMode = pageHTML.classList.contains("dark");
        localStorage.dark = darkMode;
        canvas.style.filter = darkMode
            ? `brightness(${localStorage.canvasBrightness})` || ""
            : "";
        fixColors();
        grayCanvas && toggleCanvasDarkMode();
    }
}

const gameObserver = new MutationObserver(darkClassObserver);

gameObserver.observe(pageHTML, { attributes: true });

(function addBrightnessSlider() {
    const sliderContainer = document
        .querySelector("#menuSettingsVolumeIcon")
        .parentNode.cloneNode(true);
    sliderContainer.getElementsByTagName("h5")[0].textContent =
        "Canvas Brightness";
    const icon = sliderContainer.children[0];
    icon.onload = () => {
        icon.src = "https://faust.s-ul.eu/Sa78AixS";
    };
    const slider = sliderContainer.querySelector("#menuSettingsVolume");
    slider.value = localStorage.canvasBrightness || 1;
    slider.onchange = changeBrightness;

    const grayCanvasToggle = document.createElement("div");
    grayCanvasToggle.setAttribute(
        "style",
        "display: flex; justify-content: space-between"
    );
    const label = document.createElement("label");

    label.style.fontSize = "20px";
    label.textContent = "Gray Canvas";

    let btnSwitch = document.createElement("label");
    let input = document.createElement("input");
    let span = document.createElement("span");
    span.setAttribute("class", "slider round");
    input.type = "checkbox";
    input.checked = grayCanvas;
    input.onchange = () => {
        grayCanvas = input.checked;
        localStorage.grayCanvas = grayCanvas;
	  	if (!grayCanvas && darkMode) {
		  	themes[0].selected = true;
        	themes.dispatchEvent(new Event("change"));
		  	pageHTML.classList.add("dark");
		  	themes.value = darkMode ? "Dark" : "Light";
		}
    };
    btnSwitch.setAttribute("class", "switch");
    btnSwitch.append(input, span);
    grayCanvasToggle.append(label, btnSwitch);
    settingsContainer.append(sliderContainer, grayCanvasToggle);
})();

(function toggleButtons() {
    btn = document.querySelector("#saveButton").cloneNode();
    btn.style.right = "100px";
  	btn.setAttribute("data-original-title", "Toggle Theme");
  	btn.title = "Toggle Theme";
    updateToggleStyle();
    btn.onclick = toggleDarkMode;

    document.querySelector("#gameInterface").append(btn);
})();

function changeBrightness() {
    canvas.style.filter = `brightness(${this.value})`;
    localStorage.canvasBrightness = this.value;
}

function updateToggleStyle() {
  	btn.style.backgroundImage = darkMode ? "url(https://i.imgur.com/UBpXB1r.png)" : 
								"url(https://i.imgur.com/5phmZod.png)";
}

function toggleDarkMode() {
    if (!grayCanvas) {
        pageHTML.classList.toggle("dark");
    } else {
        themes[darkMode ? 0 : 1].selected = true;
        themes.dispatchEvent(new Event("change"));
    }
}

function toggleCanvasDarkMode() {
    const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imgData.data;

    for (let i = 0; i < data.length; i += 4) {
        const [r, g, b] = [data[i], data[i + 1], data[i + 2]];

        if (r === 255 && g === 255 && b === 255 && darkMode) {
            let color = 68;
            data[i] = color;
            data[i + 1] = color;
            data[i + 2] = color;
        } 
        else if (r === 68 && g === 68 && b === 68 && !darkMode) {
            let color = 255;
            data[i] = color;
            data[i + 1] = color;
            data[i + 2] = color;
        }
    }

    ctx.putImageData(imgData, 0, 0);
}

function fixColors() {
    let names = document.getElementsByClassName("gameAvatarName");
	updateToggleStyle();
    if (!names.length)
        names = document.getElementsByClassName("gameSettingsAvatarName");
    for (let name of names) {
        if (darkMode && name.style.color === "black") {
            name.style.color = "#ccc";
        } else if (!darkMode && name.style.color === "rgb(204, 204, 204)") {
            name.style.color = "black";
        }
    }
}

const colorObserver = new MutationObserver(() => {
    fixColors();
});

colorObserver.observe(document.querySelector("#gamePlayersList"), {
    childList: true,
});

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址