diff --git a/extension/chrome.js b/extension/chrome.js index 9e2e5c8..80b5522 100644 --- a/extension/chrome.js +++ b/extension/chrome.js @@ -42,7 +42,6 @@ var dimensions = { activate: function(tab){ this.tab = tab; - this.takeScreenshot(); chrome.tabs.insertCSS(this.tab.id, { file: 'tooltip.css' }); chrome.tabs.executeScript(this.tab.id, { file: 'tooltip.js' }); @@ -79,13 +78,11 @@ var dimensions = { case 'distances': this.port.postMessage({ type: event.data.type, - data: event.data.data + data: event.data.data }); break; case 'screenshot processed': - // the first time we don't have a port connection yet - if(this.port) - this.port.postMessage({ type: 'screenshot taken', data: this.image.src }); + this.port.postMessage({ type: 'screenshot taken', data: this.image.src }); break; } }, @@ -137,7 +134,7 @@ var dimensions = { this.ctx.drawImage(this.image, 0, 0); // read out the image data from the canvas - imgData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height).data; + var imgData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height).data; this.worker.postMessage({ type: 'imgData', diff --git a/extension/dimensions.js b/extension/dimensions.js index 10944de..6cd3f59 100644 --- a/extension/dimensions.js +++ b/extension/dimensions.js @@ -4,7 +4,8 @@ var dimensionsThreshold = 6; onmessage = function(event){ switch(event.data.type){ case 'imgData': - data = grayscale( new Uint8ClampedArray(event.data.imgData) ); + imgData = new Uint8ClampedArray(event.data.imgData); + data = grayscale( imgData ); width = event.data.width; height = event.data.height; postMessage({ type: "screenshot processed" }); @@ -118,6 +119,8 @@ function finishMeasureArea(){ area.top = area.y - area.top; area.bottom = area.bottom - area.y; + area.backgroundColor = getColorAt(area.x, area.y); + postMessage({ type: 'distances', data: area @@ -227,6 +230,7 @@ function measureDistances(input){ distances.x = input.x; distances.y = input.y; + distances.backgroundColor = getColorAt(input.x, input.y); postMessage({ type: 'distances', @@ -234,6 +238,15 @@ function measureDistances(input){ }); } +function getColorAt(x, y){ + if(!inBoundaries(x, y)) + return -1; + + var i = y * width * 4 + x * 4; + + return rgbToHsl(imgData[i], imgData[++i], imgData[++i]); +} + function getLightnessAt(data, x, y){ return inBoundaries(x, y) ? data[y * width + x] : -1; } @@ -242,6 +255,7 @@ function setLightnessAt(data, x, y, value){ return inBoundaries(x, y) ? data[y * width + x] = value : -1; } + // // inBoundaries // ============ @@ -275,4 +289,36 @@ function grayscale(imgData){ } return gray; +} + +/** + * Converts an RGB color value to HSL. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes r, g, and b are contained in the set [0, 255] and + * returns h, s, and l in the set [0, 1]. + * + * @param Number r The red color value + * @param Number g The green color value + * @param Number b The blue color value + * @return Array The HSL representation + */ +function rgbToHsl(r, g, b){ + r /= 255, g /= 255, b /= 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2; + + if(max == min){ + h = s = 0; // achromatic + }else{ + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + + return [h, s, l]; } \ No newline at end of file diff --git a/extension/tooltip.css b/extension/tooltip.css index bc2251a..d2ed782 100644 --- a/extension/tooltip.css +++ b/extension/tooltip.css @@ -41,6 +41,10 @@ box-sizing: border-box; } + .altColor .fn-tooltip { + background: hsla(50,100%,10%,.55); + } + .fn-tooltip.left { left: auto; right: 5px; @@ -56,6 +60,10 @@ background: hsla(205,100%,50%,.55); } + .altColor .fn-axis { + background: hsla(50,100%,50%,.55); + } + .fn-axis:before, .fn-axis:after { content: ""; diff --git a/extension/tooltip.js b/extension/tooltip.js index 1ce359e..52248d2 100644 --- a/extension/tooltip.js +++ b/extension/tooltip.js @@ -1,23 +1,30 @@ +var debug = false; + var body = document.querySelector('body'); var port = chrome.runtime.connect({ name: "dimensions" }); var changeDelay = 300; var changeTimeout; -var paused = false; +var paused = true; var inputX, inputY; var altKeyWasPressed = false; var connectionClosed = false; +var lineColor = getLineColor(); +var colorThreshold = [0.2,0.5,0.2]; var overlay = document.createElement('div'); overlay.className = 'fn-noCursor'; -disableCursor(); +function init(){ + window.addEventListener('mousemove', onInputMove); + window.addEventListener('touchmove', onInputMove); + window.addEventListener('scroll', onVisibleAreaChange); + window.addEventListener('resize', onResizeWindow); -window.addEventListener('mousemove', onInputMove); -window.addEventListener('touchmove', onInputMove); -window.addEventListener('scroll', onVisibleAreaChange); -window.addEventListener('resize', onResizeWindow); + window.addEventListener('keydown', detectAltKeyPress); + window.addEventListener('keyup', detectAltKeyRelease); -window.addEventListener('keydown', detectAltKeyPress); -window.addEventListener('keyup', detectAltKeyRelease); + disableCursor(); + requestNewScreenshot(); +} port.onMessage.addListener(function(event){ if(connectionClosed) @@ -29,7 +36,9 @@ port.onMessage.addListener(function(event){ break; case 'screenshot taken': resume(); - // debugScreenshot(event.data); + + if(debug) + debugScreenshot(event.data); break; case 'destroy': destroy(); @@ -45,9 +54,14 @@ function onResizeWindow(){ onResizeWindow(); -function debugScreenshot(src){ +function removeDebugScreenshot(){ var oldscreen = body.querySelector('.fn-screenshot'); - oldscreen && body.removeChild(oldscreen); + if(oldscreen) + oldscreen.parentNode.removeChild(oldscreen); +} + +function debugScreenshot(src){ + removeDebugScreenshot(); var screenshot = new Image(); screenshot.src = src; @@ -62,6 +76,7 @@ function destroy(){ window.removeEventListener('scroll', onVisibleAreaChange); removeDimensions(); + removeDebugScreenshot(); enableCursor(); } @@ -74,10 +89,15 @@ function removeDimensions(){ function onVisibleAreaChange(){ if(!paused) pause(); + else + return; if(changeTimeout) clearTimeout(changeTimeout); + if(debug) + removeDebugScreenshot(); + changeTimeout = setTimeout(requestNewScreenshot, changeDelay); } @@ -168,6 +188,13 @@ function showDimensions(dimensions){ newDimensions.style.left = dimensions.x + "px"; newDimensions.style.top = dimensions.y + "px"; + console.log(lineColor, dimensions.backgroundColor); + + if(Math.abs(dimensions.backgroundColor[0] - lineColor[0]) <= colorThreshold[0] && + Math.abs(dimensions.backgroundColor[1] - lineColor[1]) <= colorThreshold[1] && + Math.abs(dimensions.backgroundColor[2] - lineColor[2]) <= colorThreshold[2]) + newDimensions.className += ' altColor'; + var measureWidth = dimensions.left + dimensions.right; var measureHeight = dimensions.top + dimensions.bottom; @@ -197,5 +224,54 @@ function showDimensions(dimensions){ newDimensions.appendChild(yAxis); newDimensions.appendChild(tooltip); - body.appendChild(newDimensions) -} \ No newline at end of file + body.appendChild(newDimensions); +} + +function getLineColor() { + var axis = document.createElement('div'); + axis.className = 'fn-axis'; + + body.appendChild(axis); + + var style = getComputedStyle(axis); + var rgbString = style.backgroundColor; + var colorsOnly = rgbString.substring(rgbString.indexOf('(') + 1, rgbString.lastIndexOf(')')).split(/,\s*/); + + body.removeChild(axis); + + return rgbToHsl(colorsOnly[0], colorsOnly[1], colorsOnly[2]); +} + +/** + * Converts an RGB color value to HSL. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes r, g, and b are contained in the set [0, 255] and + * returns h, s, and l in the set [0, 1]. + * + * @param Number r The red color value + * @param Number g The green color value + * @param Number b The blue color value + * @return Array The HSL representation + */ +function rgbToHsl(r, g, b){ + r /= 255, g /= 255, b /= 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2; + + if(max == min){ + h = s = 0; // achromatic + }else{ + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + + return [h, s, l]; +} + +init(); \ No newline at end of file