123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- const selectors = {
- get sortControl() {
- return document.forms.sortControl.elements;
- },
- get clusterControl() {
- return document.forms.clusterControl.elements;
- },
- get colorSpace() {
- return selectors.sortControl.colorSpace.value;
- },
- get useClusters() {
- return selectors.sortControl.useClusters.value;
- },
- get prevColors() {
- return document.getElementById("prev-colors");
- },
- set background(hex) {
- document.querySelector(":root").style.setProperty("--background", hex);
- },
- set highlight(hex) {
- document.querySelector(":root").style.setProperty("--highlight", hex);
- },
- };
- const onMetricChange = (elements, skipUpdates = false) => {
- elements.sortOrderLabel.value = elements.sortOrder.checked
- ? "Maximizing"
- : "Minimizing";
- const kind = elements.metricKind.value;
- elements.whole.disabled = kind !== "whole";
- elements.mean.disabled = kind !== "mean";
- elements.statistic.disabled = kind !== "statistic";
- elements.sortMetric.value = elements[kind].value;
- if (!skipUpdates) {
- updateSort();
- showResults(selectors.sortControl.resultsToDisplay.value);
- }
- };
- const onColorChange = (inputValue, skipUpdates = false) => {
- const colorInput = "#" + (inputValue?.replace("#", "") ?? "FFFFFF");
- if (colorInput.length !== 7) {
- return;
- }
- const rgb = d3.color(colorInput);
- if (!rgb) {
- return;
- }
- const hex = rgb.formatHex();
- selectors.sortControl.colorText.value = hex;
- selectors.sortControl.colorPicker.value = hex;
- const contrast = getContrastingTextColor(hex);
- const newColor = document.createElement("div");
- newColor.innerHTML = hex;
- newColor.style = `
- color: ${contrast};
- background-color: ${hex};
- `;
- selectors.prevColors.prepend(newColor);
- selectors.background = hex;
- selectors.highlight = contrast;
- if (!skipUpdates) {
- updateScores(rgb);
- updateSort();
- showResults(selectors.sortControl.resultsToDisplay.value);
- }
- };
- const randomColor = () =>
- d3.hsl(Math.random() * 360, Math.random(), Math.random()).formatHex();
- const calcScores = (data, target) => {
- const sigma = Math.sqrt(
- data.inertia - 2 * vectorDot(data.mu.vector, target.vector) + target.sqMag
- );
- const theta = rad2deg * Math.acos(vectorDot(data.mu.unit, target.unit));
- const rawPhi = Math.abs(data.mu.hue - target.hue);
- return {
- sigma,
- bigTheta: 1 - vectorDot(data.nu, target.unit),
- alpha: sigma * Math.pow(bigTheta, target.chroma + target.lightness),
- theta,
- phi: Math.min(rawPhi, 360 - rawPhi),
- delta: vectorMag(data.mu.vector.map((x, i) => x - target.vector[i])),
- manhattan: data.mu.vector
- .map((x, i) => Math.abs(x - target.vector[i]))
- .reduce((x, y) => x + y),
- ch: Math.max(...data.mu.vector.map((x, i) => Math.abs(x - target.vector[i]))),
- lightnessDiff: Math.abs(data.mu.lightness - target.lightness),
- inertia: data.inertia,
- variance: data.inertia - data.mu.sqMag,
- muNuAngle: data.muNuAngle,
- size: data.size,
- lightness: data.mu.lightness,
- chroma: data.mu.chroma,
- importance: data.importance,
- };
- };
- const currentScores = {};
- const currentBestClusterIndices = {};
- let sortedData = pokemonData;
- const updateScores = (rgb) => {
- const { J, a, b } = d3.jab(rgb);
- const targetJab = buildVectorData([J, a, b], jab2hue, jab2lit, jab2chroma, jab2hex);
- const targetRgb = buildVectorData(
- [rgb.r, rgb.g, rgb.b],
- rgb2hue,
- rgb2lit,
- rgb2chroma,
- rgb2hex
- );
- pokemonData.forEach(({ name, jab, rgb }) => {
- currentScores[name] = {
- jab: {
- total: calcScores(jab.total, targetJab),
- clusters: jab.clusters.map((c) => calcScores(c, targetJab)),
- },
- rgb: {
- total: calcScores(rgb.total, targetRgb),
- clusters: rgb.clusters.map((c) => calcScores(c, targetRgb)),
- },
- };
- });
- };
- const updateSort = () => {
- pokemonData.forEach(({ name, jab, rgb }) => {
- currentBestClusterIndices[name] = {
- // TODO
- jab: 0,
- rgb: 0,
- };
- });
- // TODO
- };
- const showResults = (resultsToDisplay) => {
- // TODO
- };
- window.addEventListener("load", () => {
- const metricTemplate = document.getElementById("metric-form-template").content;
- selectors.sortControl.metric.appendChild(metricTemplate.cloneNode(true));
- selectors.sortControl.metricKind.value = "whole";
- selectors.sortControl.whole.value = "alpha";
- onMetricChange(selectors.sortControl, true);
- selectors.clusterControl.metric.appendChild(metricTemplate.cloneNode(true));
- selectors.clusterControl.sortOrder.checked = true;
- selectors.clusterControl.metricKind.value = "statistic";
- selectors.clusterControl.statistic.value = "importance";
- onMetricChange(selectors.clusterControl, true);
- const scaleTemplate = document.getElementById("scale-form-template").content;
- selectors.sortControl.rescaleSection.appendChild(scaleTemplate.cloneNode(true));
- selectors.sortControl.rescaleFactor.value = "none";
- selectors.clusterControl.rescaleSection.appendChild(scaleTemplate.cloneNode(true));
- selectors.clusterControl.rescaleFactor.value = "inverse";
- });
|