Many applications have their own names for colors in their palettes. This example features an Apps Script library to retrieve and manipulate colors according to their names in their home palettes. The known palettes currently are Material colors, HTML named colors and the Google Apps Palette. The Google Apps Palette looks like this in the GUI. I've generated the material palette using this library, along with the closest matching colors in the Apps and html palette. The idea is to be able to get a color by its palette and name, or to find its name from its color codes. You can use the library by including this in your project. It's also available on Github if you prefer, and the test spreadsheet is here if you'd like to make a copy. Some examples (if you are using the library you'll need to prefix ColorList with the library identifier eg cColorList.ColorList.getColor()) function test() { // get a color properties Logger.log(JSON.stringify(cColorList.ColorList.getColor('google','light red berry 1'))); // get a color properties by hex code Logger.log(JSON.stringify(cColorList.ColorList.getColorName('google','#f3f3f3'))); // get a color properties by rgb number Logger.log(JSON.stringify(cColorList.ColorList.getColorName('html',255))); // get closest Logger.log(JSON.stringify(cColorList.ColorList.getClosest ('html' , '#ff9900'))); Logger.log(JSON.stringify(cColorList.ColorList.getClosest ('material' , '#ff9900'))); // check grey/gray Logger.log(JSON.stringify(cColorList.ColorList.getColor('material','grey 600'))); Logger.log(JSON.stringify(cColorList.ColorList.getColor('google','light gray 2'))); // get closest var lister = cColorList.ColorList; Logger.log(JSON.stringify(lister.getClosest ('material' , lister.getColor('google','red berry').value))); } The result is not only the code matching the name and palette, but loads of additional color related information (see Color Arranger for more information on these properties). { "name": "light red berry 1", "value": "#ca4126", "palette": "google", "status": "ok", "properties": { "rgb": 2507210, "red": 202, "green": 65, "blue": 38, "htmlHex": "#ca4126", "luminance": 0.16378548548538505, "textColor": "#ffffff", "contrastRatio": 4.91146532991259, "black": 0.207843137254902, "yellow": 0.8118811881188118, "magenta": 0.6782178217821783, "cyan": 0, "hue": 9.878048780487813, "saturation": 68.33333333333333, "lightness": 47.05882352941176, "value": 0.792156862745098, "x": 26.597269352335072, "y": 16.47709067915203, "z": 3.612286684447369, "LStar": 47.594296368851595, "aStar": 52.928166803487386, "bStar": 45.38090169447055, "cStar": 69.71956023800627, "hStar": 40.609968669570854 } } You can then use this in your Apps Script code to set background colors and avoid worrying about hex codes. (spacing and case are ignored in the color names) - for example. ColorList.getColor('google','cornflower blue').value Text ColorA very useful property is the the textColor, which will be set to either black or white, depending on which is the best font color to use with the given background color. This property can be used to set the font color appropriately if you change the background color of a cell. ColorList.getColor('google','light red berry 1').properties.textColor Matching ColorsThis library also provides a useful way to get the closest match in a palette for some desired color.This snip shows the beginning of the result of finding the nearest match between the html palette and the google palette. and visa versa The material palette versus google apps. and so on .. the full palette matches and details can be found in this sheet. The Code for matching colors.Finding the nearest match for a given color code in a palette is simple. Here's we're looking for the closest color in the html palette to #ff9900 (orange in the google palette). Logger.log(JSON.stringify(ColorList.getClosest ('html' , '#ff9900'))); The query could also be written like this. Logger.log(JSON.stringify(ColorList.getClosest ('html' , ColorList.getColor('google' , 'orange' )))); It gives a result like this, where diff is a value between 0-100. The lower, the better the match. { "diff": 4.2351903633318795, "member": { "name": "Orange", "value": "#ffa500" } } Code for comparing to complete color schemes and dumping the result// get the best match between html and google and material palettes function match () { var ss = SpreadsheetApp.getActiveSpreadsheet(); var lister = cColorList.ColorList; // compare combinations of palettes comparePalettes_ ('google','html'); comparePalettes_ ('google','material'); comparePalettes_ ('html','google'); comparePalettes_ ('html','material'); comparePalettes_ ('material','html'); comparePalettes_ ('material','google'); /** * @param {string} p1 palette1 * @param {string} p2 palette2 */ function comparePalettes_ (p1, p2) { // do comparison and write to sheet var sheet = ss.getSheetByName(p1+'_'+ p2) || ss.insertSheet(p1+'_'+ p2); // clear the sheet sheet.clearContents(); // get each of the palettes var list1 = lister.getList(p1); // add the properties to the sheet var heads = {}; heads[p1+'Name'] = Object.keys(heads).length; heads[p1+'Value'] = Object.keys(heads).length; heads[p2+'Name'] = Object.keys(heads).length; heads[p2+'Value'] = Object.keys(heads).length; heads.difference = Object.keys(heads).length; // find the nearest matches var values = Object.keys(list1).map(function(d) { // get the nearest match in the other list var best = lister.getClosest (p2 , list1[d].value); // make this row var row = []; row[heads[p1+'Name']] = list1[d].name; row[heads[p1+'Value']] = list1[d].value; row[heads[p2+'Name']] = best.member.name; row[heads[p2+'Value']] = best.member.value; row[heads.difference] = best.diff; return row; }); // now write the whole thing out sheet.getRange (1,1,values.length+1 , Object.keys(heads).length) .setValues([Object.keys(heads)].concat(values)); // colorize the columns sheet.getRange (2,1+heads[p1+'Name'],values.length , 2) .setBackgrounds(values.map (function(row) { return row.slice(0,2).map(function(col) { return row[heads[p1+'Value']]; }); })); sheet.getRange (2,1+heads[p2+'Name'],values.length , 2) .setBackgrounds(values.map (function(row) { return row.slice(0,2).map(function(col) { return row[heads[p2+'Value']]; }); })); // choose best font color sheet.getRange (2,1+heads[p1+'Name'],values.length , 2) .setFontColors(values.map (function(row) { return row.slice(0,2).map(function(col) { return lister.getColor(p2,row[heads[p2+'Name']]).properties.textColor; }); })); sheet.getRange (2,1+heads[p2+'Name'],values.length , 2) .setFontColors(values.map (function(row) { return row.slice(0,2).map(function(col) { return lister.getColor(p2,row[heads[p2+'Name']]).properties.textColor; }); })); } } Adding palettesIt is possible to add your own palettes with a simple pattern. To demonstrate, I'll use the material color design principle as demonstrated in the material palette site, where you can create something like this given a primary and an accent color. By providing a primary and an accent color, here's the same thing applied to a sheet. In this case using Amber and Blue. Abstracting the actual color selection means that colors can be referred to as dark, light, primary, icons, accent, secondaryText and primaryText and changing the color is just a matter of picking a new primary and accent color, with no changes of code required. This library can be used for client side color manipulation too of course. A new Material palette combination is created like this var theCombination = new cColorList.MaterialPalette('pink','blue'); and components accessed like this, which allows complete abstraction from the color scheme used. var accent = lister.getColor (theCombination.getName(), 'accent').value; Here's the code for creating a selection of combinations, each on its own sheet. // generate various material palette combinations function generateMaterial() { var lister = cColorList.ColorList; var ss = SpreadsheetApp.getActiveSpreadsheet(); // here's a list of palette combinations to try [['pink','lime'],['amber','blue'],['purple','deeporange'],['deeporange','purple']].forEach(function (combination) { // create the material palette var mp = new cColorList.MaterialPalette(combination[0],combination[1]); // a sheet for each known combination or create one var sheet = ss.getSheetByName(mp.getName()) || ss.insertSheet(mp.getName()); // clear the sheet sheet.clear(); //now we can use that with the normal lister stuff show all the props on a sheet var members = lister.getList(mp.getName()); sheet.getRange(1,1,1,1).setValues ([['combination:' + mp.getName()]]); Object.keys(members).forEach(function(d,i) { // get the details on the material palette var color = lister.getColorName ('material', members[d].value); // write the details sheet.getRange(i+2,1,1,3).setValues ([[members[d].name,color.name,members[d].value]]); // set the background to show the color sheet.getRange(i+2,1,1,3).setBackgrounds ([[members[d].value,members[d].value,members[d].value]]); // use a contrasting text color if it exists in the material list, otherwise use the material text color var textColor = color.properties ? color.properties.textColor : members.primaryText; sheet.getRange(i+2,1,1,3).setFontColors ([[textColor,textColor,textColor]]); // specific colors can now be called out abstractly like this - allowing easy refactoring. Logger.log( lister.getColor(mp.getName() , 'primary').value); Logger.log( lister.getColor(mp.getName() , 'dark').value); Logger.log( lister.getColor(mp.getName() , 'light').value); Logger.log( lister.getColor(mp.getName() , 'accent').value); Logger.log( lister.getColor(mp.getName() , 'primaryText').value); Logger.log( lister.getColor(mp.getName() , 'secondaryText').value); }); }); } Creating your own.The material combination code is in the ColorList library but it's straightforward to create your own by adapting this pattern. In this case, the colors are picked up from the material palette, but they can be anything you want them to be, as can the properties like dark, light and so on. 'use strict'; var MaterialPalette = function (primary, accent) { var self = this; var primary_ = (primary || 'Indigo').toLowerCase(); var accent_ = (accent || 'Amber').toLowerCase(); self.getName = function () { return 'material' + primary_ + accent_; }; var gc = ColorList.getColor; // add to known palettes KnownPalettes.palettes[self.getName()] = { "dark":gc('material ' , primary_ + " 700").value, "light":gc('material ' ,primary_ + " 100").value, "primary":gc('material ' ,primary_ + " 500").value, "icons":gc('material ' ,"white").value, "accent":gc('material ' ,accent_ + (["pink","blue"].indexOf(accent_) === -1 ? " 500" : "a200")).value, "primaryText":gc('material ' ,"gray 900").value, "secondaryText":"#727272", "divider":"#B6B6B6" }; // update the keys. ColorList.reset(); } Dumping the color properties.
|
Services > Desktop Liberation - the definitive resource for Google Apps Script and Microsoft Office automation > Color Fiesta >