changeset 1609:0bb3051fd6fd

move colorpick to its own file Ignore-this: 1e6572cf19a17c861e22ed1789206c39
author Drew Perttula <drewp@bigasterisk.com>
date Mon, 05 Jun 2017 08:28:50 +0000
parents faa62d5e84d8
children b0846845c772
files light9/web/light9-color-picker.html light9/web/live/index.html
diffstat 2 files changed, 223 insertions(+), 225 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/light9/web/light9-color-picker.html	Mon Jun 05 08:28:50 2017 +0000
@@ -0,0 +1,222 @@
+<link rel="import" href="/lib/polymer/polymer.html">
+
+<dom-module id="light9-color-picker">
+  <template>
+    <style>
+     :host {
+         position: relative;
+     }
+     #smallRainbowComp, #largeRainbowComp {
+         display: inline-block;
+         overflow: hidden;
+         position: relative;
+     }
+     #smallRainbow {
+         background: url(/colorpick_rainbow_small.png);
+         width: 150px; 
+         height: 30px;
+     }
+     #largeRainbow {
+         background: url(/colorpick_rainbow_large.png);
+         width: 400px; 
+         height: 200px;
+     }
+     #smallCrosshair, #largeCrosshair {
+         position: absolute;
+         left: -60px;
+         top: -62px;
+         pointer-events: none;
+     }
+     #smallCrosshair {
+         background: url(/colorpick_crosshair_small.svg);
+         /* this can't be too tall, or chrome will cull it in the 
+            second column if its top goes above the top of the columns */
+         width: 400px; 
+         height: 60px;
+     }
+     #largeCrosshair {
+         background: url(/colorpick_crosshair_large.svg);
+         width: 1000px; 
+         height: 1000px;
+     }
+     #largeRainbowComp {
+         display: none;
+         position: absolute;
+         border: 4px solid #545454;
+         box-shadow: 8px 11px 40px 0px rgba(0, 0, 0, 0.74);
+         z-index: 10;
+         left: -50px;
+         top: -110px;
+     }
+    </style>
+    <div id="smallRainbowComp">
+      <div id="smallRainbow" on-mouseenter="onEnterSmall"></div>
+      <div id="smallCrosshair"></div>
+    </div>
+    <div id="largeRainbowComp">
+      <div id="largeRainbow"
+           on-mousemove="onCanvasMove"
+           on-mouseup="hideLarge"
+           on-mouseleave="hideLarge"></div>
+      <div id="largeCrosshair"></div>
+    </div>
+  </template>
+  <script>
+   class RainbowCanvas {
+       constructor(url, size) {
+           this.size = size;
+           var elem = document.createElement('canvas');
+           elem.width = size[0];
+           elem.height = size[1];
+
+           this.ctx = elem.getContext('2d');
+
+           this.colorPos = {} // color: pos
+           
+           var img = new Image();
+           img.onload = function() {
+               this.ctx.drawImage(img, 0, 0);
+               this._readImage();
+           }.bind(this);
+           img.src = url;
+       }
+       _readImage() {
+           var data = this.ctx.getImageData(
+               0, 0, this.size[0], this.size[1]).data;
+           for (var y = 0; y < this.size[1]; y+=1) {
+               for (var x = 0; x < this.size[0]; x+=1) {
+                   var base = (y * this.size[0] + x) * 4;
+                   var c = this._hexFromRgb(
+                       data[base + 0], data[base + 1], data[base + 2]);
+                   this.colorPos[c] = [x, y];
+               }
+           }
+       }
+       _hexFromRgb(r, g, b) {
+           var hex = function (x) {
+               return ('00' + x.toString(16)).slice(-2);
+           };
+           return '#' + hex(r) + hex(g) + hex(b);
+       }
+       colorAt(pos) {
+           var data = this.ctx.getImageData(pos[0], pos[1], 1, 1).data;
+           return this._hexFromRgb(data[0], data[1], data[2]);
+       }
+       _fullBrightness(r, g, b) {
+           var high = Math.max(r, g, b);
+           if (high == 0) {
+               return [0, 0, 0];
+           }
+           return [Math.floor(255 * r / high),
+                   Math.floor(255 * g / high),
+                   Math.floor(255 * b / high)];
+       }
+       posFor(color) {
+           let r = parseInt(color.substr(1, 2), 16),
+               g = parseInt(color.substr(3, 2), 16),
+               b = parseInt(color.substr(5, 2), 16);
+
+           let bright = this._fullBrightness(r, g, b);
+           r = bright[0]; g = bright[1]; b = bright[2];
+           
+           // We may not have a match for this color exactly (e.g. on
+           // the small image), so we have to search for a near one.
+           
+           // 0, 1, -1, 2, -2, ...
+           let walk = function(x) { return -x + (x > 0 ? 0 : 1); }
+           
+           var radius = 8;
+           for (var dr = 0; dr < radius; dr = walk(dr)) {
+               for (var dg = 0; dg < radius; dg = walk(dg)) {
+                   for (var db = 0; db < radius; db = walk(db)) {
+                       // Don't need bounds check- out of range
+                       // corrupt colors just won't match.
+                       color = this._hexFromRgb(r + dr, g + dg, b + db);
+                       var pos = this.colorPos[color];
+                       if (pos !== undefined) {
+                           return pos;
+                       }
+                   }
+               }
+           }
+           throw new Error('no match');
+       }
+   }
+   
+   Polymer({
+       is: "light9-color-picker",
+       properties: {
+           value: { type: String, notify: true },
+       },
+       observers: ['updateSmall(value)'],
+       attached: function() {
+           if (!window.pickerCanvases) {
+               window.pickerCanvases = {
+                   large: new RainbowCanvas(
+                       '/colorpick_rainbow_large.png', [400, 200]),
+                   small: new RainbowCanvas(
+                       '/colorpick_rainbow_small.png', [150, 30]),
+               };
+           }
+           this.large = window.pickerCanvases.large;
+           this.small = window.pickerCanvases.small;
+       },
+       updateSmall: function(value) {
+           try {
+               var pos = this.small.posFor(value);
+           } catch(e) {
+               this.moveSmallCrosshair([-999, -999]);
+               return;
+           }
+           this.moveSmallCrosshair(pos);
+       },
+       _floatLarge: function() {
+           // Large might span multiple columns, and chrome won't
+           // send events for those parts. Workaround: take it out of
+           // the columns.
+           let large = this.$.largeRainbowComp;
+           let rect = this.$.smallRainbowComp.getBoundingClientRect();
+           document.body.append(large);
+           large.style.position = 'fixed';
+           large.style.left = (rect.left - 100) + 'px';
+           large.style.top = (rect.top - 50) + 'px';
+       },
+       showLarge: function() {
+           this._floatLarge();
+           this.$.largeRainbowComp.style.display = 'block';
+           try {
+               this.moveLargeCrosshair(this.large.posFor(this.value));
+           } catch(e) {
+               this.moveLargeCrosshair([-999, -999]);
+               return;
+           }
+       },
+       hideLarge: function() {
+           this.$.largeRainbowComp.style.display = 'none';
+       },
+       onEnterSmall: function() {
+           // not if we just closed the large one
+           this.showLarge();
+       },
+       moveLargeCrosshair: function(pos, _elem) {
+           _elem = _elem || this.$.largeCrosshair;
+           _elem.style.left = (pos[0] - _elem.offsetWidth / 2) + 'px';
+           _elem.style.top = (pos[1] - _elem.offsetHeight / 2) + 'px';
+       },
+       moveSmallCrosshair: function(pos) {
+           this.moveLargeCrosshair(pos, this.$.smallCrosshair);
+       },
+       onCanvasMove: function(ev) {
+           if (ev.buttons != 1) {
+               return;
+           }
+           var canvas = this.$.largeRainbow;
+           var pos = [ev.offsetX - canvas.offsetLeft,
+                      ev.offsetY - canvas.offsetTop];
+           this.moveLargeCrosshair(pos);
+           this.value = this.large.colorAt(pos);
+       },
+   });
+  </script>
+</dom-module>
+
--- a/light9/web/live/index.html	Mon Jun 05 08:25:28 2017 +0000
+++ b/light9/web/live/index.html	Mon Jun 05 08:28:50 2017 +0000
@@ -16,234 +16,10 @@
     <script src="/lib/underscore/underscore-min.js"></script>
     <link rel="import" href="../rdfdb-synced-graph.html">
     <link rel="import" href="/resource-display.html">
+    <link rel="import" href="/light9-color-picker.html">
   </head>
   <body>
 
-    <dom-module id="light9-color-picker">
-      <template>
-        <style>
-         :host {
-             position: relative;
-         }
-         #smallRainbowComp, #largeRainbowComp {
-             display: inline-block;
-             overflow: hidden;
-             position: relative;
-         }
-         #smallRainbow {
-             background: url(/colorpick_rainbow_small.png);
-             width: 150px; 
-             height: 30px;
-         }
-         #largeRainbow {
-             background: url(/colorpick_rainbow_large.png);
-             width: 400px; 
-             height: 200px;
-         }
-         #smallCrosshair, #largeCrosshair {
-             position: absolute;
-             left: -60px;
-             top: -62px;
-             pointer-events: none;
-         }
-         #smallCrosshair {
-             background: url(/colorpick_crosshair_small.svg);
-             /* this can't be too tall, or chrome will cull it in the 
-                second column if its top goes above the top of the columns */
-             width: 400px; 
-             height: 60px;
-         }
-         #largeCrosshair {
-             background: url(/colorpick_crosshair_large.svg);
-             width: 1000px; 
-             height: 1000px;
-         }
-         #largeRainbowComp {
-             display: none;
-             position: absolute;
-             border: 4px solid #545454;
-             box-shadow: 8px 11px 40px 0px rgba(0, 0, 0, 0.74);
-             z-index: 10;
-             left: -50px;
-             top: -110px;
-         }
-        </style>
-        <div id="smallRainbowComp">
-          <div id="smallRainbow" on-mouseenter="onEnterSmall"></div>
-          <div id="smallCrosshair"></div>
-        </div>
-        <div id="largeRainbowComp">
-          <div id="largeRainbow"
-                  on-mousemove="onCanvasMove"
-                  on-mouseup="hideLarge"
-                  on-mouseleave="hideLarge"></div>
-          <div id="largeCrosshair"></div>
-        </div>
-      </template>
-      <script>
-       HTMLImports.whenReady(function () {
-           class RainbowCanvas {
-               constructor(url, size) {
-                   this.size = size;
-                   var elem = document.createElement('canvas');
-                   elem.width = size[0];
-                   elem.height = size[1];
-
-                   this.ctx = elem.getContext('2d');
-
-                   this.colorPos = {} // color: pos
-                   
-                   var img = new Image();
-                   img.onload = function() {
-                       this.ctx.drawImage(img, 0, 0);
-                       this._readImage();
-                   }.bind(this);
-                   img.src = url;
-               }
-               _readImage() {
-                   var data = this.ctx.getImageData(
-                       0, 0, this.size[0], this.size[1]).data;
-                   for (var y = 0; y < this.size[1]; y+=1) {
-                       for (var x = 0; x < this.size[0]; x+=1) {
-                           var base = (y * this.size[0] + x) * 4;
-                           var c = this._hexFromRgb(data[base + 0],
-                                                    data[base + 1],
-                                                    data[base + 2]);
-                           this.colorPos[c] = [x, y];
-                       }
-                   }
-               }
-               _hexFromRgb(r, g, b) {
-                   var hex = function (x) {
-                       return ('00' + x.toString(16)).slice(-2);
-                   };
-                   return '#' + hex(r) + hex(g) + hex(b);
-               }
-               colorAt(pos) {
-                   var data = this.ctx.getImageData(pos[0], pos[1], 1, 1).data;
-                   return this._hexFromRgb(data[0], data[1], data[2]);
-               }
-               _fullBrightness(r, g, b) {
-                   var high = Math.max(r, g, b);
-                   if (high == 0) {
-                       return [0, 0, 0];
-                   }
-                   return [Math.floor(255 * r / high),
-                           Math.floor(255 * g / high),
-                           Math.floor(255 * b / high)];
-               }
-               posFor(color) {
-                   let r = parseInt(color.substr(1, 2), 16),
-                       g = parseInt(color.substr(3, 2), 16),
-                       b = parseInt(color.substr(5, 2), 16);
-
-                   let bright = this._fullBrightness(r, g, b);
-                   r = bright[0]; g = bright[1]; b = bright[2];
-                   
-                   // We may not have a match for this color exactly (e.g. on
-                   // the small image), so we have to search for a near one.
-                   
-                   // 0, 1, -1, 2, -2, ...
-                   let walk = function(x) { return -x + (x > 0 ? 0 : 1); }
-                   
-                   var radius = 8;
-                   for (var dr = 0; dr < radius; dr = walk(dr)) {
-                       for (var dg = 0; dg < radius; dg = walk(dg)) {
-                           for (var db = 0; db < radius; db = walk(db)) {
-                               // Don't need bounds check- out of range
-                               // corrupt colors just won't match.
-                               color = this._hexFromRgb(r + dr, g + dg, b + db);
-                               var pos = this.colorPos[color];
-                               if (pos !== undefined) {
-                                   return pos;
-                               }
-                           }
-                       }
-                   }
-                   throw new Error('no match');
-               }
-           }
-           
-           Polymer({
-               is: "light9-color-picker",
-               properties: {
-                   value: { type: String, notify: true },
-               },
-               observers: ['updateSmall(value)'],
-               attached: function() {
-                   if (!window.pickerCanvases) {
-                       window.pickerCanvases = {
-                           large: new RainbowCanvas(
-                               '/colorpick_rainbow_large.png', [400, 200]),
-                           small: new RainbowCanvas(
-                               '/colorpick_rainbow_small.png', [150, 30]),
-                       };
-                   }
-                   this.large = window.pickerCanvases.large;
-                   this.small = window.pickerCanvases.small;
-               },
-               updateSmall: function(value) {
-                   try {
-                       var pos = this.small.posFor(value);
-                   } catch(e) {
-                       this.moveSmallCrosshair([-999, -999]);
-                       return;
-                   }
-                   this.moveSmallCrosshair(pos);
-               },
-               _floatLarge: function() {
-                   // Large might span multiple columns, and chrome won't
-                   // send events for those parts. Workaround: take it out of
-                   // the columns.
-                   let large = this.$.largeRainbowComp;
-                   let rect = this.$.smallRainbowComp.getBoundingClientRect();
-                   document.body.append(large);
-                   large.style.position = 'fixed';
-                   large.style.left = (rect.left - 100) + 'px';
-                   large.style.top = (rect.top - 50) + 'px';
-
-               },
-               showLarge: function() {
-                   this._floatLarge();
-                   this.$.largeRainbowComp.style.display = 'block';
-                   try {
-                       this.moveLargeCrosshair(this.large.posFor(this.value));
-                   } catch(e) {
-                       this.moveLargeCrosshair([-999, -999]);
-                       return;
-                   }
-               },
-               hideLarge: function() {
-                   this.$.largeRainbowComp.style.display = 'none';
-               },
-               onEnterSmall: function() {
-                   // not if we just closed the large one
-                   this.showLarge();
-               },
-               moveLargeCrosshair: function(pos, _elem) {
-                   _elem = _elem || this.$.largeCrosshair;
-                   _elem.style.left = (pos[0] - _elem.offsetWidth / 2) + 'px';
-                   _elem.style.top = (pos[1] - _elem.offsetHeight / 2) + 'px';
-               },
-               moveSmallCrosshair: function(pos) {
-                   this.moveLargeCrosshair(pos, this.$.smallCrosshair);
-               },
-               onCanvasMove: function(ev) {
-                   if (ev.buttons != 1) {
-                       return;
-                   }
-                   var canvas = this.$.largeRainbow;
-                   var pos = [ev.offsetX - canvas.offsetLeft,
-                              ev.offsetY - canvas.offsetTop];
-                   this.moveLargeCrosshair(pos);
-                   this.value = this.large.colorAt(pos);
-               },
-           });
-       });
-      </script>
-    </dom-module>
-    
-       
     <dom-module id="light9-live-control">
       <template>
         <style>