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:
RGB(redValue, greenValue, blueValue, alphaValue or nil) (Color) • Makes a new color in the RGB colorspace, with the given components. If the alpha component is not given, 1.0 is used.
HSB(hueValue, saturationValue, brillianceValue, alphaValue or nil) • Makes a new color in the HSB colorspace, with the given components. If the alpha component is not given, 1.0 is used.
White(whiteValue, alphaValue or nil) • Makes a new color in the White colorspace, with the given components. If the alpha component is not given, 1.0 is used. A White value of: 0 is black, .5 is 50% gray.
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:
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:
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
black (Color) • A color in the White colorspace with white component of 0.0.
blue (Color) • A color in the RGB colorspace with components (0, 0, 1, 1).
brown (Color) • A color in the RGB colorspace with components (0.6, 0.4, 0.2, 1).
clear (Color) • A color in the White colorspace with white component of 0.0 and alpha of 0.0 (“transparent black”).
cyan (Color) • A color in the RGB colorspace with components (0, 1, 1, 1).
darkGray (Color) • A color in the White colorspace with white component of 0.333.
gray (Color) • A color in the White colorspace with white component of 0.5.
green (Color) • A color in the RGB colorspace with components (0, 1, 0, 1).
lightGray (Color) • A color in the White colorspace with white component of 0.667.
magenta (Color) • A color in the RGB colorspace with components (1, 0, 1, 1).
orange (Color) • A color in the RGB colorspace with components (1, 0.5, 0, 1).
purple (Color) • A color in the RGB colorspace with components (1, 0, 1, 1).
red (Color) • A color in the RGB colorspace with components (1, 0, 0, 1).
white (Color) • A color in the White colorspace with white component of 1.0.
yellow (Color) • A color in the RGB colorspace with components (1, 1, 0, 1).
Color Instance Properties
Once a Color object has been created, you can use the following instance properties to gather information about the color object.
alpha (Number r/o) • Returns the alpha component of the color.
blue (Number r/o) • Returns the blue component of the color, after converting to a RGB colorspace.
brightness (Number r/o) • Returns the brightness component of the color, after converting to a HSB colorspace.
colorSpace (ColorSpace r/o) • Returns the colorspace of the instance.
green (Number r/o) • Returns the green component of the color, after converting to a RGB colorspace.
hue (Number r/o) • Returns the hue component of the color, after converting to a HSB colorspace.
red (Number r/o) • Returns the red component of the color, after converting to a RGB colorspace.
saturation (Number r/o) • Returns the saturation component of the color, after converting to a HSB colorspace.
white (Number r/o) • Returns the white component of the color, after converting to a White colorspace.
Color Instance Functions
Color objects can be blended to create new colors, using the blend() method:
blend(otherColor, fractionNumber) (Color or nil) • Returns a new color that is a linear combination of the receiver and fraction of the other color (so, a fraction of 1.0 would just return the otherColor. If the colors cannot be blended (for example, if they cannot be converted to the same colorspace), then null is returned.
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.
CMYK (ColorSpace r/o) • A colorspace with cyan, magenta, yellow, black, and alpha components.
HSB (ColorSpace r/o) • A colorspace with hue, saturation, and value (or brightness) components.
Named (ColorSpace r/o) • A space for named colors, like system defined colors, or specific color palette spaces.
Pattern (ColorSpace r/o) • A colorspace that wraps a pattern image.
RGB (ColorSpace r/o) • The sRGB colorspace with red, green, blue, and alpha components.
White (ColorSpace r/o) • A colorspace with white and alpha components.
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 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/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;
})();