How to draw transparent links

Hi Walter. I have any questions about Link. The first, I created link with linkLabel and wanna create transparent segment of Link when placed linkLabel. And the second Is it possible to make Links transparent at the points of intersection with Node?

Normally one makes the background of the label solid enough to hide the link path and anything else that might be behind it.

For the second question do you have a sketch or screenshot of what you have now and what you want instead?

If I try to makeImage from my Diagram with transparent background, the background of the label is visible.
For the second question attach sketch. Dont wanna use node background for the same reason that in the first case
Screenshot from 2022-12-20 22-23-31

I wanna use my diagrams with transparent background and not transparent elements are stoped me

What you see for a Link, besides any link labels including any arrowheads, is the Link.path, which is a Shape. Each Shape only has a single Shape.stroke property that controls how it is drawn. To avoid drawing the link path where the label is, you will may need to set the Shape.strokeDashArray so as to have a gap where the label is. Since your links probably have different lengths, you’ll need to set the Shape.strokeDashArray to account for the distance between the start of the path and the start of your label. And the gap that you specify in the strokeDashArray will need to match the diameter of the label.

This can be complicated to control, so I’m wondering if you wouldn’t rather implement your link labels as separate nodes.

Thank you for the sketch, but I don’t understand. On the left side there seems to be a Node, but how can there be only one Link unless that Link is not connected with that Node?

On the right side, if there are two Links that connect with that one Node, then you can get a gap between the end of the link path and the edge of the node/port by specifying fromShortLength and toShortLength to be a value larger than the default value of zero.

On sketch links not connecting to nodes. For example there are three nodes and the first and second are connected by the link and the third is placed on the link. Such example I wanna draw on sketch.

So that Node is unrelated to the Link? Does that mean that you want that Node to cause whatever is behind it to become transparent, just within the area occupied by the Node? If the user moved that Node, a hole will appear wherever they leave the Node? And what happens when they move that Node to partly overlap with another Node?

I don’t think there’s any easy solution for this. It would involve making an image from all of the links, punching transparent holes in that image where there are nodes, and then rendering that image instead of actually drawing all of the links.

Maybe you can suggest a better solution for solving my problem? Let me remind you that I need to make the link invisible if it crosses the node, so that the node has a transparent background. And all this so that when rendering the image I can make a transparent background for the picture.

To confirm, instead of “make the link invisible if it crosses the node” did you mean “make the link invisible where it crosses the node”?

Yes, “make the link invisible where it crosses the node”?

OK. It will be a while before I have time to work on this, if it’s even possible.

Thanks, will be waiting

Here’s an example of something that I think basically works, but it’s not something that we can afford to support.

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2022 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
const $ = go.GraphObject.make;

const myDiagram =
  $(go.Diagram, "myDiagramDiv",
    {
      "ViewportBoundsChanged": e => updateBackground(),
      "ModelChanged": e => { if (e.isTransactionFinished) updateBackground(); },
      "undoManager.isEnabled": true
    });
myDiagram.findLayer("Background").opacity = 0;  // links are normally hidden
const myBackgroundImage =  // this shows the links
  $(go.Part,
    { layerName: "Grid" },  // not pickable or selectable, not in document bounds
    $(go.Picture));
myDiagram.add(myBackgroundImage);

myDiagram.nodeTemplate =
  $(go.Node,  // assume the background is normally null
    new go.Binding("location", "loc", go.Point.parse),
    { locationSpot: go.Spot.Center },
    $(go.Panel, "Auto",
      { margin: 8 },
      $(go.Shape, { fill: null, portId: "" }),
      $(go.TextBlock, { margin: 8 },
        new go.Binding("text"))
    )
  );

myDiagram.linkTemplate =
  $(go.Link,
    { layerName: "Background", fromShortLength: 10, toShortLength: 10 },
    $(go.Shape),
    $(go.Shape, { toArrow: "Standard", segmentOffset: new go.Point(-10, 0) })
  );

myDiagram.model = new go.GraphLinksModel(
[
  { key: 1, text: "Alpha", color: "lightblue", loc: "0 0" },
  { key: 2, text: "Beta", color: "orange", loc: "200 0" },
  { key: 3, text: "Gamma", color: "lightgreen", loc: "0 200" },
  { key: 4, text: "Delta", color: "pink", loc: "200 200" },
  { key: 5, text: "Epsilon", color: "yellow", loc: "100 100" },
],
[
  { from: 1, to: 2 },
  { from: 1, to: 3 },
  { from: 3, to: 4 },
  { from: 4, to: 1 },
  { from: 2, to: 5 },
]);

function updateBackground() {
  const oldskips = myDiagram.skipsUndoManager;
  myDiagram.skipsUndoManager = true;
  // first just draw the links (i.e. just the "Background" Layer) to a canvas
  myDiagram.findLayer("Background").opacity = 1;
  const vb = myDiagram.viewportBounds;
  myDiagram.makeImageData({
    size: vb.size,
    maxSize: vb.size,
    position: vb.position,
    scale: 1,
    parts: myDiagram.findLayer("Background").parts,
    returnType: "ImageData",
    callback: imgdata => {
      myDiagram.findLayer("Background").opacity = 0;
      myDiagram.nodes.each(n => n.background = "black");
      // then draw everything but the links/"Background" Layer to an image
      const canvas = document.createElement("canvas");
      canvas.width = vb.width;
      canvas.height = vb.height;
      const ctx = canvas.getContext("2d");
      ctx.putImageData(imgdata, 0, 0);
      myDiagram.makeImageData({
        size: vb.size,
        maxSize: vb.size,
        position: vb.position,
        scale: 1,
        returnType: "Image",
        callback: img2 => {
          myDiagram.nodes.each(n => n.background = null);
          img2.onload = () => {
            // now draw that image so that it clears out where the nodes are
            ctx.globalCompositeOperation = "destination-out";
            ctx.drawImage(img2, 0, 0);
            // update the Picture
            myBackgroundImage.position = vb.position;
            const pic = myBackgroundImage.elt(0);
            pic.scale = 1;
            pic.desiredSize = vb.size;
            pic.element = canvas;
            myDiagram.skipsUndoManager = oldskips;
          }
        }
      })
    }
  });
}
  </script>
</body>
</html>

Oh, thanks. It is work))) How I should download Diagram image that to save all Diagram parts?

You’ll need to apply the same logic for each “page” that you want to render, rather than just for the viewport.