mirror of
https://github.com/pebble-dev/clay.git
synced 2026-08-28 04:46:57 -04:00
When setting the value for the color picker, round it to the closest available value in the layout
This commit is contained in:
@@ -10,6 +10,8 @@ module.exports = {
|
||||
description: ''
|
||||
},
|
||||
initialize: function(minified, clay) {
|
||||
var HTML = minified.HTML;
|
||||
var self = this;
|
||||
|
||||
/**
|
||||
* @param {string|boolean|number} color
|
||||
@@ -22,13 +24,23 @@ module.exports = {
|
||||
return 'transparent';
|
||||
}
|
||||
|
||||
color = padColorString(color);
|
||||
|
||||
return '#' + (useSunlight ? sunlightColorMap[color] : color);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @return {string}
|
||||
*/
|
||||
function padColorString(color) {
|
||||
color = color.toLowerCase();
|
||||
|
||||
while (color.length < 6) {
|
||||
color = '0' + color;
|
||||
}
|
||||
|
||||
return '#' + (useSunlight ? sunlightColorMap[color] : color);
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,12 +49,66 @@ module.exports = {
|
||||
*/
|
||||
function normalizeColor(value) {
|
||||
switch (typeof value) {
|
||||
case 'number': return value.toString(16);
|
||||
case 'number': return padColorString(value.toString(16));
|
||||
case 'string': return value.replace(/^#|^0x/, '');
|
||||
default: return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array.<Array>} layout
|
||||
* @returns {Array}
|
||||
*/
|
||||
function flattenLayout(layout) {
|
||||
return layout.reduce(function(a, b) {
|
||||
return a.concat(b);
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HEX color to LAB.
|
||||
* Adapted from: https://github.com/antimatter15/rgb-lab
|
||||
* @param {string} hex
|
||||
* @returns {Array} - [l, a, b]
|
||||
*/
|
||||
function hex2lab(hex) {
|
||||
hex = hex.replace(/^#|^0x/, '');
|
||||
|
||||
var r = parseInt(hex.slice(0, 2), 16) / 255;
|
||||
var g = parseInt(hex.slice(2, 4), 16) / 255;
|
||||
var b = parseInt(hex.slice(4), 16) / 255;
|
||||
|
||||
r = (r > 0.04045) ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
||||
g = (g > 0.04045) ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
||||
b = (b > 0.04045) ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
||||
|
||||
var x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
|
||||
var y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.00000;
|
||||
var z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
|
||||
|
||||
x = (x > 0.008856) ? Math.pow(x, 1 / 3) : (7.787 * x) + 16 / 116;
|
||||
y = (y > 0.008856) ? Math.pow(y, 1 / 3) : (7.787 * y) + 16 / 116;
|
||||
z = (z > 0.008856) ? Math.pow(z, 1 / 3) : (7.787 * z) + 16 / 116;
|
||||
|
||||
return [(116 * y) - 16, 500 * (x - y), 200 * (y - z)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the perceptual color distance between two LAB colors
|
||||
* @param {Array} labA
|
||||
* @param {Array} labB
|
||||
* @returns {number}
|
||||
*/
|
||||
function deltaE(labA, labB) {
|
||||
var deltaL = labA[0] - labB[0];
|
||||
var deltaA = labA[1] - labB[1];
|
||||
var deltaB = labA[2] - labB[2];
|
||||
|
||||
return Math.sqrt(Math.pow(deltaL, 2) +
|
||||
Math.pow(deltaA, 2) +
|
||||
Math.pow(deltaB, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the layout based on the connected watch
|
||||
* @returns {Array}
|
||||
@@ -62,8 +128,32 @@ module.exports = {
|
||||
return standardLayouts.COLOR;
|
||||
}
|
||||
|
||||
var HTML = minified.HTML;
|
||||
var self = this;
|
||||
/**
|
||||
* @param {number|string} color
|
||||
* @return {number}
|
||||
*/
|
||||
self.roundColorToLayout = function(color) {
|
||||
var itemValue = normalizeColor(color);
|
||||
|
||||
// if the color is not in the layout we will need find the closest match
|
||||
if (colorList.indexOf(itemValue) === -1) {
|
||||
var itemValueLAB = hex2lab(itemValue);
|
||||
var differenceArr = colorList.map(function(color) {
|
||||
var colorLAB = hex2lab(normalizeColor(color));
|
||||
return deltaE(itemValueLAB, colorLAB);
|
||||
});
|
||||
|
||||
// Get the lowest number from the differenceArray
|
||||
var lowest = Math.min.apply(Math, differenceArr);
|
||||
|
||||
// Get the index for that lowest number
|
||||
var index = differenceArr.indexOf(lowest);
|
||||
itemValue = colorList[index];
|
||||
}
|
||||
|
||||
return parseInt(itemValue, 16);
|
||||
};
|
||||
|
||||
var useSunlight = self.config.sunlight !== false;
|
||||
var sunlightColorMap = {
|
||||
'000000': '000000', '000055': '001e41', '0000aa': '004387', '0000ff': '0068ca',
|
||||
@@ -118,6 +208,12 @@ module.exports = {
|
||||
layout = [layout];
|
||||
}
|
||||
|
||||
var colorList = flattenLayout(layout).map(function(item) {
|
||||
return normalizeColor(item);
|
||||
}).filter(function(item) {
|
||||
return item;
|
||||
});
|
||||
|
||||
var grid = '';
|
||||
var rows = layout.length;
|
||||
var cols = 0;
|
||||
|
||||
@@ -145,16 +145,12 @@ module.exports = {
|
||||
},
|
||||
color: {
|
||||
get: function() {
|
||||
return parseInt(this.$manipulatorTarget.get('value'), 16);
|
||||
return parseInt(this.$manipulatorTarget.get('value'), 10) || 0;
|
||||
},
|
||||
set: function(value) {
|
||||
switch (typeof value) {
|
||||
case 'number': value = value.toString(16); break;
|
||||
case 'string': value = value.replace(/^#|^0x/, ''); break;
|
||||
}
|
||||
value = value || '000000';
|
||||
value = this.roundColorToLayout(value || 0);
|
||||
|
||||
if (this.get() === parseInt(value, 16)) { return this; }
|
||||
if (this.get() === value) { return this; }
|
||||
this.$manipulatorTarget.set('value', value);
|
||||
return this.trigger('change');
|
||||
},
|
||||
|
||||
@@ -134,6 +134,39 @@ function testAutoLayout(platform, layout, allowGray, desc, activeWatchInfo) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number|string} input
|
||||
* @param {number} expected
|
||||
* @param {array|string} layout
|
||||
* @return {void}
|
||||
*/
|
||||
function testClosestToLayout(input, expected, layout) {
|
||||
it('rounds ' + input + ' to ' + expected.toString(16) +
|
||||
' in layout: ' + JSON.stringify(layout),
|
||||
function() {
|
||||
var clayConfig;
|
||||
var colorItem;
|
||||
|
||||
clayConfig = fixture.clayConfig([{
|
||||
type: 'color',
|
||||
sunlight: false,
|
||||
layout: layout
|
||||
}]);
|
||||
colorItem = clayConfig.getItemsByType('color')[0];
|
||||
colorItem.set(input);
|
||||
assert.strictEqual(colorItem.get(), expected);
|
||||
|
||||
clayConfig = fixture.clayConfig([{
|
||||
type: 'color',
|
||||
sunlight: false,
|
||||
layout: layout
|
||||
}]);
|
||||
colorItem = clayConfig.getItemsByType('color')[0];
|
||||
colorItem.set(input);
|
||||
assert.strictEqual(colorItem.get(), expected);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} sunlight
|
||||
* @param {Array|string} [layout=color]
|
||||
@@ -291,6 +324,41 @@ describe('component - color', function() {
|
||||
assert.strictEqual($picker.get('classList').contains('show'), false);
|
||||
});
|
||||
|
||||
describe('color rounding', function() {
|
||||
var layout = 'GRAY';
|
||||
testClosestToLayout('000000', 0x000000, layout);
|
||||
testClosestToLayout('005500', 0x000000, layout);
|
||||
testClosestToLayout('55aa55', 0xaaaaaa, layout);
|
||||
testClosestToLayout('ffaaff', 0xaaaaaa, layout);
|
||||
testClosestToLayout('ffffaa', 0xffffff, layout);
|
||||
testClosestToLayout('ffffff', 0xffffff, layout);
|
||||
|
||||
layout = 'BLACK_WHITE';
|
||||
testClosestToLayout('000000', 0x000000, layout);
|
||||
testClosestToLayout('005500', 0x000000, layout);
|
||||
testClosestToLayout('55aa55', 0xffffff, layout);
|
||||
testClosestToLayout('ffaaff', 0xffffff, layout);
|
||||
testClosestToLayout('ffffaa', 0xffffff, layout);
|
||||
testClosestToLayout('ffffff', 0xffffff, layout);
|
||||
|
||||
layout = 'COLOR';
|
||||
testClosestToLayout('000000', 0x000000, layout);
|
||||
testClosestToLayout('005500', 0x005500, layout);
|
||||
testClosestToLayout('55bb55', 0x55aa55, layout);
|
||||
testClosestToLayout('ff99ff', 0xffaaff, layout);
|
||||
testClosestToLayout('ffffee', 0xffffff, layout);
|
||||
testClosestToLayout('ffffff', 0xffffff, layout);
|
||||
|
||||
layout = ['ff0000', 'ff5500', 'ff00ff', '00ff00', '555555'];
|
||||
testClosestToLayout('000000', 0x555555, layout);
|
||||
testClosestToLayout('ff0000', 0xff0000, layout);
|
||||
testClosestToLayout('ff1111', 0xff0000, layout);
|
||||
testClosestToLayout('00aa00', 0x00ff00, layout);
|
||||
testClosestToLayout('ff55ff', 0xff00ff, layout);
|
||||
testClosestToLayout('aaaaaa', 0x555555, layout);
|
||||
testClosestToLayout('ffffff', 0x555555, layout);
|
||||
});
|
||||
|
||||
describe('layouts', function() {
|
||||
|
||||
// allow gray does nothing for 2.x
|
||||
|
||||
Reference in New Issue
Block a user