ソースを参照

Add math to web page

Kirk Trombley 3 年 前
コミット
836e71192d
3 ファイル変更185 行追加70 行削除
  1. 12 0
      nearest.css
  2. 154 64
      nearest.html
  3. 19 6
      nearest.js

+ 12 - 0
nearest.css

@@ -1,6 +1,7 @@
 body {
     width: 100vw;
     padding-top: 4px;
+    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
 }
 
 .container {
@@ -20,6 +21,17 @@ body {
     align-items: flex-start;
 }
 
+.center-aligned {
+    align-items: center;
+}
+
+#obj-fn {
+    display: inline-flex;
+    flex-flow: column nowrap;
+    justify-content: center;
+    min-height: 64px;
+}
+
 .padded {
     padding-left: 16px;
     padding-right: 16px;

+ 154 - 64
nearest.html

@@ -1,77 +1,167 @@
 <!DOCTYPE html>
 <html lang="en">
-    <head>
-        <meta charset="utf-8" />
-        <title>Pokemon By Color</title>
-        <link rel="stylesheet" href="nearest.css">
-        <script src="https://unpkg.com/d3-color@3.0.1/dist/d3-color.min.js"></script>
-        <script src="https://unpkg.com/d3-cam02@0.1.5/build/d3-cam02.min.js"></script>
-        <script src="https://unpkg.com/fuse.js@6.5.3/dist/fuse.js"></script>
-        <script src="database.js"></script>
-        <script src="nearest.js"></script>
-        <script lang="javascript">window.onload = () => { onUpdate(); }</script>
-    </head>
-    <body>
-        <noscript>Requires javascript</noscript>    
-        <div class="container">
-            <div id="left-panel" class="padded panel">
+
+<head>
+    <meta charset="utf-8" />
+    <title>Pokemon By Color</title>
+    <link rel="stylesheet" href="nearest.css">
+    <script src="https://unpkg.com/d3-color@3.0.1/dist/d3-color.min.js"></script>
+    <script src="https://unpkg.com/d3-cam02@0.1.5/build/d3-cam02.min.js"></script>
+    <script src="https://unpkg.com/fuse.js@6.5.3/dist/fuse.min.js"></script>
+    <script src="https://unpkg.com/texzilla@1.0.2/TeXZilla.js"></script>
+    <script src="database.js"></script>
+    <script src="nearest.js"></script>
+    <script lang="javascript">window.onload = () => { onUpdate(); }</script>
+</head>
+
+<body>
+    <noscript>Requires javascript</noscript>
+    <div class="container">
+        <div id="left-panel" class="padded panel">
+            <div class="container center-aligned">
                 <div>
-                    Minimizing:
-                    <span id="x-term">X(P)</span>
-                    <span>-</span>
-                    <span id="c-value">2</span>
-                    <span id="q-vec">q</span>
-                    <span>·</span>
-                    <span id="y-vec">Y(P)</span>
+                    <math xmlns="http://www.w3.org/1998/Math/MathML">
+                        <semantics>
+                            <mrow>
+                                <mi>X</mi>
+                                <mrow>
+                                    <mo>(</mo>
+                                    <mi>P</mi>
+                                    <mo>)</mo>
+                                </mrow>
+                                <mo>=</mo>
+                                <mfrac>
+                                    <mn>1</mn>
+                                    <mrow>
+                                        <mo>|</mo>
+                                        <mi>P</mi>
+                                        <mo>|</mo>
+                                    </mrow>
+                                </mfrac>
+                                <munder>
+                                    <mo>∑</mo>
+                                    <mrow>
+                                        <mi>p</mi>
+                                        <mo>∊</mo>
+                                        <mi>P</mi>
+                                    </mrow>
+                                </munder>
+                                <msup>
+                                    <mrow>
+                                        <mo>|</mo>
+                                        <mrow>
+                                            <mo>|</mo>
+                                            <mover>
+                                                <mi>p</mi>
+                                                <mo stretchy="false">⇀</mo>
+                                            </mover>
+                                            <mo>|</mo>
+                                        </mrow>
+                                        <mo>|</mo>
+                                    </mrow>
+                                    <mn>2</mn>
+                                </msup>
+                            </mrow>
+                            <annotation encoding="TeX">X\\left(P\\right) = \\frac{1}{\\left|P\\right|}\\sum_{p\\in
+                                P}{\\left|\\left|\\vec{p}\\right|\\right|^2}</annotation>
+                        </semantics>
+                    </math>
+                </div>
+                <div>
+                    <math xmlns="http://www.w3.org/1998/Math/MathML">
+                        <semantics>
+                            <mrow>
+                                <mover>
+                                    <mi>Y</mi>
+                                    <mo stretchy="false">⇀</mo>
+                                </mover>
+                                <mrow>
+                                    <mo>(</mo>
+                                    <mi>P</mi>
+                                    <mo>)</mo>
+                                </mrow>
+                                <mo>=</mo>
+                                <mfrac>
+                                    <mn>1</mn>
+                                    <mrow>
+                                        <mo>|</mo>
+                                        <mi>P</mi>
+                                        <mo>|</mo>
+                                    </mrow>
+                                </mfrac>
+                                <munder>
+                                    <mo>∑</mo>
+                                    <mrow>
+                                        <mi>p</mi>
+                                        <mo>∊</mo>
+                                        <mi>P</mi>
+                                    </mrow>
+                                </munder>
+                                <mover>
+                                    <mi>p</mi>
+                                    <mo stretchy="false">⇀</mo>
+                                </mover>
+                            </mrow>
+                            <annotation encoding="TeX">Y\\left(P\\right) = \\frac{1}{\\left|P\\right|}\\sum_{p\\in
+                                P}{\\vec{p}}</annotation>
+                        </semantics>
+                    </math>
+                </div>
+            </div>
+            <div class="container center-aligned">
+                Minimizing: <span id="obj-fn">X(P) - 2q&sdot;Y(P)</span>
+            </div>
+            <form class="panel" onsubmit="onUpdate(event)">
+                <div class="container control">
+                    <label for="include-x">Include X:</label>
+                    <input type="checkbox" checked oninput="onUpdate()" id="include-x">
                 </div>
-                <form class="panel" onsubmit="onUpdate(event)">
-                    <div class="container control">
-                        <label for="include-x">Include X:</label>
-                        <input type="checkbox" checked oninput="onUpdate()" id="include-x">
-                    </div>
-                    
-                    <div class="container control">
-                        <label for="norm-q-y">Normalize q and Y:</label>
-                        <input type="checkbox" oninput="onUpdate()" id="norm-q-y">
-                    </div>
-                    
-                    <div class="container control">
-                        <label for="close-coeff">Closeness coefficient: <span id="close-coeff-display">2</span></label>
-                        <input type="range" min="0" max="10" value="2" step="0.1" oninput="onUpdate()" id="close-coeff">                
-                    </div>
 
-                    <div class="container control">
-                        <div>Color Space: <span id="color-space">CAM02-UCS</span></div>
-                        <button id="space-toggle" type="button" onclick="onToggleSpace()">Swap to RGB</button>
-                    </div>
-                </form>
+                <div class="container control">
+                    <label for="norm-q-y">Normalize q and Y:</label>
+                    <input type="checkbox" oninput="onUpdate()" id="norm-q-y">
+                </div>
 
-                <div class="panel bypkmn">
-                    <form class="container control" onsubmit="onUpdate(event)">
-                        <label for="pokemon-name">Search By Pokemon</label>
-                        <input id="pokemon-name" size="15" oninput="onUpdate()">
-                    </form>
-                    <ul id="search-list" class="pkmn-list"></ul>
+                <div class="container control">
+                    <label for="close-coeff">Closeness coefficient: <span id="close-coeff-display">2</span></label>
+                    <input type="range" min="0" max="10" value="2" step="0.1" oninput="onUpdate()" id="close-coeff">
                 </div>
-            </div>
-            <div class="padded panel bycolor">
-                <div>
-                    Search By Color - click random, or enter six digit hex code (optional #)
+
+                <div class="container control">
+                    <div>Color Space: <span id="color-space">CAM02-UCS</span></div>
+                    <button id="space-toggle" type="button" onclick="onToggleSpace()">Swap to RGB</button>
                 </div>
-                <form class="panel" onsubmit="onUpdate(event)">
-                    <div class="container bycolor_l1">
-                        <button class="padded" type="button" onclick="onRandomColor()">Random color</button>
-                        <input class="margined" size="7" maxlength="7" id="color-input" oninput="onUpdate()" value="#ffffff" />
-                        <img src="https://img.pokemondb.net/sprites/sword-shield/icon/bulbasaur.png" />
-                    </div>
+            </form>
 
-                    <div class="container bycolor_l2">
-                        <label for="num-poke" style="min-width: 200px;">Number to find: <span id="num-poke-display">10</span></label>
-                        <input type="range" min="1" max="100" value="10" oninput="onUpdate()" id="num-poke">
-                    </div>
+            <div class="panel bypkmn">
+                <form class="container control" onsubmit="onUpdate(event)">
+                    <label for="pokemon-name">Search By Pokemon</label>
+                    <input id="pokemon-name" size="15" oninput="onUpdate()">
                 </form>
-                <ul id="best-list" class="pkmn-list"></ul>
+                <ul id="search-list" class="pkmn-list"></ul>
             </div>
         </div>
-    </body>
+        <div class="padded panel bycolor">
+            <div>
+                Search By Color - click random, or enter six digit hex code (optional #)
+            </div>
+            <form class="panel" onsubmit="onUpdate(event)">
+                <div class="container bycolor_l1">
+                    <button class="padded" type="button" onclick="onRandomColor()">Random color</button>
+                    <input class="margined" size="7" maxlength="7" id="color-input" oninput="onUpdate()"
+                        value="#ffffff" />
+                    <img src="https://img.pokemondb.net/sprites/sword-shield/icon/bulbasaur.png" />
+                </div>
+
+                <div class="container bycolor_l2">
+                    <label for="num-poke" style="min-width: 200px;">Number to find: <span
+                            id="num-poke-display">10</span></label>
+                    <input type="range" min="1" max="100" value="10" oninput="onUpdate()" id="num-poke">
+                </div>
+            </form>
+            <ul id="best-list" class="pkmn-list"></ul>
+        </div>
+    </div>
+</body>
+
 </html>

+ 19 - 6
nearest.js

@@ -76,6 +76,16 @@ const paramsChanged = (...args) => {
   return old === null || old.filter((p, i) => p !== args[i]).length > 0
 }
 
+const renderVec = math => `\\vec{${math.charAt(0)}}${math.substr(1)}`;
+
+const renderNorm = vec => `\\frac{${vec}}{\\left|\\left|${vec}\\right|\\right|}`;
+
+const renderMath = (includeX, normQY) => {
+  const xTerm = includeX ? "X\\left(P\\right)" : "";
+  const qyMod = normQY ? c => renderNorm(renderVec(c)) : renderVec;
+  return TeXZilla.toMathML(`${xTerm}-2${qyMod("q")}\\cdot ${qyMod("Y\\left(P\\right)")}`);
+}
+
 const onUpdate = (event) => {
   if (event) {
     event.preventDefault();
@@ -92,12 +102,15 @@ const onUpdate = (event) => {
   const targetRGB = hex2rgb(targetColor);
 
   // Update display values
-  document.getElementById("x-term").textContent = includeX ? "X(P)" : "";
-  document.getElementById("c-value").textContent = closeCoeff;
-  document.getElementById("q-vec").textContent = normQY ? "q̂" : "q";
-  document.getElementById("y-vec").textContent = normQY ? "Ŷ(P)" : "Y(P)";
-  document.getElementById("close-coeff-display").innerHTML = closeCoeff;
-  document.getElementById("num-poke-display").textContent = numPoke;
+  // document.getElementById("x-term").textContent = includeX ? "X(P)" : "";
+  // document.getElementById("c-value").textContent = closeCoeff;
+  // document.getElementById("q-vec").innerHTML = normQY ? "<mover><m" : "q";
+  // document.getElementById("y-vec").textContent = normQY ? "Ŷ(P)" : "Y(P)";
+  // document.getElementById("close-coeff-display").innerHTML = closeCoeff;
+  // document.getElementById("num-poke-display").textContent = numPoke;
+  const objFnElem = document.getElementById("obj-fn");
+  objFnElem.innerHTML = "";
+  objFnElem.appendChild(renderMath(includeX, normQY));
   
   // determine metrics from configuration
   const targetInSpace = useRGB ? targetRGB : rgb2jab(targetRGB);