Move color picker elements to widget classes
This commit is contained in:
parent
529638de37
commit
95c78a994e
190
src/main.js
190
src/main.js
|
|
@ -58,6 +58,7 @@ import {
|
||||||
shadow,
|
shadow,
|
||||||
} from "./styles.js";
|
} from "./styles.js";
|
||||||
import { Icon } from "./icon.js";
|
import { Icon } from "./icon.js";
|
||||||
|
import { AlphaSelectionBar, ColorSelectorWidget, ColorWidget, HueSelectionBar, SaturationValueSelectionGradient } from "./widgets.js";
|
||||||
const {
|
const {
|
||||||
writeTextFile: writeTextFile,
|
writeTextFile: writeTextFile,
|
||||||
readTextFile: readTextFile,
|
readTextFile: readTextFile,
|
||||||
|
|
@ -5148,7 +5149,6 @@ function toolbar() {
|
||||||
fillColor.classList.add("fill")
|
fillColor.classList.add("fill")
|
||||||
strokeColor.classList.add("stroke")
|
strokeColor.classList.add("stroke")
|
||||||
fillColor.setColor = (hsv, alpha) => {
|
fillColor.setColor = (hsv, alpha) => {
|
||||||
console.log(hsv)
|
|
||||||
const rgb = hsvToRgb(...hsv)
|
const rgb = hsvToRgb(...hsv)
|
||||||
const color = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha
|
const color = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha
|
||||||
fillColor.style.setProperty("--color", color);
|
fillColor.style.setProperty("--color", color);
|
||||||
|
|
@ -5197,167 +5197,20 @@ function toolbar() {
|
||||||
colorCvs.currentColor = "#00ffba88";
|
colorCvs.currentColor = "#00ffba88";
|
||||||
colorCvs.currentHSV = [0,0,0]
|
colorCvs.currentHSV = [0,0,0]
|
||||||
colorCvs.currentAlpha = 1
|
colorCvs.currentAlpha = 1
|
||||||
|
|
||||||
|
colorCvs.colorSelectorWidget = new ColorSelectorWidget(0, 0, colorCvs)
|
||||||
|
|
||||||
colorCvs.draw = function () {
|
colorCvs.draw = function () {
|
||||||
const darkMode =
|
|
||||||
window.matchMedia &&
|
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
||||||
let ctx = colorCvs.getContext("2d");
|
let ctx = colorCvs.getContext("2d");
|
||||||
ctx.lineWidth = 2;
|
colorCvs.colorSelectorWidget.draw(ctx)
|
||||||
if (darkMode) {
|
|
||||||
ctx.fillStyle = "#333";
|
|
||||||
} else {
|
|
||||||
ctx.fillStyle = "#ccc"; //TODO
|
|
||||||
}
|
|
||||||
ctx.fillRect(0, 0, colorCvs.width, colorCvs.height);
|
|
||||||
|
|
||||||
// draw current color
|
|
||||||
drawCheckerboardBackground(
|
|
||||||
ctx,
|
|
||||||
padding,
|
|
||||||
padding,
|
|
||||||
colorCvs.width - 2 * padding,
|
|
||||||
50,
|
|
||||||
10,
|
|
||||||
);
|
|
||||||
ctx.fillStyle = colorCvs.currentColor;
|
|
||||||
ctx.fillRect(padding, padding, colorCvs.width - 2 * padding, 50);
|
|
||||||
|
|
||||||
// Draw main gradient
|
|
||||||
let mainGradient = ctx.createImageData(mainSize, mainSize);
|
|
||||||
let data = mainGradient.data;
|
|
||||||
// let { h, s, v } = hexToHsv(colorCvs.currentColor);
|
|
||||||
let [h, s, v] = colorCvs.currentHSV
|
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
|
||||||
let x = ((i / 4) % mainSize) / mainSize;
|
|
||||||
let y = Math.floor(i / 4 / mainSize) / mainSize;
|
|
||||||
let hue = h;
|
|
||||||
let rgb = hsvToRgb(hue, x, 1 - y);
|
|
||||||
data[i + 0] = rgb.r;
|
|
||||||
data[i + 1] = rgb.g;
|
|
||||||
data[i + 2] = rgb.b;
|
|
||||||
data[i + 3] = 255;
|
|
||||||
}
|
|
||||||
ctx.putImageData(mainGradient, padding, 2 * padding + 50);
|
|
||||||
// draw pointer
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.arc(
|
|
||||||
s * mainSize + padding,
|
|
||||||
(1 - v) * mainSize + 2 * padding + 50,
|
|
||||||
3,
|
|
||||||
0,
|
|
||||||
2 * Math.PI,
|
|
||||||
);
|
|
||||||
ctx.strokeStyle = "white";
|
|
||||||
ctx.stroke();
|
|
||||||
|
|
||||||
let hueGradient = ctx.createImageData(mainSize, gradwidth);
|
|
||||||
data = hueGradient.data;
|
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
|
||||||
let x = ((i / 4) % mainSize) / mainSize;
|
|
||||||
let y = Math.floor(i / 4 / gradwidth);
|
|
||||||
let rgb = hslToRgb(x, 1, 0.5);
|
|
||||||
data[i + 0] = rgb.r;
|
|
||||||
data[i + 1] = rgb.g;
|
|
||||||
data[i + 2] = rgb.b;
|
|
||||||
data[i + 3] = 255;
|
|
||||||
}
|
|
||||||
ctx.putImageData(hueGradient, padding, 3 * padding + 50 + mainSize);
|
|
||||||
// draw pointer
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.rect(
|
|
||||||
h * mainSize + padding - 2,
|
|
||||||
3 * padding + 50 + mainSize,
|
|
||||||
4,
|
|
||||||
gradwidth,
|
|
||||||
);
|
|
||||||
ctx.strokeStyle = "white";
|
|
||||||
ctx.stroke();
|
|
||||||
|
|
||||||
drawCheckerboardBackground(
|
|
||||||
ctx,
|
|
||||||
colorCvs.width - (padding + gradwidth),
|
|
||||||
2 * padding + 50,
|
|
||||||
gradwidth,
|
|
||||||
mainSize,
|
|
||||||
10,
|
|
||||||
);
|
|
||||||
const gradient = ctx.createLinearGradient(
|
|
||||||
0,
|
|
||||||
2 * padding + 50,
|
|
||||||
0,
|
|
||||||
2 * padding + 50 + mainSize,
|
|
||||||
); // Vertical gradient
|
|
||||||
gradient.addColorStop(0, `${colorCvs.currentColor.slice(0, 7)}ff`); // Full color at the top
|
|
||||||
gradient.addColorStop(1, `${colorCvs.currentColor.slice(0, 7)}00`);
|
|
||||||
ctx.fillStyle = gradient;
|
|
||||||
ctx.fillRect(
|
|
||||||
colorCvs.width - (padding + gradwidth),
|
|
||||||
2 * padding + 50,
|
|
||||||
gradwidth,
|
|
||||||
mainSize,
|
|
||||||
);
|
|
||||||
let alpha =
|
|
||||||
parseInt(colorCvs.currentColor.slice(7, 9) || "ff", 16) / 255;
|
|
||||||
// draw pointer
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.rect(
|
|
||||||
colorCvs.width - (padding + gradwidth),
|
|
||||||
2 * padding + 50 + (1 - alpha) * mainSize - 2,
|
|
||||||
gradwidth,
|
|
||||||
4,
|
|
||||||
);
|
|
||||||
ctx.strokeStyle = "white";
|
|
||||||
ctx.stroke();
|
|
||||||
};
|
};
|
||||||
colorCvs.addEventListener("mousedown", (e) => {
|
colorCvs.addEventListener("mousedown", (e) => {
|
||||||
colorCvs.clickedMainGradient = false;
|
colorCvs.clickedMainGradient = false;
|
||||||
colorCvs.clickedHueGradient = false;
|
colorCvs.clickedHueGradient = false;
|
||||||
colorCvs.clickedAlphaGradient = false;
|
colorCvs.clickedAlphaGradient = false;
|
||||||
let mouse = getMousePos(colorCvs, e);
|
let mouse = getMousePos(colorCvs, e);
|
||||||
// let { h, s, v } = hexToHsv(colorCvs.currentColor);
|
colorCvs.colorSelectorWidget.handleMouseEvent("mousedown", mouse.x, mouse.y)
|
||||||
let [h, s, v] = colorCvs.currentHSV
|
|
||||||
if (
|
|
||||||
mouse.x > padding &&
|
|
||||||
mouse.x < padding + mainSize &&
|
|
||||||
mouse.y > 2 * padding + 50 &&
|
|
||||||
mouse.y < 2 * padding + 50 + mainSize
|
|
||||||
) {
|
|
||||||
// we clicked in the main gradient
|
|
||||||
let x = (mouse.x - padding) / mainSize;
|
|
||||||
let y = (mouse.y - (2 * padding + 50)) / mainSize;
|
|
||||||
let rgb = hsvToRgb(h, x, 1 - y);
|
|
||||||
let alpha = colorCvs.currentColor.slice(7, 9) || "ff";
|
|
||||||
colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
|
||||||
colorCvs.currentHSV = [h, x, 1 - y]
|
|
||||||
colorCvs.currentAlpha = alpha
|
|
||||||
colorCvs.clickedMainGradient = true;
|
|
||||||
} else if (
|
|
||||||
mouse.x > padding &&
|
|
||||||
mouse.x < padding + mainSize &&
|
|
||||||
mouse.y > 3 * padding + 50 + mainSize &&
|
|
||||||
mouse.y < 3 * padding + 50 + mainSize + gradwidth
|
|
||||||
) {
|
|
||||||
// we clicked in the hue gradient
|
|
||||||
let x = (mouse.x - padding) / mainSize;
|
|
||||||
let rgb = hsvToRgb(x, s, v);
|
|
||||||
let alpha = colorCvs.currentColor.slice(7, 9) || "ff";
|
|
||||||
colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
|
||||||
colorCvs.currentHSV = [x, s, v]
|
|
||||||
colorCvs.currentAlpha = alpha
|
|
||||||
colorCvs.clickedHueGradient = true;
|
|
||||||
} else if (
|
|
||||||
mouse.x > colorCvs.width - (padding + gradwidth) &&
|
|
||||||
mouse.x < colorCvs.width - padding &&
|
|
||||||
mouse.y > 2 * padding + 50 &&
|
|
||||||
mouse.y < 2 * padding + 50 + mainSize
|
|
||||||
) {
|
|
||||||
// we clicked in the alpha gradient
|
|
||||||
let y = 1 - (mouse.y - (2 * padding + 50)) / mainSize;
|
|
||||||
let alpha = Math.round(y * 255).toString(16);
|
|
||||||
colorCvs.currentColor = `${colorCvs.currentColor.slice(0, 7)}${alpha}`;
|
|
||||||
colorCvs.currentAlpha = alpha
|
|
||||||
colorCvs.clickedAlphaGradient = true;
|
|
||||||
}
|
|
||||||
colorCvs.colorEl.setColor(colorCvs.currentHSV, colorCvs.currentAlpha);
|
colorCvs.colorEl.setColor(colorCvs.currentHSV, colorCvs.currentAlpha);
|
||||||
colorCvs.draw();
|
colorCvs.draw();
|
||||||
});
|
});
|
||||||
|
|
@ -5367,6 +5220,8 @@ function toolbar() {
|
||||||
colorCvs.clickedMainGradient = false;
|
colorCvs.clickedMainGradient = false;
|
||||||
colorCvs.clickedHueGradient = false;
|
colorCvs.clickedHueGradient = false;
|
||||||
colorCvs.clickedAlphaGradient = false;
|
colorCvs.clickedAlphaGradient = false;
|
||||||
|
|
||||||
|
colorCvs.colorSelectorWidget.handleMouseEvent("mouseup", mouse.x, mouse.y)
|
||||||
if (e.target != colorCvs) {
|
if (e.target != colorCvs) {
|
||||||
colorCvs.style.display = "none";
|
colorCvs.style.display = "none";
|
||||||
window.removeEventListener("mousemove", evtListener);
|
window.removeEventListener("mousemove", evtListener);
|
||||||
|
|
@ -5377,33 +5232,8 @@ function toolbar() {
|
||||||
}
|
}
|
||||||
evtListener = window.addEventListener("mousemove", (e) => {
|
evtListener = window.addEventListener("mousemove", (e) => {
|
||||||
let mouse = getMousePos(colorCvs, e);
|
let mouse = getMousePos(colorCvs, e);
|
||||||
let { h, s, v } = hexToHsv(colorCvs.currentColor);
|
colorCvs.colorSelectorWidget.handleMouseEvent("mousemove", mouse.x, mouse.y)
|
||||||
if (colorCvs.clickedMainGradient) {
|
colorCvs.draw()
|
||||||
let x = clamp((mouse.x - padding) / mainSize);
|
|
||||||
let y = clamp((mouse.y - (2 * padding + 50)) / mainSize);
|
|
||||||
let rgb = hsvToRgb(h, x, 1 - y);
|
|
||||||
let alpha = colorCvs.currentColor.slice(7, 9) || "ff";
|
|
||||||
colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
|
||||||
colorCvs.currentHSV = [h, x, 1-y]
|
|
||||||
colorCvs.currentAlpha = alpha
|
|
||||||
colorCvs.draw();
|
|
||||||
} else if (colorCvs.clickedHueGradient) {
|
|
||||||
let x = clamp((mouse.x - padding) / mainSize);
|
|
||||||
let rgb = hsvToRgb(x, s, v);
|
|
||||||
let alpha = colorCvs.currentColor.slice(7, 9) || "ff";
|
|
||||||
colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
|
||||||
colorCvs.currentHSV = [x, s, v]
|
|
||||||
colorCvs.currentAlpha = alpha
|
|
||||||
colorCvs.draw();
|
|
||||||
} else if (colorCvs.clickedAlphaGradient) {
|
|
||||||
let y = clamp(1 - (mouse.y - (2 * padding + 50)) / mainSize);
|
|
||||||
let alpha = Math.round(y * 255)
|
|
||||||
.toString(16)
|
|
||||||
.padStart(2, "0");
|
|
||||||
colorCvs.currentColor = `${colorCvs.currentColor.slice(0, 7)}${alpha}`;
|
|
||||||
colorCvs.currentAlpha = alpha
|
|
||||||
colorCvs.draw();
|
|
||||||
}
|
|
||||||
colorCvs.colorEl.setColor(colorCvs.currentHSV, colorCvs.currentAlpha);
|
colorCvs.colorEl.setColor(colorCvs.currentHSV, colorCvs.currentAlpha);
|
||||||
});
|
});
|
||||||
// Get mouse coordinates relative to the viewport
|
// Get mouse coordinates relative to the viewport
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,294 @@
|
||||||
|
import { clamp, drawCheckerboardBackground, hslToRgb, hsvToRgb, rgbToHex } from "./utils.js"
|
||||||
|
|
||||||
|
class Widget {
|
||||||
|
constructor(x, y) {
|
||||||
|
this._globalEvents = new Set()
|
||||||
|
this.x = x
|
||||||
|
this.y = y
|
||||||
|
this.children = []
|
||||||
|
}
|
||||||
|
handleMouseEvent(eventType, x, y) {
|
||||||
|
for (let child of this.children) {
|
||||||
|
if (child.hitTest(x, y) || child._globalEvents.has(eventType)) {
|
||||||
|
child.handleMouseEvent(eventType, x-child.x, y-child.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const eventTypes = [
|
||||||
|
"mousedown",
|
||||||
|
"mousemove",
|
||||||
|
"mouseup",
|
||||||
|
"dblclick"
|
||||||
|
]
|
||||||
|
if (eventTypes.indexOf(eventType)!=-1) {
|
||||||
|
if (typeof(this[eventType]) == "function") {
|
||||||
|
this[eventType](x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hitTest(x, y) {
|
||||||
|
if ((x >= this.x) && (x <= this.x+this.width) &&
|
||||||
|
(y >= this.y) && (y <= this.y+this.height)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
draw(ctx) {
|
||||||
|
for (let child of this.children) {
|
||||||
|
const transform = ctx.getTransform()
|
||||||
|
ctx.translate(child.x, child.y)
|
||||||
|
child.draw(ctx)
|
||||||
|
ctx.setTransform(transform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HueSelectionBar extends Widget {
|
||||||
|
constructor(width, height, x, y, colorCvs) {
|
||||||
|
super(x, y)
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
this.colorCvs = colorCvs
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(ctx) {
|
||||||
|
const [h, s, v] = this.colorCvs.currentHSV
|
||||||
|
const hueGradient = ctx.createImageData(this.width, this.height);
|
||||||
|
const data = hueGradient.data;
|
||||||
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
|
const x = ((i / 4) % this.width) / this.width;
|
||||||
|
const y = Math.floor(i / 4 / this.height);
|
||||||
|
const rgb = hslToRgb(x, 1, 0.5);
|
||||||
|
data[i + 0] = rgb.r;
|
||||||
|
data[i + 1] = rgb.g;
|
||||||
|
data[i + 2] = rgb.b;
|
||||||
|
data[i + 3] = 255;
|
||||||
|
}
|
||||||
|
const transform = ctx.getTransform();
|
||||||
|
ctx.putImageData(hueGradient, transform.e, transform.f);
|
||||||
|
// draw pointer
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.rect(
|
||||||
|
h * this.width - 2,
|
||||||
|
0,
|
||||||
|
4,
|
||||||
|
this.height,
|
||||||
|
);
|
||||||
|
ctx.strokeStyle = "white";
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
updateColorFromMouse(x, y) {
|
||||||
|
let [h, s, v] = this.colorCvs.currentHSV
|
||||||
|
x = clamp(x / this.width);
|
||||||
|
let rgb = hsvToRgb(x, s, v);
|
||||||
|
let alpha = this.colorCvs.currentColor.slice(7, 9) || "ff";
|
||||||
|
this.colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
||||||
|
this.colorCvs.currentHSV = [x, s, v]
|
||||||
|
this.colorCvs.currentAlpha = alpha
|
||||||
|
}
|
||||||
|
mousedown(x, y) {
|
||||||
|
this._globalEvents.add("mousemove")
|
||||||
|
this._globalEvents.add("mouseup")
|
||||||
|
|
||||||
|
this.updateColorFromMouse(x, y)
|
||||||
|
this.clicked = true;
|
||||||
|
}
|
||||||
|
mousemove(x, y) {
|
||||||
|
if (this.clicked) {
|
||||||
|
this.updateColorFromMouse(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mouseup(x, y) {
|
||||||
|
this._globalEvents.delete("mousemove")
|
||||||
|
this._globalEvents.delete("mouseup")
|
||||||
|
this.clicked = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SaturationValueSelectionGradient extends Widget {
|
||||||
|
constructor(width, height, x, y, colorCvs) {
|
||||||
|
super(x, y)
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
this.colorCvs = colorCvs
|
||||||
|
}
|
||||||
|
draw(ctx) {
|
||||||
|
let mainGradient = ctx.createImageData(this.width, this.height);
|
||||||
|
let data = mainGradient.data;
|
||||||
|
// let { h, s, v } = hexToHsv(colorCvs.currentColor);
|
||||||
|
let [h, s, v] = this.colorCvs.currentHSV
|
||||||
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
|
let x = ((i / 4) % this.width) / this.width;
|
||||||
|
let y = Math.floor(i / 4 / this.height) / this.height;
|
||||||
|
let hue = h;
|
||||||
|
let rgb = hsvToRgb(hue, x, 1 - y);
|
||||||
|
data[i + 0] = rgb.r;
|
||||||
|
data[i + 1] = rgb.g;
|
||||||
|
data[i + 2] = rgb.b;
|
||||||
|
data[i + 3] = 255;
|
||||||
|
}
|
||||||
|
const transform = ctx.getTransform();
|
||||||
|
ctx.putImageData(mainGradient, transform.e, transform.f);
|
||||||
|
// draw pointer
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(
|
||||||
|
s * this.width,
|
||||||
|
(1 - v) * this.height,
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
2 * Math.PI,
|
||||||
|
);
|
||||||
|
ctx.strokeStyle = "white";
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
updateColorFromMouse(x, y) {
|
||||||
|
const [h, s, v] = this.colorCvs.currentHSV
|
||||||
|
const _x = clamp(x / this.width);
|
||||||
|
const _y = clamp(y / this.height);
|
||||||
|
const rgb = hsvToRgb(h, _x, 1 - _y);
|
||||||
|
const alpha = this.colorCvs.currentColor.slice(7, 9) || "ff";
|
||||||
|
this.colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
||||||
|
this.colorCvs.currentHSV = [h, _x, 1 - _y]
|
||||||
|
this.colorCvs.currentAlpha = alpha
|
||||||
|
}
|
||||||
|
|
||||||
|
mousedown(x, y) {
|
||||||
|
this._globalEvents.add("mousemove")
|
||||||
|
this._globalEvents.add("mouseup")
|
||||||
|
this.updateColorFromMouse(x, y)
|
||||||
|
this.clicked = true;
|
||||||
|
}
|
||||||
|
mousemove(x, y) {
|
||||||
|
if (this.clicked) {
|
||||||
|
this.updateColorFromMouse(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mouseup(x, y) {
|
||||||
|
this._globalEvents.delete("mousemove")
|
||||||
|
this._globalEvents.delete("mouseup")
|
||||||
|
this.clicked = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlphaSelectionBar extends Widget {
|
||||||
|
constructor(width, height, x, y, colorCvs) {
|
||||||
|
super(x, y)
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
this.colorCvs = colorCvs
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(ctx) {
|
||||||
|
drawCheckerboardBackground(ctx, 0, 0, this.width, this.height, 10);
|
||||||
|
// Vertical gradient
|
||||||
|
const gradient = ctx.createLinearGradient( 0, 0, 0, this.height);
|
||||||
|
gradient.addColorStop(0, `${this.colorCvs.currentColor.slice(0, 7)}ff`); // Full color at the top
|
||||||
|
gradient.addColorStop(1, `${this.colorCvs.currentColor.slice(0, 7)}00`);
|
||||||
|
ctx.fillStyle = gradient;
|
||||||
|
ctx.fillRect(0, 0, this.width, this.height);
|
||||||
|
let alpha =
|
||||||
|
parseInt(this.colorCvs.currentColor.slice(7, 9) || "ff", 16) / 255;
|
||||||
|
// draw pointer
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.rect(0, (1 - alpha) * this.height - 2, this.width, 4);
|
||||||
|
ctx.strokeStyle = "white";
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
updateColorFromMouse(x, y) {
|
||||||
|
y = 1 - y / this.height;
|
||||||
|
const alpha = Math.round(clamp(y) * 255).toString(16);
|
||||||
|
this.colorCvs.currentColor = `${this.colorCvs.currentColor.slice(0, 7)}${alpha}`;
|
||||||
|
this.colorCvs.currentAlpha = alpha
|
||||||
|
}
|
||||||
|
mousedown(x, y) {
|
||||||
|
this._globalEvents.add("mousemove")
|
||||||
|
this._globalEvents.add("mouseup")
|
||||||
|
this.updateColorFromMouse(x, y)
|
||||||
|
this.clicked = true;
|
||||||
|
}
|
||||||
|
mousemove(x, y) {
|
||||||
|
if (this.clicked) {
|
||||||
|
this.updateColorFromMouse(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mouseup(x, y) {
|
||||||
|
this._globalEvents.delete("mousemove")
|
||||||
|
this._globalEvents.delete("mouseup")
|
||||||
|
this.clicked = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColorWidget extends Widget {
|
||||||
|
constructor(width, height, x, y, colorCvs) {
|
||||||
|
super(x, y)
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
this.colorCvs = colorCvs
|
||||||
|
}
|
||||||
|
draw(ctx) {
|
||||||
|
drawCheckerboardBackground(ctx, 0, 0, this.width, this.height, 10);
|
||||||
|
ctx.fillStyle = this.colorCvs.currentColor;
|
||||||
|
ctx.fillRect(0, 0, this.width, this.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColorSelectorWidget extends Widget {
|
||||||
|
constructor(x, y, colorCvs) {
|
||||||
|
super(x, y)
|
||||||
|
this.colorCvs = colorCvs
|
||||||
|
const padding = 10;
|
||||||
|
const gradwidth = 25;
|
||||||
|
const ccwidth = 300;
|
||||||
|
const mainSize = ccwidth - (3 * padding + gradwidth);
|
||||||
|
this.children = [
|
||||||
|
new ColorWidget(
|
||||||
|
colorCvs.width - 2 * padding,
|
||||||
|
50,
|
||||||
|
padding,
|
||||||
|
padding,
|
||||||
|
colorCvs
|
||||||
|
),
|
||||||
|
new HueSelectionBar(
|
||||||
|
mainSize,
|
||||||
|
gradwidth,
|
||||||
|
padding,
|
||||||
|
3 * padding + 50 + mainSize, colorCvs
|
||||||
|
),
|
||||||
|
new SaturationValueSelectionGradient(
|
||||||
|
mainSize,
|
||||||
|
mainSize,
|
||||||
|
padding,
|
||||||
|
2 * padding + 50,
|
||||||
|
colorCvs
|
||||||
|
),
|
||||||
|
new AlphaSelectionBar(
|
||||||
|
gradwidth,
|
||||||
|
mainSize,
|
||||||
|
colorCvs.width - (padding + gradwidth),
|
||||||
|
2 * padding + 50,
|
||||||
|
colorCvs
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
draw(ctx) {
|
||||||
|
const darkMode =
|
||||||
|
window.matchMedia &&
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
if (darkMode) {
|
||||||
|
ctx.fillStyle = "#333";
|
||||||
|
} else {
|
||||||
|
ctx.fillStyle = "#ccc"; //TODO
|
||||||
|
}
|
||||||
|
ctx.fillRect(0, 0, this.colorCvs.width, this.colorCvs.height);
|
||||||
|
super.draw(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Widget,
|
||||||
|
HueSelectionBar,
|
||||||
|
SaturationValueSelectionGradient,
|
||||||
|
AlphaSelectionBar,
|
||||||
|
ColorWidget,
|
||||||
|
ColorSelectorWidget
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue