×

Color

The creation, blending, and application of colors to shapes and text is a common task performed in all Omni applications. This page details how to work with color values in various color spaces.

Color Functions

The following functions are used to create instances of the Color class:

Here’s an OmniGraffle script example that creates a green circle (in the RGB color space) with a 50% transparency (alpha value) overlaid on a blue square:

green-circle-blue-square
omnigraffle:///omnijs-run?script=cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0Asquare%20%3D%20cnvs%2EaddShape%28%27Rectangle%27%2Cnew%20Rect%2872%2C72%2C200%2C200%29%29%0Asquare%2EfillColor%20%3D%20Color%2ERGB%280%2C%200%2C%201%2C%201%29%0Acircle%20%3D%20cnvs%2EaddShape%28%27Circle%27%2Cnew%20Rect%28150%2C150%2C200%2C200%29%29%0Acircle%2EfillColor%20%3D%20Color%2ERGB%280%2C%201%2C%200%2C%200%2E5%29
Create Shapes with Color Fills
 

cnvs = document.windows[0].selection.canvas square = cnvs.addShape('Rectangle', new Rect(72,72,200,200)) square.fillColor = Color.RGB(0, 0, 1, 1) circle = cnvs.addShape('Circle', new Rect(150,150,200,200)) circle.fillColor = Color.RGB(0, 1, 0, 0.5)

Here’s an OmniGraffle script example that adds grayscale tint swatches, from black to white in increments of 10%, to the current canvas:

omnigraffle:///omnijs-run?script=cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0AobjSize%20%3D%2048%0Aoffset%20%3D%200%0Aswatches%20%3D%20new%20Array%28%29%0Afor%28i%20%3D%200%3B%20i%20%3C%2011%3B%20i%2B%2B%29%7B%0A%09offset%20%3D%20offset%20%20%2B%20objSize%0A%09aRect%20%3D%20new%20Rect%28offset%2C%20objSize%2C%20objSize%2C%20objSize%29%0A%09graphic%20%3D%20cnvs%2EaddShape%28%27Rectangle%27%2C%20aRect%29%0A%09color%20%3D%20Color%2EWhite%28i*%2E1%2C1%29%0A%09graphic%2EfillColor%20%3D%20color%0A%09swatches%2Epush%28graphic%29%0A%7D%0AswatchStrip%20%3D%20new%20Group%28swatches%29
grayscale-swatches
Grayscale Bar - 10% Increments
 

cnvs = document.windows[0].selection.canvas objSize = 48 offset = 0 swatches = new Array() for(i = 0; i < 11; i++){ offset = offset + objSize aRect = new Rect(offset, objSize, objSize, objSize) graphic = cnvs.addShape('Rectangle', aRect) color = Color.White(i*.1,1) graphic.fillColor = color swatches.push(graphic) } swatchStrip = new Group(swatches)

Color Class Properties

Some common colors can be represented with the following property values instead of using one of the Color methods.

Common Color Values


graphic.fillColor = Color.blue

Color Instance Properties

Once a Color object has been created, you can use the following instance properties to gather information about the color object.

Color Instance Functions

Color objects can be blended to create new colors, using the blend() method:

omnigraffle://localhost/omnijs-run?script=try%7Bvar%20cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0Avar%20graphic%20%3D%20cnvs%2EaddShape%28%27Circle%27%2C%20new%20Rect%280%2C%200%2C%20200%2C%20200%29%29%0Avar%20colorA%20%3D%20Color%2Ered%0Avar%20colorB%20%3D%20Color%2Eyellow%0Avar%20blendColor%20%3D%20colorA%2Eblend%28colorB%2C%200%2E5%29%0Agraphic%2EfillColor%20%3D%20blendColor%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

Here’s an example of blending colors: creating an orange circle by blending red and yellow

New Shape with Blended Colors
 

cnvs = document.windows[0].selection.canvas graphic = cnvs.addShape('Circle', new Rect(0, 0, 200, 200)) colorA = Color.red colorB = Color.yellow blendColor = colorA.blend(colorB, 0.5) graphic.fillColor = blendColor
 

ColorSpace

A color space is a specific organization of colors.

Examples

Here are some script examples using the Color class:

Hex Color Value for Color Object


function componentToHex(c){ hex = c.toString(16); return hex.length == 1 ? "0" + hex : hex; } function HEXforColor(clrObj){ rv = clrObj.red gv = clrObj.green bv = clrObj.blue r = Math.round(rv * 255) g = Math.round(gv * 255) b = Math.round(bv * 255) colorHEX = "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); return colorHEX.toUpperCase() }
Calling the Functions


clrObj = Color.RGB(0.22574300483333884, 0.7168752888153417, 0.996078431372549, 1) HEXforColor(clrObj) //--> "#3ab7fe"
Do Colors Match?


function RGBMatch(colorA, colorB){ return ( colorA.red === colorB.red && colorA.green === colorB.green && colorA.blue === colorB.blue ) ? true:false }

Color Info Plug-In

An OmniGraffle plug-in for displaying the color information of the selected graphic. Color object constructor statements for each of the colors (stroke, fill, text) will be logged to the console.

color-info color-info-log
Color Info of Selected Graphic
  

/*{ "type": "action", "targets": ["omnigraffle"], "author": "Otto Automator", "identifier": "com.omni-automation.og.color-info", "version": "1.1", "description": "Present the color information for the selected graphic.", "label": "Color Info", "shortLabel": "Color Info", "paletteLabel": "Color Info", "image": "swatchpalette" }*/ (() => { function componentToHex(c){ var hex = c.toString(16); return hex.length == 1 ? "0" + hex : hex; } function HEXforColor(clrObj){ rv = clrObj.red gv = clrObj.green bv = clrObj.blue r = Math.round(rv * 255) g = Math.round(gv * 255) b = Math.round(bv * 255) colorHEX = "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); return colorHEX } const action = new PlugIn.Action(function(selection, sender){ graphic = selection.graphics[0] // console.clear() if(graphic.fillColor){ var graphicFillColor = graphic.fillColor var fillColorHEX = HEXforColor(graphicFillColor).toUpperCase() var red = String(graphicFillColor.red) var green = String(graphicFillColor.green) var blue = String(graphicFillColor.blue) var alpha = String(graphicFillColor.alpha) var fillValues = "R: " + red + "\n" + "G: " + green + "\n" + "B: " + blue + "\n" + "A: " + alpha console.log(`FILL: ${fillColorHEX}`, `Color.RGB(${red}, ${green}, ${blue}, ${alpha})`) } else { var fillValues = "No Fill" var fillColorHEX = "N/A" } if(graphic.strokeColor){ var graphicStrokeColor = graphic.strokeColor var strokeColorHEX = HEXforColor(graphicStrokeColor).toUpperCase() var red = String(graphicStrokeColor.red) var green = String(graphicStrokeColor.green) var blue = String(graphicStrokeColor.blue) var alpha = String(graphicStrokeColor.alpha) var strokeValues = "R: " + red + "\n" + "G: " + green + "\n" + "B: " + blue + "\n" + "A: " + alpha console.log(`STROKE: ${strokeColorHEX}`, `Color.RGB(${red}, ${green}, ${blue}, ${alpha})`) } else { var strokeValues = "No Stroke" var strokeColorHEX = "N/A" } if(graphic instanceof Shape && graphic.textColor){ var graphicTextColor = graphic.textColor var textColorHEX = HEXforColor(graphicTextColor).toUpperCase() var red = String(graphicTextColor.red) var green = String(graphicTextColor.green) var blue = String(graphicTextColor.blue) var alpha = String(graphicTextColor.alpha) var colorValues = "R: " + red + "\n" + "G: " + green + "\n" + "B: " + blue + "\n" + "A: " + alpha console.log(`TEXT: ${textColorHEX}`, `Color.RGB(${red}, ${green}, ${blue}, ${alpha})`) } else { var colorValues = "No Color" var textColorHEX = "N/A" } var message = `FILL: ${fillColorHEX}\n` + fillValues + `\n\nSTROKE: ${strokeColorHEX}\n` + strokeValues + `\n\nTEXT: ${textColorHEX}\n` + colorValues new Alert("Graphic Colors", message).show() }); action.validate = function(selection, sender){ // One single graphic selected (not a group) if (selection.graphics.length === 1){ if (selection.graphics[0] instanceof Group){ return false } else { return true } } else { return false} }; return action; })();

Find/Change Colors

This OmniGraffle plug-in will find and replace all occurrences of a specified HEX color used in any of the selected ways (fill color, stroke color, text color) in all of graphics of the current canvas. If some graphics are already selected, they will be processed, otherwise if no graphics are selected, all graphics on the canvas will be processed.

find-change-color
Find/Replace HEX Color
  

/*{ "type": "action", "targets": ["omnigraffle"], "author": "Otto Automator", "identifier": "com.omni-automation.og.find-change-color", "version": "1.8", "description": "Will replace the indicated HEX color value for fill, stroke, and text in either the selected graphics, or if no graphics are selected, all graphics on the current canvas.", "label": "Find/Change Color", "shortLabel": "Find/Change Color", "paletteLabel": "Find/Change Color", "image":"paintpalette.fill" }*/ (() => { var changeCount = 0 function incrementChangeCount(){ changeCount = changeCount + 1 } function componentToHex(c){ var hex = c.toString(16); return hex.length == 1 ? "0" + hex : hex; } function HEXforColor(clrObj){ rv = clrObj.red gv = clrObj.green bv = clrObj.blue r = Math.round(rv * 255) g = Math.round(gv * 255) b = Math.round(bv * 255) colorHEX = componentToHex(r) + componentToHex(g) + componentToHex(b); return colorHEX.toUpperCase() } function hexToRGBColorObject(hexStr) { var r = 0, g = 0, b = 0; r = "0x" + hexStr[0] + hexStr[1]; g = "0x" + hexStr[2] + hexStr[3]; b = "0x" + hexStr[4] + hexStr[5]; red = (+r / 255).toFixed(10) green = (+g / 255).toFixed(10) blue = (+b / 255).toFixed(10) return Color.RGB(Number(red), Number(green), Number(blue), 1) } function colorMatch(hexColor, clrObj){ objHEXvalue = HEXforColor(clrObj) hexValue = objHEXvalue return (hexColor === hexValue) ? true:false } function RGBMatch(colorA, colorB){ return ( colorA.red === colorB.red && colorA.green === colorB.green && colorA.blue === colorB.blue ) ? true:false } function processGroup(aGroup, shouldChangeFill, shouldChangeStroke, shouldChangeText, targetHEX, replacementColor){ processItems(aGroup.graphics, shouldChangeFill, shouldChangeStroke, shouldChangeText, targetHEX, replacementColor) } function processItems(items, shouldChangeFill, shouldChangeStroke, shouldChangeText, targetHEX, replacementColor){ items.forEach(item => { if (item instanceof Shape){ var itemName = (item.name) ? item.name : "" console.log("Shape", item.id, itemName) if(shouldChangeText && item.textColor){ if (colorMatch(targetHEX, item.textColor)){ item.textColor = replacementColor incrementChangeCount() console.log("Shape", item.id, "text changed") } } if(shouldChangeFill && item.fillColor){ if (colorMatch(targetHEX, item.fillColor)){ item.fillColor = replacementColor incrementChangeCount() console.log("Shape", item.id, "fill changed") } } if(shouldChangeStroke && item.strokeColor){ if (colorMatch(targetHEX, item.strokeColor)){ item.strokeColor = replacementColor incrementChangeCount() console.log("Shape", item.id, "stroke changed") } } } else if (item instanceof Line){ var itemName = (item.name) ? item.name : "" console.log("Line", item.id, itemName) if(shouldChangeStroke && item.strokeColor){ if (colorMatch(targetHEX, item.strokeColor)){ item.strokeColor = replacementColor incrementChangeCount() console.log("Line", item.id, "stroke changed") } } } else if (item instanceof Group){ var itemName = (item.name) ? item.name : "" console.log("Group", itemName) processGroup(item, shouldChangeFill, shouldChangeStroke, shouldChangeText, targetHEX, replacementColor) } else { var itemName = (item.name) ? item.name : "" console.log("Unknown", item.id, itemName) } }) } const action = new PlugIn.Action(async function(selection, sender){ targetColorField = new Form.Field.String( "targetColor", "Search for", "FFFFFF" ) replaceColorField = new Form.Field.String( "replaceColor", "Replace with", "000000" ) fillCheckbox = new Form.Field.Checkbox( "shouldProcessFill", "Fill Color", false ) strokeCheckbox = new Form.Field.Checkbox( "shouldProcessStroke", "Stroke Color", false ) textCheckbox = new Form.Field.Checkbox( "shouldProcessText", "Text Color", false ) inputForm = new Form() inputForm.addField(targetColorField) inputForm.addField(replaceColorField) inputForm.addField(fillCheckbox) inputForm.addField(strokeCheckbox) inputForm.addField(textCheckbox) inputForm.validate = function(formObject){ processFill = formObject.values['shouldProcessFill'] processStroke = formObject.values['shouldProcessStroke'] processText = formObject.values['shouldProcessText'] values = [processFill, processStroke, processText] var targetStatus, replaceStatus targetColor = formObject.values['targetColor'] if(!targetColor){return false} if (/^[a-f0-9]+$/i.test(targetColor)){ targetStatus = (targetColor.length === 6) ? true:false } else { targetStatus = false } replaceColor = formObject.values['replaceColor'] if (!replaceColor){return false} if (/^[a-f0-9]+$/i.test(replaceColor)){ replaceStatus = (replaceColor.length === 6) ? true:false } else { replaceStatus = false } return (values.includes(true) && targetStatus === true && replaceStatus === true) ? true:false } formPrompt = "Enter 6-character HEX colors (no #):" buttonTitle = "Continue" formObject = await inputForm.show(formPrompt,buttonTitle) console.clear() shouldChangeFill = formObject.values['shouldProcessFill'] shouldChangeStroke = formObject.values['shouldProcessStroke'] shouldChangeText = formObject.values['shouldProcessText'] targetHEX = formObject.values['targetColor'] console.log("targetHEX",targetHEX) targetColor = hexToRGBColorObject(targetHEX) replaceHEX = formObject.values['replaceColor'] console.log("replaceHEX",replaceHEX) replacementColor = hexToRGBColorObject(replaceHEX) console.log("fill:" + shouldChangeFill,"stroke:" + shouldChangeStroke,"text:" + shouldChangeText) // use selected graphics or if none, all graphics targetGraphics = selection.graphics if (targetGraphics.length === 0){ cnvs = selection.canvas targetGraphics = cnvs.graphics } changeCount = 0 processItems(targetGraphics, shouldChangeFill, shouldChangeStroke, shouldChangeText, targetHEX, replacementColor) console.log("// Script to locate an item by ID:") console.log("cnvs = document.windows[0].selection.canvas") console.log("graphic = cnvs.graphicWithId(*idNumber*)") console.log("document.windows[0].selection.view.select([graphic],false)") message = String(changeCount) + " items were altered." new Alert("COMPLETED",message).show() }); action.validate = function(selection, sender){ return true }; return action; })();

Opacity

The opacity of a graphic is controlled by the alpha value of its fill or stroke color. For example, this script will generate an instance of the Color class whose color is red with 50% transparency:

Color with 50% Opacity


Color.RGB(1, 0, 0, 0.5) //--> [object Color] {alpha: 0.5, blue: 0, brightness: 1, colorSpace: [object ColorSpace: RGB], green: 0, hue: 1, red: 1, saturation: 1, white: 0.3}

Set Graphic Opacity

Here is an Omni Automation plug-in for OmniGraffle that will change the opacity of the selected items (shapes, lines, and groups) to the percentage value provided by the plug-in user:

Set Opacity of Selected Items
  

/*{ "type": "action", "targets": ["omnigraffle"], "author": "Otto Automator", "identifier": "com.omni-automation.og.set-opacity-of-selection", "version": "1.1", "description": "This action will set the opacity of the selected graphics to the indicated percentage.", "label": "Set Opacity", "shortLabel": "Opacity", "paletteLabel": "Opacity", "image": "paintbrush.fill" }*/ (() => { function processStroke(item,opacity){ c = item.strokeColor newColor = Color.RGB(c.red, c.green, c.blue, opacity) item.strokeColor = newColor } function processFill(item,opacity){ c = item.fillColor newColor = Color.RGB(c.red, c.green, c.blue, opacity) item.fillColor = newColor } function processGroup(group,opacity,shouldIncludeStroke){ group.graphics.forEach(item => { if(item instanceof Shape){ processFill(item,opacity) if (shouldIncludeStroke){processStroke(item,opacity)} } if (item instanceof Line){ processStroke(item,opacity) } if (item instanceof Group){ processGroup(item,opacity,shouldIncludeStroke) } }) } var action = new PlugIn.Action(async function(selection, sender){ textInputField = new Form.Field.String( "textInput", null, "50" ) checkSwitchField = new Form.Field.Checkbox( "shouldIncludeStroke", "Apply opacity setting to shape’s stroke", true ) inputForm = new Form() inputForm.addField(textInputField) inputForm.addField(checkSwitchField) inputForm.validate = function(formObject){ inputText = formObject.values['textInput'] if (!inputText) {return false} var isnum = /^[0-9]+$/i.test(inputText) if (isnum){ var opacityValue = Number(inputText) return ((opacityValue >= 0 && opacityValue <= 100)? true:false) } return false } formPrompt = "Enter an opacity value (0-100):" buttonTitle = "Continue" formObject = await inputForm.show(formPrompt,buttonTitle) textValue = formObject.values['textInput'] console.log('textValue: ',textValue) shouldIncludeStroke = formObject.values['shouldIncludeStroke'] opacityValue = Number(inputText) * .01 selection.graphics.forEach(item => { if (item instanceof Shape){ processFill(item,opacityValue) if (shouldIncludeStroke){processStroke(item, opacityValue)} } if (item instanceof Line){ processStroke(item, opacityValue) } if (item instanceof Group){ processGroup(item, opacityValue, shouldIncludeStroke) } }) }); action.validate = function(selection, sender){ return (selection.graphics.length > 0) }; return action; })();