Custom link shape

I am trying to create a custom link that consists of three stacked lines. I have seen the example that uses the pathPAttern approach, but it becomes very rough when used with orthogonal links. The corners are far from smooth. I have created an extension that offsets the original line, however Gojs only draws the last line.

function tripleLineLink() {
	go.Link.call(this);
}

go.Diagram.inherit(tripleLineLink, go.Link);

tripleLineLink.prototype.makeGeometry = function () {
	const originalGeomtry = go.Link.prototype.makeGeometry.call(this);
	const upperLine = go.Link.prototype.makeGeometry.call(this).offset(10, -50);
	const lowerLine = go.Link.prototype.makeGeometry.call(this).offset(-10, 50);

	const combined = go.Geometry.parse(
		`${go.Geometry.stringify(originalGeomtry)} ${go.Geometry.stringify(
			upperLine
		)} ${go.Geometry.stringify(lowerLine)}`
	);

	return combined;
};

this results in a svg path string that describes three different lines. Somehow Gojs only draws the path from the last M command.

image
As you can see in the image, only the lowerLine path is drawn

Is this expected behaviour and is there a way achieve a smooth three line link?

Best,

Niek

Yes, sharp corners are a problem for Shape.pathPattern.

Stringifying and parsing while computing geometries is probably not so good for performance. But maybe you don’t need to compute your own Geometry in a custom Link class. Would something like this do?

  $(go.Link,
    { routing: go.Link.Orthogonal },
    $(go.Shape, { isPanelMain: true, strokeWidth: 10, stroke: "black" }),
    $(go.Shape, { isPanelMain: true, strokeWidth: 6, stroke: "white" }),
    $(go.Shape, { isPanelMain: true, strokeWidth: 2, stroke: "black" })
  )

It could be a final solution. However, we have a grid background and ideally you can see the grid through the three lines. So a hint in a different direction would be welcome.

Yes, the “white” (or whatever background color you want) is solid, in order to block out the middle of the wider “black” stroke.

Sorry, I can’t think of a better idea right now.

EDIT: actually, assuming your links are orthogonal, if you use Shape.pathPattern and you make the corners rounded by setting Link.corner to some reasonable value, does that produce a better visual rendering? Is your pathPattern object is only one pixel wide?

I’ve already set the Link.corner to high values, but instead of becoming more smooth gaps show up between the pattern parts. My path pattern was the copy from the triple line example:

'M0 0 L1 0 M0 3 L1 3 M0 6 L1 6'

Which should be 1px, making the the line end smaller doesn’t help.

You didnt answer my initial question, Gojs doesn’t work correctly with more than one path? Or to better phrase it, if an M command is in the geometry string it ignores everything before and only renders what comes after?

Sorry, I couldn’t tell from your one screenshot what was wrong and what you wanted instead.

Here are two examples of overriding Link.makeGeometry:
https://gojs.net/latest/samples/taperedLinks.html
https://gojs.net/latest/samples/multiArrow.html

So, yes, you could override makeGeometry to do what you want. But I think you’ll find that it is more difficult than what you tried at first. There is only one Geometry for a Link, and I think you will need to make sure that when there is a turn that the PathFigure on the outside or the turn/curve is longer than the PathFigure on the inside of the turn/curve.