Add eyedropper tool

This commit is contained in:
Skyler Lehmkuhl 2025-01-05 19:20:45 -05:00
parent 62cfa9bf8c
commit 377a1cc6c1
3 changed files with 115 additions and 1 deletions

47
src/assets/eyedropper.svg Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="16"
height="16"
fill="currentColor"
class="bi bi-eyedropper"
viewBox="0 0 16 16"
version="1.1"
id="svg1"
sodipodi:docname="eyedropper.svg"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
inkscape:zoom="73.8125"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-width="1151"
inkscape:window-height="1028"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg1" />
<path
d="M13.354.646a1.207 1.207 0 0 0-1.708 0L8.5 3.793l-.646-.647a.5.5 0 1 0-.708.708L8.293 5l-7.147 7.146A.5.5 0 0 0 1 12.5v1.793l-.854.853a.5.5 0 1 0 .708.707L1.707 15H3.5a.5.5 0 0 0 .354-.146L11 7.707l1.146 1.147a.5.5 0 0 0 .708-.708l-.647-.646 3.147-3.146a1.207 1.207 0 0 0 0-1.708zM2 12.707l7-7L10.293 7l-7 7H2z"
id="path1" />
<path
style="fill:#bfbfbf;fill-opacity:0.5;stroke:none;stroke-width:0.0270957;stroke-linejoin:round"
d="M 0.37160845,15.975572 C 0.23058508,15.935565 0.11353909,15.834277 0.0494617,15.696799 0.01944525,15.6324 0.01397395,15.601861 0.01397395,15.49873 c 0,-0.208493 1.5764e-4,-0.208713 0.5351384,-0.745164 l 0.45949385,-0.460757 0.00374,-0.961815 0.00374,-0.961815 0.038443,-0.08129 C 1.0893202,12.214319 1.435257,11.864491 4.6967857,8.6046278 L 8.3006014,5.002657 7.6971445,4.3977977 C 7.0135239,3.7125884 7.0225026,3.7240849 7.0135045,3.5224386 7.0079852,3.3987497 7.0364006,3.3020761 7.1068697,3.2047965 7.2311516,3.03323 7.4758779,2.9636814 7.6816257,3.0414565 7.7563111,3.0696885 7.792915,3.1019953 8.1323288,3.4392494 L 8.501745,3.8063149 10.130635,2.179274 c 0.89589,-0.8948726 1.65718,-1.64596077 1.691756,-1.66908486 0.113189,-0.0757006 0.25504,-0.13905454 0.388525,-0.17352532 0.117603,-0.0303692 0.151481,-0.0333125 0.327611,-0.0284617 0.182472,0.005025 0.206332,0.008827 0.335478,0.0534514 0.288426,0.0996612 0.238681,0.056177 1.461202,1.27730008 1.184817,1.1834612 1.19065,1.189933 1.279081,1.4192393 0.05865,0.1520951 0.08089,0.2757401 0.08089,0.4498464 0,0.2412105 -0.06869,0.4642793 -0.206776,0.6714696 -0.02235,0.033531 -0.7728,0.7939659 -1.667673,1.6898558 l -1.62704,1.6288903 0.367066,0.3694162 c 0.337254,0.3394138 0.369561,0.3760177 0.397792,0.4507031 0.07778,0.2057478 0.0082,0.4504741 -0.163339,0.574756 -0.09728,0.070469 -0.193954,0.098885 -0.317643,0.093365 -0.201602,-0.009 -0.190319,-1.886e-4 -0.873821,-0.6821053 L 11.000419,7.7024679 7.3969074,11.304226 c -3.2399405,3.238364 -3.6117133,3.60569 -3.684799,3.640722 l -0.081287,0.03896 -0.9618152,0.0037 -0.9618152,0.0037 -0.4607081,0.458355 c -0.39248014,0.390476 -0.47248593,0.463828 -0.54023815,0.49531 -0.0950846,0.04418 -0.23990543,0.05739 -0.3346362,0.03051 z M 6.8043723,10.502994 10.303091,7.0042953 9.6494596,6.3505599 8.9958285,5.6968245 5.4970676,9.1955658 1.9983065,12.694307 V 13.348 14.001693 h 0.6536736 0.6536734 z"
id="path2" />
<path
style="fill:#ffffff;fill-opacity:0.5;stroke:none;stroke-width:0.0270957;stroke-linejoin:round"
d="M 0.33514452,15.956292 C 0.2025283,15.903523 0.06941865,15.760191 0.0330582,15.631007 c -0.009398,-0.03339 -0.01365979,-0.104909 -0.01019039,-0.17101 0.0052748,-0.100497 0.011283,-0.12203 0.05203058,-0.186469 0.02555881,-0.04042 0.24531428,-0.273821 0.49362843,-0.524281 l 0.44756128,-0.451432 0.00486,-0.964216 c 0.00475,-0.941742 0.00552,-0.965608 0.03292,-1.023908 0.040768,-0.08673 0.7792718,-0.834616 4.2485061,-4.3024793 L 8.3107476,5.0000287 7.72489,4.4102599 C 7.4026682,4.0858871 7.1147991,3.7847152 7.0851808,3.740989 7.0329519,3.663882 7.0311935,3.6575553 7.0268192,3.5309975 7.0207785,3.3562244 7.0519026,3.2693845 7.15895,3.162337 7.242162,3.0791251 7.3372371,3.0344211 7.462245,3.0197289 c 0.090414,-0.010626 0.2271973,0.022912 0.2931279,0.071874 0.026501,0.01968 0.2049578,0.1912597 0.396571,0.3812881 L 8.5003315,3.8183966 10.136816,2.186929 c 1.033688,-1.0305183 1.665946,-1.65098425 1.716465,-1.68445189 0.09605,-0.0636294 0.252896,-0.13141261 0.374511,-0.16184804 0.117252,-0.0293436 0.435661,-0.0305781 0.544946,-0.002113 0.148466,0.0386704 0.291387,0.10275213 0.381774,0.17117714 0.138626,0.10494251 0.602982,0.55596799 1.422965,1.38211599 0.915545,0.9224282 0.961632,0.9755037 1.040955,1.1987856 0.04847,0.1364499 0.06497,0.2427876 0.06476,0.4175015 -2.83e-4,0.2347439 -0.06044,0.4448758 -0.181458,0.6338515 -0.03261,0.050924 -0.611765,0.6413231 -1.684926,1.7176419 l -1.635234,1.6400461 0.345522,0.3484038 c 0.190038,0.1916222 0.361624,0.3700864 0.381305,0.3965873 0.04896,0.065931 0.0825,0.2027135 0.07187,0.2931279 -0.01469,0.1250079 -0.0594,0.220083 -0.142608,0.303295 -0.107047,0.1070474 -0.193887,0.1381715 -0.36866,0.1321308 -0.126564,-0.00437 -0.132881,-0.00613 -0.209992,-0.05837 -0.04373,-0.029623 -0.342046,-0.3146353 -0.662934,-0.6333615 -0.320887,-0.3187261 -0.58914,-0.579502 -0.596117,-0.579502 -0.007,0 -1.3417223,1.3295661 -2.966102,2.9545919 -3.4511864,3.452558 -4.247166,4.23866 -4.3389317,4.285086 l -0.064105,0.03243 -0.9641237,0.0051 -0.9641238,0.0051 -0.4589281,0.454631 c -0.52894239,0.523988 -0.53701685,0.529886 -0.73450642,0.536437 -0.0849326,0.0028 -0.13180834,-0.0023 -0.17399476,-0.01912 z M 6.8111671,10.509747 c 1.9205812,-1.92057 3.4919659,-3.4980231 3.4919659,-3.5054511 0,-0.017711 -1.2895944,-1.3074288 -1.307304,-1.3074288 -0.00748,0 -1.5849756,1.5713757 -3.5055566,3.491946 L 1.9983065,12.680759 v 0.660467 0.660467 h 0.6604474 0.6604475 z"
id="path3" />
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -39,6 +39,7 @@ import {
rotateAroundPoint,
getRotatedBoundingBox,
rotateAroundPointIncremental,
rgbToHsv,
} from "./utils.js";
import {
backgroundColor,
@ -272,6 +273,16 @@ let tools = {
},
},
},
eyedropper: {
icon: "/assets/eyedropper.svg",
properties: {
dropperColor: {
type: "enum",
options: ["Fill color", "Stroke color"],
label: "Color"
}
}
}
};
let mouseEvent;
@ -294,6 +305,7 @@ let context = {
fillShape: false,
strokeShape: true,
fillGaps: 5,
dropperColor: "Fill color",
dragging: false,
selectionRect: undefined,
selection: [],
@ -4687,6 +4699,21 @@ function stage() {
// }
}
break;
case "eyedropper":
const ctx = stage.getContext("2d")
const imageData = ctx.getImageData(mouse.x, mouse.y, 1, 1); // Get pixel at (x, y)
const data = imageData.data; // The pixel data is in the `data` array
const hsv = rgbToHsv(...data)
if (context.dropperColor == "Fill color") {
for (let el of document.querySelectorAll(".color-field.fill")) {
el.setColor(hsv, 'ff')
}
} else {
for (let el of document.querySelectorAll(".color-field.stroke")) {
el.setColor(hsv, 'ff')
}
}
break;
default:
break;
}
@ -5118,10 +5145,13 @@ function toolbar() {
let strokeColor = document.createElement("div");
fillColor.className = "color-field";
strokeColor.className = "color-field";
fillColor.classList.add("fill")
strokeColor.classList.add("stroke")
fillColor.setColor = (hsv, alpha) => {
console.log(hsv)
const rgb = hsvToRgb(...hsv)
console.log(alpha)
const color = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha
console.log(color)
fillColor.style.setProperty("--color", color);
fillColor.color = color;
fillColor.hsv = hsv

View File

@ -542,6 +542,42 @@ const rgbToHex = (r, g, b) => {
return `#${(1 << 24 | (r << 16) | (g << 8) | b).toString(16).slice(1).toUpperCase()}`;
};
function rgbToHsv(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const delta = max - min;
let h = 0;
let s = 0;
let v = max;
if (delta !== 0) {
s = delta / max;
if (r === max) {
h = (g - b) / delta;
} else if (g === max) {
h = 2 + (b - r) / delta;
} else {
h = 4 + (r - g) / delta;
}
h *= 60;
if (h < 0) {
h += 360;
}
}
// Normalize hue to be between 0 and 1
h /= 360;
return [h, s, v]; // Return as array [h, s, v]
}
function clamp(n) {
// Clamps a value between 0 and 1
return Math.min(Math.max(n,0),1)
@ -885,6 +921,7 @@ export {
hexToHsl,
hexToHsv,
rgbToHex,
rgbToHsv,
drawCheckerboardBackground,
clamp,
signedAngleBetweenVectors,