Connecting Graphics

The ability to visualize data and relationships is a core feature of OmniGraffle. For example, by connecting graphics with lines and arrows, a script can show the hierarchy of an organization or the relationship between objects. This page describes how to connect graphics with lines.

There are a couple approaches to connecting objects in an OmniGraffle document. You can connect existing objects in the document; create new objects to connect, or clone existing objects to maintain a particular object shape or styling. The examples on this page demonstrate the connection of cloned objects.

Allowing Connections

There is a user-settable preference for a selected object to enable or disable its ability to receive connection lines from other objects (see image below). In the examples shown on this page, the allowsConnections property of the Graphics class will be enabled within the scripts themselves.

connections-preference

Connecting Two Graphics

As an example, here's how to connect two named graphics on the current canvas:

cnvs = document.windows[0].selection.canvas graphicA = cnvs.graphicWithName(‘My First Graphic’) graphicB = cnvs.graphicWithName(‘My Second Graphic’) line = cnvs.connect(graphicA,graphicB) line.lineType = LineType.Curved

As an example, here's how to connect two selected graphics on the current canvas:

graphics = document.windows[0].selection.graphics if (graphics.length === 2){ cnvs = document.windows[0].selection.canvas line = cnvs.connect(graphics[0],graphics[1]) } else { alertTitle = 'Selection Error' alertMessage = 'Please select the two graphics to connect.' var alert = new Alert(alertTitle, alertMessage) alert.show(function(result){}) }
omnigraffle://localhost/omnijs-run?script=graphics%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Egraphics%0Aif%20%28graphics%2Elength%20%3D%3D%3D%202%29%7B%0A%09cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09line%20%3D%20cnvs%2Econnect%28graphics%5B0%5D%2Cgraphics%5B1%5D%29%0A%7D%20else%20%7B%0A%09alertTitle%20%3D%20%27Selection%20Error%27%0A%09alertMessage%20%3D%20%27Please%20select%20the%20two%20graphics%20to%20connect%2E%27%0A%09var%20alert%20%3D%20new%20Alert%28alertTitle%2C%20alertMessage%29%0A%09alert%2Eshow%28function%28result%29%7B%7D%29%0A%7D

Create a Connected Graphic Clone

The script example below, demonstrates how to create a connected clone of the currently selected graphic, with the new clone replacing the original item as the selected item (see image below).

The cloning is accomplished using the duplicateTo() method of the Canvas class, and the connection is accomplished using the connect() method of the Graphic class. And the selection wil be controlled using the deselect() and select() methods of the GraphicView class.

In the example, the clone is positioned directly below the original item, but the script can be adjusted to place the clone to the left, right, or even diagonally from the original item, by using the properties of the Rect class to determine the new point for the cloned item’s origin (position). For example, to create a clone of the selected object placed to the right of the original, the coordinates for the new point would be expressed as:

(geo.maxX + offset, geo.minY) instead of (geo.minX, geo.maxY + offset)

connected-clone
//Clone and Connect if (document.windows[0].selection.graphics.length != 1){ title = "SELECTION ERROR" message = "Please select a single graphic." new Alert(title, message).show(function(result){throw new Error('user cancelled')}) } else { cnvs = document.windows[0].selection.canvas graphic = document.windows[0].selection.graphics[0] graphic.allowsConnections = true geo = graphic.geometry offset = 72 clone = graphic.duplicateTo(new Point(geo.minX, geo.maxY + offset),cnvs) line = cnvs.connect(graphic,clone) line.lineType = LineType.Curved if(graphic.strokeColor == null){ lcolor = Color.black } else { lcolor = graphic.strokeColor } line.strokeColor = lcolor line.shadowColor = null line.strokeThickness = 4 line.strokeType = StrokeType.Single line.headType = 'Arrow' line.tailType = 'None' document.windows[0].selection.view.deselect([graphic]) document.windows[0].selection.view.select([clone]) }
omnigraffle:///omnijs-run?script=%2F%2FClone%20and%20Connect%0Aif%20%28document%2Ewindows%5B0%5D%2Eselection%2Egraphics%2Elength%20%21%3D%201%29%7B%0A%09title%20%3D%20%22SELECTION%20ERROR%22%0A%09message%20%3D%20%22Please%20select%20a%20single%20graphic%2E%22%0A%09new%20Alert%28title%2C%20message%29%2Eshow%28function%28result%29%7Bthrow%20new%20Error%28%27user%20cancelled%27%29%7D%29%0A%7D%20else%20%7B%0A%09cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09graphic%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Egraphics%5B0%5D%0A%09graphic%2EallowsConnections%20%3D%20true%0A%09geo%20%3D%20graphic%2Egeometry%0A%09offset%20%3D%2072%0A%09clone%20%3D%20graphic%2EduplicateTo%28new%20Point%28geo%2EminX%2C%20geo%2EmaxY%20%2B%20offset%29%2Ccnvs%29%0A%09line%20%3D%20cnvs%2Econnect%28graphic%2Cclone%29%0A%09line%2ElineType%20%3D%20LineType%2ECurved%0A%09if%28graphic%2EstrokeColor%20%3D%3D%20null%29%7B%0A%09%09lcolor%20%3D%20Color%2Eblack%0A%09%7D%20else%20%7B%0A%09%09lcolor%20%3D%20graphic%2EstrokeColor%0A%09%7D%0A%09line%2EstrokeColor%20%3D%20lcolor%0A%09line%2EshadowColor%20%3D%20null%0A%09line%2EstrokeThickness%20%3D%204%0A%09line%2EstrokeType%20%3D%20StrokeType%2ESingle%0A%09line%2EheadType%20%3D%20%27Arrow%27%0A%09line%2EtailType%20%3D%20%27None%27%0A%09document%2Ewindows%5B0%5D%2Eselection%2Eview%2Edeselect%28%5Bgraphic%5D%29%0A%09document%2Ewindows%5B0%5D%2Eselection%2Eview%2Eselect%28%5Bclone%5D%29%0A%7D

TIP: The script above makes an excellent assigned object action tool for quickly creating a chain of connected objects.

5-Item Diagram Circle

Here’s a script that delivers in an instant, something that is difficult to accomplish by hand: the creation of a relationship circle. In this case, there are five items (an original item cloned four times) placed equidistant from each other in a connected circle. The script is made possible through the exposed properties of the Rect class, and the methods and properties from the standard JavaScript Math class.

TIP: The circle has been added to serve as a template guide should you wish to bend the straight connection lines into curves (see image below).

5-item-diagram-circle
if (document.windows[0].selection.graphics.length != 1){ title = "SELECTION ERROR" message = "Please select a single graphic." new Alert(title, message).show(function(result){throw new Error('user cancelled')}) } else { // connect lines function function connectObjects(startObj,endObj){ cnvs = document.windows[0].selection.canvas aLine = cnvs.connect(startObj,endObj) aLine.lineType = LineType.Curved aLine.strokeColor = Color.black aLine.shadowColor = null aLine.strokeThickness = 4 aLine.strokeType = StrokeType.Single aLine.headType = 'Arrow' aLine.tailType = 'None' } // number of diagram items numObj = 5 // origin object properties cnvs = document.windows[0].selection.canvas obj = document.windows[0].selection.graphics[0] objGeo = obj.geometry objC = objGeo.center objH = objGeo.height objW = objGeo.width // diameter and radius of circle diameter = objH * (numObj + 1) radius = diameter/2 console.log('radius: ' + radius) // center of the circle centerX = objC.x centerY = objC.y + radius console.log('CC: ' + centerX + ', ' + centerY) // create a circle cRect = new Rect(objGeo.midX - radius,objGeo.midY,diameter,diameter) circle = cnvs.addShape('Circle',cRect) circle.orderBelow(obj) // angle of each segment arc = 360/numObj objP = obj arcT = 0 for(i = 0; i < numObj-1; i++){ arcT = arcT + arc console.log('arcT: ' + arcT) if (arcT == 90){ // 0 nX = centerX + radius nY = centerY console.log(nX + ", " + nY) newPoint = new Point(nX-(objW/2),nY-(objH/2)) } else if(arcT == 180 ){ // 90 nX = centerX nY = centerY + radius console.log(nX + ", " + nY) newPoint = new Point(nX-(objW/2),nY-(objH/2)) } else if(arcT == 270){ // 180 nX = centerX - radius nY = centerY console.log(nX + ", " + nY) newPoint = new Point(nX-(objW/2),nY-(objH/2)) } else if(arcT == 360 ){ // 270 nX = centerX nY = centerY - radius console.log(nX + ", " + nY) newPoint = new Point(nX-(objW/2),nY-(objH/2)) } else if(arcT < 90 && arcT > 0){ console.log('Q1') angle = 90 - arcT console.log(angle) radians = angle * Math.PI / 180 nX = centerX + (radius * Math.cos(radians)) nY = centerY - (radius * Math.sin(radians)) console.log(nX + ", " + nY) newPoint = new Point(nX-(objW/2),nY-(objH/2)) } else if(arcT > 90 && arcT < 180){ console.log('Q2') angle = 90 - (180 - arcT) // adjacent angle console.log(angle) radians = angle * Math.PI / 180 nX = centerX + (radius * Math.cos(radians)) nY = centerY + (radius * Math.sin(radians)) console.log(nX + ", " + nY) newPoint = new Point(nX-(objW/2),nY-(objH/2)) } else if(arcT > 180 && arcT < 270){ console.log('Q3') angle = 270 - arcT console.log(angle) radians = angle * Math.PI / 180 nX = centerX - (radius * Math.cos(radians)) nY = centerY + (radius * Math.sin(radians)) console.log(nX + ", " + nY) newPoint = new Point(nX-(objW/2),nY-(objH/2)) } else if(arcT > 270){ console.log('Q4') angle = 90 - (360 - arcT) console.log(angle) radians = angle * Math.PI / 180 nX = centerX - (radius * Math.cos(radians)) nY = centerY - (radius * Math.sin(radians)) console.log(nX + ", " + nY) newPoint = new Point(nX-(objW/2),nY-(objH/2)) } objN = obj.duplicateTo(newPoint) connectObjects(objP,objN) if (i == numObj -2){ // connect to the starting shape connectObjects(objN,obj) } else { objP = objN } } }
omnigraffle:///omnijs-run?script=if%20%28document%2Ewindows%5B0%5D%2Eselection%2Egraphics%2Elength%20%21%3D%201%29%7B%0A%09title%20%3D%20%22SELECTION%20ERROR%22%0A%09message%20%3D%20%22Please%20select%20a%20single%20graphic%2E%22%0A%09new%20Alert%28title%2C%20message%29%2Eshow%28function%28result%29%7Bthrow%20new%20Error%28%27user%20cancelled%27%29%7D%29%0A%7D%20else%20%7B%0A%09%2F%2F%20connect%20lines%20function%0A%09function%20connectObjects%28startObj%2CendObj%29%7B%0A%09%09cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09%09aLine%20%3D%20cnvs%2Econnect%28startObj%2CendObj%29%0A%09%09aLine%2ElineType%20%3D%20LineType%2ECurved%0A%09%09aLine%2EstrokeColor%20%3D%20Color%2Eblack%0A%09%09aLine%2EshadowColor%20%3D%20null%0A%09%09aLine%2EstrokeThickness%20%3D%204%0A%09%09aLine%2EstrokeType%20%3D%20StrokeType%2ESingle%0A%09%09aLine%2EheadType%20%3D%20%27Arrow%27%0A%09%09aLine%2EtailType%20%3D%20%27None%27%0A%09%7D%0A%09%0A%09%2F%2F%20number%20of%20diagram%20items%0A%09numObj%20%3D%205%0A%09%0A%09%2F%2F%20origin%20object%20properties%0A%09cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09obj%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Egraphics%5B0%5D%0A%09objGeo%20%3D%20obj%2Egeometry%0A%09objC%20%3D%20objGeo%2Ecenter%0A%09objH%20%3D%20objGeo%2Eheight%0A%09objW%20%3D%20objGeo%2Ewidth%0A%09%2F%2F%20diameter%20and%20radius%20of%20circle%0A%09diameter%20%3D%20objH%20*%20%28numObj%20%2B%201%29%0A%09radius%20%3D%20diameter%2F2%0A%09console%2Elog%28%27radius%3A%20%27%20%2B%20radius%29%0A%09%2F%2F%20center%20of%20the%20circle%0A%09centerX%20%3D%20objC%2Ex%0A%09centerY%20%3D%20objC%2Ey%20%2B%20radius%0A%09console%2Elog%28%27CC%3A%20%27%20%2B%20centerX%20%2B%20%27%2C%20%27%20%2B%20centerY%29%0A%09%2F%2F%20create%20a%20circle%0A%09cRect%20%3D%20new%20Rect%28objGeo%2EmidX%20-%20radius%2CobjGeo%2EmidY%2Cdiameter%2Cdiameter%29%0A%09circle%20%3D%20cnvs%2EaddShape%28%27Circle%27%2CcRect%29%0A%09circle%2EorderBelow%28obj%29%0A%0A%09%2F%2F%20angle%20of%20each%20segment%0A%09arc%20%3D%20360%2FnumObj%0A%0A%09objP%20%3D%20obj%0A%09arcT%20%3D%200%0A%09for%28i%20%3D%200%3B%20i%20%3C%20numObj-1%3B%20i%2B%2B%29%7B%0A%09%09arcT%20%3D%20arcT%20%2B%20arc%0A%09%09console%2Elog%28%27arcT%3A%20%27%20%2B%20arcT%29%0A%09%09if%20%28arcT%20%3D%3D%2090%29%7B%0A%09%09%09%2F%2F%200%0A%09%09%09nX%20%3D%20centerX%20%2B%20radius%0A%09%09%09nY%20%3D%20centerY%0A%09%09%09console%2Elog%28nX%20%2B%20%22%2C%20%22%20%2B%20nY%29%0A%09%09%09newPoint%20%3D%20new%20Point%28nX-%28objW%2F2%29%2CnY-%28objH%2F2%29%29%0A%09%09%7D%20else%20if%28arcT%20%3D%3D%20180%20%29%7B%0A%09%09%09%2F%2F%2090%0A%09%09%09nX%20%3D%20centerX%0A%09%09%09nY%20%3D%20centerY%20%2B%20radius%0A%09%09%09console%2Elog%28nX%20%2B%20%22%2C%20%22%20%2B%20nY%29%0A%09%09%09newPoint%20%3D%20new%20Point%28nX-%28objW%2F2%29%2CnY-%28objH%2F2%29%29%0A%09%09%7D%20else%20if%28arcT%20%3D%3D%20270%29%7B%0A%09%09%09%2F%2F%20180%0A%09%09%09nX%20%3D%20centerX%20-%20radius%0A%09%09%09nY%20%3D%20centerY%0A%09%09%09console%2Elog%28nX%20%2B%20%22%2C%20%22%20%2B%20nY%29%0A%09%09%09newPoint%20%3D%20new%20Point%28nX-%28objW%2F2%29%2CnY-%28objH%2F2%29%29%0A%09%09%7D%20else%20if%28arcT%20%3D%3D%20360%20%29%7B%0A%09%09%09%2F%2F%20270%0A%09%09%09nX%20%3D%20centerX%0A%09%09%09nY%20%3D%20centerY%20-%20radius%0A%09%09%09console%2Elog%28nX%20%2B%20%22%2C%20%22%20%2B%20nY%29%0A%09%09%09newPoint%20%3D%20new%20Point%28nX-%28objW%2F2%29%2CnY-%28objH%2F2%29%29%0A%09%09%7D%20else%20if%28arcT%20%3C%2090%20%26%26%20arcT%20%3E%200%29%7B%0A%09%09%09console%2Elog%28%27Q1%27%29%0A%09%09%09angle%20%3D%2090%20-%20arcT%0A%09%09%09console%2Elog%28angle%29%0A%09%09%09radians%20%3D%20angle%20*%20Math%2EPI%20%2F%20180%0A%09%09%09nX%20%3D%20centerX%20%2B%20%28radius%20*%20Math%2Ecos%28radians%29%29%0A%09%09%09nY%20%3D%20centerY%20-%20%28radius%20*%20Math%2Esin%28radians%29%29%0A%09%09%09console%2Elog%28nX%20%2B%20%22%2C%20%22%20%2B%20nY%29%0A%09%09%09newPoint%20%3D%20new%20Point%28nX-%28objW%2F2%29%2CnY-%28objH%2F2%29%29%0A%09%09%7D%20else%20if%28arcT%20%3E%2090%20%26%26%20arcT%20%3C%20180%29%7B%0A%09%09%09console%2Elog%28%27Q2%27%29%0A%09%09%09angle%20%3D%2090%20-%20%28180%20-%20arcT%29%20%2F%2F%20adjacent%20angle%0A%09%09%09console%2Elog%28angle%29%0A%09%09%09radians%20%3D%20angle%20*%20Math%2EPI%20%2F%20180%0A%09%09%09nX%20%3D%20centerX%20%2B%20%28radius%20*%20Math%2Ecos%28radians%29%29%0A%09%09%09nY%20%3D%20centerY%20%2B%20%28radius%20*%20Math%2Esin%28radians%29%29%0A%09%09%09console%2Elog%28nX%20%2B%20%22%2C%20%22%20%2B%20nY%29%0A%09%09%09newPoint%20%3D%20new%20Point%28nX-%28objW%2F2%29%2CnY-%28objH%2F2%29%29%0A%09%09%7D%20else%20if%28arcT%20%3E%20180%20%26%26%20arcT%20%3C%20270%29%7B%0A%09%09%09console%2Elog%28%27Q3%27%29%0A%09%09%09angle%20%3D%20270%20-%20arcT%0A%09%09%09console%2Elog%28angle%29%0A%09%09%09radians%20%3D%20angle%20*%20Math%2EPI%20%2F%20180%0A%09%09%09nX%20%3D%20centerX%20-%20%28radius%20*%20Math%2Ecos%28radians%29%29%0A%09%09%09nY%20%3D%20centerY%20%2B%20%28radius%20*%20Math%2Esin%28radians%29%29%0A%09%09%09console%2Elog%28nX%20%2B%20%22%2C%20%22%20%2B%20nY%29%0A%09%09%09newPoint%20%3D%20new%20Point%28nX-%28objW%2F2%29%2CnY-%28objH%2F2%29%29%0A%09%09%7D%20else%20if%28arcT%20%3E%20270%29%7B%0A%09%09%09console%2Elog%28%27Q4%27%29%0A%09%09%09angle%20%3D%2090%20-%20%28360%20-%20arcT%29%0A%09%09%09console%2Elog%28angle%29%0A%09%09%09radians%20%3D%20angle%20*%20Math%2EPI%20%2F%20180%0A%09%09%09nX%20%3D%20centerX%20-%20%28radius%20*%20Math%2Ecos%28radians%29%29%0A%09%09%09nY%20%3D%20centerY%20-%20%28radius%20*%20Math%2Esin%28radians%29%29%0A%09%09%09console%2Elog%28nX%20%2B%20%22%2C%20%22%20%2B%20nY%29%0A%09%09%09newPoint%20%3D%20new%20Point%28nX-%28objW%2F2%29%2CnY-%28objH%2F2%29%29%0A%09%09%7D%0A%09%09objN%20%3D%20obj%2EduplicateTo%28newPoint%29%0A%09%09connectObjects%28objP%2CobjN%29%0A%09%09if%20%28i%20%3D%3D%20numObj%20-2%29%7B%0A%09%09%09%2F%2F%20connect%20to%20the%20starting%20shape%0A%09%09%09connectObjects%28objN%2Cobj%29%0A%09%09%7D%20else%20%7B%0A%09%09%09objP%20%3D%20objN%0A%09%09%7D%0A%09%7D%0A%7D

TIP: For those interested in the underlying logic of this automation tool, the script uses a basic trigonometry formula to calculate the x (horizontal) and y (vertical) coordinates for each of the individual arc-segment points on the circle: (x=r(cosA), y=r(sinA)) where r is the circle radius and A is the angle of the arc segment. Math is so cool!

formula-graph

And the image below shows connection lines edited to be curves:

circle-7-curved-lines

TIP: Change the value of the numObj variable in the script to be the number of diagram items you want, such as: 3, 4, 5, 6, 7, 8, or 9

Magnets

magnets-menu

By default, connection lines are drawn from the center of one graphic to the center of another graphic, as shown in the previous example. However, you can choose to “magnetize” the handles of a graphic so that connection lines will be drawn to them. A connection magnet is a place on a shape that attracts connected lines.

The pop-down menu under the Other Objects tab (macOS), lists the various options for determining which handles can receive a connecting line. This setting is currently not settable via a script, and so any scripts creating connections will honor the current setting of the object to be connected.

For example, the image below shows the result of the previous script, if the originating object has active magnets for the north and south handles (see below).

magnets-circle
UNDER CONSTRUCTION

This webpage is in the process of being developed. Any content may change and may not be accurate or complete at this time.

DISCLAIMER