NPM and extensions

GoJS is downloadable as NPM package but it’s not possible to easily use extensions because it not export the main function used as class. Is this possible you add this important feature in your roadmap. When we work with a framwork like React/Angular it’s an essential need.

I have duplicate the CurvedLinkReshapingTool in my project and refactor some element asked by my linter, but that doesnt work. The curviness change each time I drag the handle but the link is not updated. An idea why ?

import go from 'gojs';

export default function CurvedLinkReshapingTool() {;
  this._originalCurviness = NaN;

go.Diagram.inherit(CurvedLinkReshapingTool, go.LinkReshapingTool);

CurvedLinkReshapingTool.prototype.makeAdornment = function(pathshape) {
  const link = pathshape.part;
  if (link !== null && link.curve === go.Link.Bezier && link.pointsCount === 4) {
    const adornment = new go.Adornment();
    adornment.type = go.Panel.Link;
    const h = this.makeHandle();
    this.setReshapingBehavior(h, go.LinkReshapingTool.All);
    h.cursor = 'move';
    adornment.category =;
    adornment.adornedObject = pathshape;
    return adornment;
  return, pathshape);

CurvedLinkReshapingTool.prototype.doActivate = function() {;
  this._originalCurviness = this.adornedLink.curviness;

CurvedLinkReshapingTool.prototype.doCancel = function() {
  this.adornedLink.curviness = this._originalCurviness;;

CurvedLinkReshapingTool.prototype.reshape = function(newpt) {
  const link = this.adornedLink;
  if (link !== null && link.curve === go.Link.Bezier && link.pointsCount === 4) {
    const start = link.getPoint(0);
    const end = link.getPoint(3);
    const ang = start.directionPoint(end);
    const mid = new go.Point((start.x + end.x) / 2, (start.y + end.y) / 2);
    const a = new go.Point(9999, 0).rotate(ang + 90).add(mid);
    const b = new go.Point(9999, 0).rotate(ang - 90).add(mid);
    const q = newpt.copy().projectOntoLineSegmentPoint(a, b);
    let curviness = Math.sqrt(mid.distanceSquaredPoint(q));
    if (link.fromPort === link.toPort) {
      if (newpt.y < link.fromPort.getDocumentPoint(go.Spot.Center).y) curviness = -curviness;
    } else {
      const diff = mid.directionPoint(q) - ang;
      if ((diff > 0 && diff < 180) || (diff < -180)) curviness = -curviness;

    link.curviness = curviness; // <-- this value change each time I drag the handle
    return q;
  }, newpt);

We’re rewriting the extensions in TypeScript right now. After this long weekend holiday I’ll see if that class is ready for you.

Great to hear walter !

Walter, in this sample “State Chart With Incremental Saves” it’s possible to reshape a link with basic bezier curve handles. It’s better than just change the curviness. It seem just property has changed : ‘reshape: true’. But in my case I dont see this handles. What are the prerequisites to activate this feature ?

Don’t use the CurvedLinkReshapingTool.

Sure :) It’s the case… my code :

  diagram.toolManager.linkingTool.temporaryLink = this.getLinkTemplate(true);
  diagram.toolManager.relinkingTool.temporaryLink = this.getLinkTemplate(true);
  diagram.linkTemplate = this.getLinkTemplate();

And the link template :

 getLinkTemplate(temporary = false) {
    return this.go(go.Link,
        selectionAdorned: false,
        routing: go.Link.Bezier,
        curve: go.Link.Bezier,
        relinkableFrom: true,
        relinkableTo: true,
        reshapable: true,
        opacity: 0.3,
        toEndSegmentLength: 60,
        fromEndSegmentLength: 60,
        adjusting: go.Link.Stretch,
          strokeWidth: 3,
          stroke: '#CCCCCC',
          strokeDashArray: temporary ? [6, 2] : null,
      new go.Binding('curviness', 'curviness').makeTwoWay(),
      new go.Binding('points').makeTwoWay(),

I have no handles…

Ooops – Link.routing cannot be go.Link.Bezier.

Humm same thing with

routing: go.Link.Normal,

Setting Link.curve to go.Link.Bezier and Link.reshapable to true, should result in this behavior, taken from the unmodified State Chart sample:

This assumes that the nodes (and links) and layout do not set fromSpot and toSpot.

Is that not what you want?

No :) In my case fromSpot and toSport are sets. I want the handles to manually find a perfect place for the link.

I don’t understand what you want. By default for Bezier curve links you’ll get two handles, which give maximum flexibility for a cubic Bezier curve. By using the CurvedLinkReshapingTool you’ll just get one handle, which is simpler to use and adequate for many cases.

Walter I dont want to use CurvedLinkReshapingTool, I tried this feature before to know the default reshaping with bezier curve. I just want to reshape a link between two ports (fromSpot / toSpot).

  • First question is this possible ?
  • Second question why in my case that doen’t work my code seem to be correct (without the routing set to bezier) ?

Because you have set the fromSpot and toSpot to specific Spots. (I didn’t see your screenshot until after I had posted my comment about not setting the spots for the links.) That removes the freedom to adjust the positions of the control points, thereby disallowing reshaping handles at those control points.

You could increase the fromEndSegmentLength and toEndSegmentLength.

Ok I have try without fromSpot and toSpot, that work but it’s not usable like I want As you can see, it’s possible to move the link abobe the module. I suppose you have no other solution…

What I just said: [quote=“walter, post:13, topic:8833”]
You could increase the fromEndSegmentLength and toEndSegmentLength.

You could do that in a custom LinkReshapingTool, instead of setting the Link.curviness as CurvedLinkReshapingTool does.

By the way, we will be adding our modularized and translated to TypeScript extensions starting with our next release, 1.7.16.

Do you have a date ?

Still need to fix a few things, so maybe next week.

OK, we still haven’t finished translating the bigger extensions, but most of them are now at: GoJS® Extensions of Diagramming for HTML and Canvas by Northwoods Software®

Tell us if you see any errors.

Ok Walter thanks !