form.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. const selectors = {
  2. get sortControl() {
  3. return document.forms.sortControl.elements;
  4. },
  5. get clusterControl() {
  6. return document.forms.clusterControl.elements;
  7. },
  8. get colorSpace() {
  9. return selectors.sortControl.colorSpace.value;
  10. },
  11. get useClusters() {
  12. return selectors.sortControl.useClusters.value;
  13. },
  14. };
  15. const onMetricChange = (elements, skipUpdates = false) => {
  16. elements.sortOrderLabel.value = elements.sortOrder.checked
  17. ? "Maximizing"
  18. : "Minimizing";
  19. const kind = elements.metricKind.value;
  20. elements.whole.disabled = kind !== "whole";
  21. elements.mean.disabled = kind !== "mean";
  22. elements.statistic.disabled = kind !== "statistic";
  23. elements.sortMetric.value = elements[kind].value;
  24. if (!skipUpdates) {
  25. updateSort();
  26. showResults(selectors.sortControl.resultsToDisplay.value);
  27. }
  28. };
  29. const onColorChange = (inputValue, skipUpdates = false) => {
  30. console.log(inputValue);
  31. const colorInput = "#" + (inputValue?.replace("#", "") ?? "FFFFFF");
  32. if (colorInput.length !== 7) {
  33. return;
  34. }
  35. const rgb = d3.color(colorInput);
  36. if (!rgb) {
  37. return;
  38. }
  39. const refomatted = rgb.formatHex();
  40. selectors.sortControl.colorText.value = refomatted;
  41. selectors.sortControl.colorPicker.value = refomatted;
  42. // TODO last color saver
  43. // TODO bg + text color change
  44. if (!skipUpdates) {
  45. updateScores(rgb);
  46. updateSort();
  47. showResults(selectors.sortControl.resultsToDisplay.value);
  48. }
  49. };
  50. const calcScores = (data, target) => {
  51. const sigma = Math.sqrt(
  52. data.inertia - 2 * vectorDot(data.mu.vector, target.vector) + target.sqMag
  53. );
  54. const theta = rad2deg * Math.acos(vectorDot(data.mu.unit, target.unit));
  55. const rawPhi = Math.abs(data.mu.hue - target.hue);
  56. return {
  57. sigma,
  58. bigTheta: 1 - vectorDot(data.nu, target.unit),
  59. alpha: sigma * Math.pow(bigTheta, target.chroma + target.lightness),
  60. theta,
  61. phi: Math.min(rawPhi, 360 - rawPhi),
  62. delta: vectorMag(data.mu.vector.map((x, i) => x - target.vector[i])),
  63. manhattan: data.mu.vector
  64. .map((x, i) => Math.abs(x - target.vector[i]))
  65. .reduce((x, y) => x + y),
  66. ch: Math.max(...data.mu.vector.map((x, i) => Math.abs(x - target.vector[i]))),
  67. lightnessDiff: Math.abs(data.mu.lightness - target.lightness),
  68. inertia: data.inertia,
  69. variance: data.inertia - data.mu.sqMag,
  70. muNuAngle: data.muNuAngle,
  71. size: data.size,
  72. lightness: data.mu.lightness,
  73. chroma: data.mu.chroma,
  74. importance: data.importance,
  75. };
  76. };
  77. const currentScores = {};
  78. const currentBestClusterIndices = {};
  79. let sortedData = pokemonData;
  80. const updateScores = (rgb) => {
  81. const { J, a, b } = d3.jab(rgb);
  82. const targetJab = buildVectorData([J, a, b], jab2hue, jab2lit, jab2chroma, jab2hex);
  83. const targetRgb = buildVectorData(
  84. [rgb.r, rgb.g, rgb.b],
  85. rgb2hue,
  86. rgb2lit,
  87. rgb2chroma,
  88. rgb2hex
  89. );
  90. pokemonData.forEach(({ name, jab, rgb }) => {
  91. currentScores[name] = {
  92. jab: {
  93. total: calcScores(jab.total, targetJab),
  94. clusters: jab.clusters.map((c) => calcScores(c, targetJab)),
  95. },
  96. rgb: {
  97. total: calcScores(rgb.total, targetRgb),
  98. clusters: rgb.clusters.map((c) => calcScores(c, targetRgb)),
  99. },
  100. };
  101. currentBestClusterIndices[name] = {
  102. // TODO
  103. jab: 0,
  104. rgb: 0,
  105. };
  106. });
  107. };
  108. const updateSort = () => {
  109. // TODO
  110. };
  111. const showResults = (resultsToDisplay) => {
  112. // TODO
  113. };
  114. window.onload = () => {
  115. const metricTemplate = document.getElementById("metric-form-template").content;
  116. selectors.sortControl.metric.appendChild(metricTemplate.cloneNode(true));
  117. selectors.sortControl.metricKind.value = "whole";
  118. selectors.sortControl.whole.value = "alpha";
  119. onMetricChange(selectors.sortControl, true);
  120. selectors.clusterControl.metric.appendChild(metricTemplate.cloneNode(true));
  121. selectors.clusterControl.sortOrder.checked = true;
  122. selectors.clusterControl.metricKind.value = "statistic";
  123. selectors.clusterControl.statistic.value = "importance";
  124. onMetricChange(selectors.clusterControl, true);
  125. const scaleTemplate = document.getElementById("scale-form-template").content;
  126. selectors.sortControl.rescaleSection.appendChild(scaleTemplate.cloneNode(true));
  127. selectors.sortControl.rescaleFactor.value = "none";
  128. selectors.clusterControl.rescaleSection.appendChild(scaleTemplate.cloneNode(true));
  129. selectors.clusterControl.rescaleFactor.value = "inverse";
  130. };