您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Color picker for Sketchful
当前为
// ==UserScript== // @name Color Picker // @namespace https://greasyfork.org/users/281093 // @match https://sketchful.io/* // @grant none // @version 0.6.1 // @author Bell // @description Color picker for Sketchful // @run-at document-end // jshint esversion: 6 // ==/UserScript== let defaultPalettes = [ [ "#ffffff", "#d3d1d2", "#f70f0f", "#ff7200", "#fce700", "#02cb00", "#01fe94", "#05b0ff", "#221ecd", "#a300bd", "#cc7fad", "#fdad88", "#9e5425", "#514f54", "#a9a7a8", "#ae0b00", "#c84706", "#ec9e06", "#007612", "#049d6f", "#00579d", "#0f0b96", "#6e0083", "#a65673", "#e38a5e", "#5e320d", "#000000", "#827c80", "#57060c", "#8b2500", "#9e6600", "#003f00", "#00766a", "#003b75", "#0e0151", "#3c0350", "#73314d", "#d1754e", "#421e06" ], [ "#3a3a3c", "#8e8e93", "#f8f9fa", "#ffadad", "#ffd6a5", "#fdffb6", "#caffbf", "#9bf6ff", "#a0c4ff", "#bdb2ff", "#ffc6ff", "#fdad88", "#9e5425", "#2c2c2e", "#636366", "#e0e0e0", "#ff7070", "#f3a220", "#f9e079", "#049d6f", "#92ddea", "#6dafe0", "#ab87ff", "#ff87ab", "#e38a5e", "#5e320d", "#1c1c1e", "#48484a", "#c2c2c2", "#f54d4d", "#dc8700", "#f0c808", "#00766a", "#219bc3", "#548bbc", "#715aff", "#ff5d8f", "#d1754e", "#421e06" ], [ "#081c15", "#1b4332", "#2d6a4f", "#40916c", "#52b788", "#74c69d", "#95d5b2", "#b7e4c7", "#d8f3dc", "#000000", "#faf9f9", "#ffd6ba", "#fec89a", "#774936", "#8a5a44", "#9d6b53", "#b07d62", "#c38e70", "#cd9777", "#d69f7e", "#deab90", "#e6b8a2", "#edc4b3", "#ffb5a7", "#fcd5ce", "#f8edeb", "#cb997e", "#eddcd2", "#fff1e6", "#f0efeb", "#ddbea9", "#a5a58d", "#b7b7a4", "#6d6875", "#b5838d", "#e5989b", "#ffb4a2", "#ffcdb2", "#f9dcc4" ], [ "#10002b", "#240046", "#3c096c", "#5a189a", "#7b2cbf", "#9d4edd", "#c77dff", "#e0aaff", "#efcefa", "#d4b2d8", "#a88fac", "#826c7f", "#5d4e60", "#7c6f93", "#886f93", "#a967ad", "#ad6789", "#db81ad", "#ff6c91", "#ff736c", "#ff9e46", "#faa275", "#ff8c61", "#ce6a85", "#985277", "#5c374c", "#721b65", "#b80d57", "#f8615a", "#ffd868", "#bb596b", "#f96d80", "#ff9a76", "#ffc4a3", "#00e0ff", "#74f9ff", "#a6fff2", "#e8ffe8", "#ffffff" ], [ "#007f5f", "#2b9348", "#55a630", "#80b918", "#aacc00", "#bfd200", "#d4d700", "#dddf00", "#eeef20", "#ffff3f", "#03045e", "#0077b6", "#00b4d8", "#ff4800", "#ff5400", "#ff6000", "#ff6d00", "#ff7900", "#ff8500", "#ff9100", "#ff9e00", "#ffaa00", "#ffb600", "#90e0ef", "#caf0f8", "#000000", "#143642", "#263c41", "#38413f", "#4a473e", "#5c4d3c", "#6f523b", "#815839", "#935e38", "#a56336", "#b76935", "#000000", "#ffffff", "#ffffff" ] ]; let palettes = JSON.parse(localStorage.getItem('palettes')) || defaultPalettes; let paletteIndex = parseInt(localStorage.getItem("paletteIndex")) || 0; let lockedPalettes = JSON.parse(localStorage.getItem('lockedPalettes')) || [0]; let activeColor = { node: null, index: null }; const canvas = document.querySelector("#canvas"); const ctx = canvas.getContext("2d"); const gameTools = document.querySelector("#gameTools"); const chatBox = document.querySelector("#gameChat"); const colorButtons = document.querySelectorAll(".gameToolsColor"); const colorsDiv = document.querySelector("#gameToolsColors"); const colorButton = document.querySelector("#gameToolsColors > div:nth-child(1) > div:nth-child(1)"); const colorPickerWrapper = document.createElement("div"); const colorInput = document.createElement("input"); const colorPicker = document.createElement("input"); const inputStyle = `margin: 5px 0; height: 20px; width: 35%; text-align: center; border: none;font-weight: 800; border-radius: 5px; background-color: #CBCBCB;`; const wrapperStyle = `position: absolute; margin: 5px 35%; height: 20px; width: 37px; border-radius: 5px;`; (function init() { addPicker(); updatePageStyle(); addObservers(); addListeners(); changePalette(); })(); function addPicker() { colorPicker.type = "color"; colorPicker.setAttribute("style", "opacity: 0; width: 37px; cursor: pointer;"); colorPicker.oninput = updatePicker; colorPickerWrapper.setAttribute("style", wrapperStyle); colorPickerWrapper.style.backgroundColor = colorPicker.value; colorPickerWrapper.appendChild(colorPicker); gameTools.appendChild(colorPickerWrapper); colorInput.oninput = updateInput; colorInput.onclick = selectInputText; colorInput.setAttribute("style", inputStyle); colorInput.setAttribute("spellcheck", "false"); colorInput.setAttribute("maxlength", "7"); colorInput.value = colorPicker.value; gameTools.appendChild(colorInput); addButtons(); } function addObservers() { const heightObserver = new MutationObserver(adjustChatSize); const config = { attributes: true, }; heightObserver.observe(gameTools, config); heightObserver.observe(chatBox, config); } function addListeners() { canvas.onpointerdown = pickCanvasColor; colorsDiv.onpointerdown = editColor; let saveBtn = document.querySelector("#savePalette"); saveBtn.addEventListener("dragenter", highlight, false); saveBtn.addEventListener("dragleave", unhighlight, false); saveBtn.addEventListener("drop", handleDrop, false); saveBtn.addEventListener("dragover", e => { e.preventDefault(); }, false); document.addEventListener('keydown', e => { if (e.altKey && e.shiftKey && !isPaletteLocked(paletteIndex)) { colorsDiv.style.boxShadow = "0 0 0 2px red"; } }, false); document.addEventListener('keyup', e => { if (e.altKey || e.shiftKey) { colorsDiv.style.boxShadow = ""; } }, false); } function updatePageStyle() { document.querySelector("#gameToolsSlider").style.top = "77px"; gameTools.style.height = "200px"; } function toggleLock() { let lockBtn = document.querySelector("#lockButton"); if (lockBtn.getAttribute("state") === "unlocked") { lockPalette(lockBtn); } else { unlockPalette(lockBtn); } updateLock(); } function lockPalette() { lockedPalettes.push(paletteIndex); localStorage.setItem("lockedPalettes", JSON.stringify(lockedPalettes)); } function unlockPalette() { let index = lockedPalettes.indexOf(paletteIndex); if (index < 0) return; lockedPalettes.splice(index, 1); localStorage.setItem("lockedPalettes", JSON.stringify(lockedPalettes)); } function updateLock() { let lockBtn = document.querySelector("#lockButton"); if (isPaletteLocked(paletteIndex)) { lockBtn.classList.remove("fa-unlock-alt"); lockBtn.classList.add("fa-lock"); lockBtn.setAttribute("state", "locked"); colorsDiv.style.boxShadow = ""; } else { lockBtn.classList.add("fa-unlock-alt"); lockBtn.classList.remove("fa-lock"); lockBtn.setAttribute("state", "unlocked"); } resetActiveColor(); } function addButtons() { let prevPaletteBtn = document.createElement("button"); let saveColorBtn = document.createElement("button"); let nextPaletteBtn = document.createElement("button"); let lockBtn = document.createElement("button"); addButton(prevPaletteBtn, "arrow-left", "5px 5px 5px 45px;"); addButton(saveColorBtn, "save", "5px 5px 5px 75px;", "savePalette"); addButton(nextPaletteBtn, "arrow-right", "5px 5px 5px 105px;"); addButton(lockBtn, "unlock-alt", "5px 5px 5px 135px;", "lockButton"); lockBtn.setAttribute("state", "unlocked"); prevPaletteBtn.addEventListener("click", prevPalette, false); saveColorBtn.addEventListener("click", saveColor, false); nextPaletteBtn.addEventListener("click", nextPalette, false); lockBtn.addEventListener("click", toggleLock, false); } function nextPalette() { paletteIndex = paletteIndex < (palettes.length - 1) ? paletteIndex + 1 : 0; localStorage.setItem("paletteIndex", paletteIndex); changePalette(); } function prevPalette() { paletteIndex = paletteIndex > 0 ? paletteIndex - 1 : palettes.length - 1; localStorage.setItem("paletteIndex", paletteIndex); changePalette(); } function saveColor(e) { if (e.shiftKey) { downloadPalettes(); return; } let currentPalette = palettes[paletteIndex]; if (activeColor.index) { currentPalette[activeColor.index] = colorPicker.value; } else { addColor(colorPicker.value); } changePalette(); savePalettes(); } function addColor(color) { if (palettes[paletteIndex].length > 38 || isPaletteLocked(paletteIndex)) { palettes.push([]); paletteIndex = palettes.length - 1; } palettes[paletteIndex].push(color); } function rgbToHex(rgb) { let regEx = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/; let [, r, g, b] = regEx.exec(rgb); function hex(x) { return ("0" + parseInt(x).toString(16)).slice(-2); } return `#${hex(r)}${hex(g)}${hex(b)}`; } function savePalettes() { localStorage.setItem("palettes", JSON.stringify(palettes)); } function downloadPalettes() { let formattedPaletteData = JSON.stringify(palettes[paletteIndex]).replace(/\]\,/g, "],\n\n"); download("palette.txt", formattedPaletteData); } function download(filename, text) { let pom = document.createElement('a'); pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); pom.setAttribute('download', filename); if (document.createEvent) { let event = document.createEvent('MouseEvents'); event.initEvent('click', true, true); pom.dispatchEvent(event); } else { pom.click(); } } function isPaletteLocked(index) { return lockedPalettes.includes(index); } function updateColorInputs(colorValue) { colorPickerWrapper.style.backgroundColor = colorValue; colorPicker.value = colorValue; colorInput.value = colorValue; } function editColor(event) { if (!event.target.classList.contains("gameToolsColor")) return; if (!event.shiftKey) updateColorInputs(rgbToHex(event.target.style.backgroundColor)); if (isPaletteLocked(paletteIndex)) return; let color = { node: event.target, index: Array.prototype.indexOf.call(colorButtons, event.target) }; if (event.altKey && event.shiftKey) { deletePalette(paletteIndex); } else if (event.altKey && color.index >= 0) { let palette = palettes[paletteIndex]; palette.splice(color.index, 1); changePalette(); if (isPaletteEmpty(palette)) deletePalette(paletteIndex); } else if (event.shiftKey && color.index >= 0) { setActiveColor(color); } } function deletePalette(index) { if (palettes.length < 2) return; palettes.splice(index, 1); lockedPalettes = lockedPalettes.map(lockedIndex => { return lockedIndex > index ? lockedIndex - 1 : lockedIndex; }); localStorage.setItem("lockedPalettes", JSON.stringify(lockedPalettes)); prevPalette(); savePalettes(); updateLock(); } function changePalette() { if (paletteIndex < 0 || paletteIndex >= palettes.length) { paletteIndex = 0; localStorage.setItem("paletteIndex", paletteIndex); } colorButtons.forEach((button, idx) => { button.style.backgroundColor = palettes[paletteIndex][idx] || "#fff"; }); updateLock(); } function isPaletteEmpty(palette) { if (!palette) return true; let empty = true; for (let color of palette) { if (color) { empty = false; break; } } return empty; } function setActiveColor(color) { resetActiveColor(); activeColor = color; activeColor.node.style.border = "solid 2px red"; } function resetActiveColor() { if (activeColor.node) { activeColor.node.style.border = ""; activeColor = { node: null, index: null }; } } function addButton(button, icon, pos, id = "") { let buttonStyle = `margin: ${pos}; position: absolute; height: 20px; border: none; background-color: #CBCBCB; border-radius: 5px;`; button.setAttribute("style", buttonStyle); button.setAttribute("class", `fas fa-${icon}`); button.id = id; gameTools.appendChild(button); } function updatePicker(event) { let color = event.target.value; colorPickerWrapper.style.backgroundColor = color; colorInput.value = color; setColor(color); } function updateInput(event) { let hexFound = /([0-9A-Fa-f]{3}){1,2}/.exec(event.target.value); if (!hexFound) return; let color = "#" + hexFound[0]; colorPickerWrapper.style.backgroundColor = color; colorPicker.value = color; setColor(color); } function setColor(color) { let prevColor = colorButton.style.backgroundColor; colorButton.style.backgroundColor = color; colorButton.dispatchEvent(new Event("pointerdown")); colorButton.style.backgroundColor = prevColor; } function selectInputText() { colorInput.select(); } function pickCanvasColor(event) { if (!event.altKey) return; event.preventDefault(); event.stopImmediatePropagation(); let pos = getPos(event); let [r, g, b, a] = ctx.getImageData(pos.x, pos.y, 1, 1).data; let color = `rgb(${r}, ${g}, ${b})`; updateColorInputs(rgbToHex(color)); setColor(color); } function getPos(event) { let canvasRect = canvas.getBoundingClientRect(); let canvasScale = canvas.width / canvasRect.width; return { x: (event.clientX - canvasRect.left) * canvasScale, y: (event.clientY - canvasRect.top) * canvasScale }; } function handleDrop(e) { e.preventDefault(); colorsDiv.style.filter = ""; handleFiles(e.dataTransfer.files); } function handleFiles(files) { if (!files) return; files = [...files]; files.forEach(file => { let reader = new FileReader(); reader.readAsText(file); reader.onload = loadPalette; }); } function addPalette(palette) { if (palettes[paletteIndex].length + palette.length < 40 && !isPaletteLocked(paletteIndex)) { palettes[paletteIndex] = palettes[paletteIndex].concat(palette); } else { palettes.push(palette); paletteIndex = palettes.length - 1; localStorage.setItem("paletteIndex", paletteIndex); } resetPaletteState(); } function loadPalette(event) { const loadedString = event.target.result; const coolorRegex = /CSV \*\/\s*(\S+)/; const arrayRegex = /\[\[?\s*([^\]]+)/g; const hexRegex = /#([0-9A-Fa-f]{3}){1,2}/g; let coolorMatch = loadedString.match(coolorRegex); let arrayMatch = loadedString.match(arrayRegex); if (coolorMatch) { let palette = coolorMatch[1].split(",").map(color => `#${color}`); addPalette(palette); return; } else if (arrayMatch) { let palettes = arrayMatch.map(palette => palette.match(hexRegex)); palettes.forEach(palette => addPalette(palette)); } else { let hexCodesFound = [...new Set(loadedString.match(hexRegex))]; console.log("Hex codes found: ", hexCodesFound); hexCodesFound.forEach(code => addColor(code)); changePalette(); savePalettes(); } } function replacePalettes(newPalettes) { palettes = newPalettes; paletteIndex = 0; lockedPalettes = []; resetPaletteState(); } function resetPaletteState() { updateLock(); changePalette(); savePalettes(); } function highlight(e) { e.preventDefault(); colorsDiv.style.filter = "brightness(0.6)"; } function unhighlight(e) { e.preventDefault(); colorsDiv.style.filter = ""; } function isDrawing() { return document.querySelector("#gameTools").style.display !== "none"; } function adjustChatSize() { chatBox.style.height = isDrawing() ? "calc(100% - 200px)" : "calc(100% - 180px)"; }