RotatingTool jumps on click when handleAngle is non-zero

Hi,

We’re seeing an issue where setting a non-zero handleAngle on RotatingTool causes the node to immediately snap to a wrong angle the moment you click the handle, before any dragging occurs. With handleAngle = 0 it works fine.

Setup:
const tool = new go.RotatingTool();
tool.handleAngle = 135;
tool.handleDistance = 25;
diagram.toolManager.rotatingTool = tool;

To reproduce: Select the node and click the rotation handle — the node jumps instantly without any mouse movement.

I’ve attached a minimal repro below. It includes a toggle between handleAngle = 0 (no jump) and handleAngle = 135 (jumps) so you can compare directly.


  <!DOCTYPE html>                                                                                                                                                                                                                 
  <html>                                                    
  <head>
    <script src="https://unpkg.com/[email protected]/release/go.js"></script>
  </head>                                                                                                                                                                                                                         
  <body>
    <p>                                                                                                                                                                                                                           
      <label><input type="radio" name="mode" value="0" onchange="setHandleAngle(0)"> handleAngle = 0 (no jump)</label>
      <label><input type="radio" name="mode" value="135" checked onchange="setHandleAngle(135)"> handleAngle = 135 (jumps on click)</label>                                                                                       
    </p>                                                                                                                                                                                                                          
    <div id="diagram" style="width:600px;height:400px;border:1px solid #ccc"></div>                                                                                                                                               
                                                                                                                                                                                                                                  
    <script>                                                
      const $ = go.GraphObject.make;                                                                                                                                                                                              
                                                            
      const diagram = $(go.Diagram, 'diagram', {
        'undoManager.isEnabled': true,
      });

      diagram.nodeTemplate = $(go.Node, 'Auto',                                                                                                                                                                                   
        { rotatable: true },
        $(go.Shape, 'Rectangle', { fill: '#4a90d9', stroke: null, width: 120, height: 80 }),                                                                                                                                      
        $(go.TextBlock, 'Rotate me', { stroke: 'white', font: 'bold 13px sans-serif' })
      );                                                                                                                                                                                                                          
   
      diagram.model = new go.GraphLinksModel([{ key: 1 }]);                                                                                                                                                                       
                                                            
      function setHandleAngle(angle) {
        const tool = new go.RotatingTool();
        tool.handleAngle = angle;                                                                                                                                                                                                 
        tool.handleDistance = 25;
        diagram.toolManager.rotatingTool = tool;                                                                                                                                                                                  
      }                                                     

      setHandleAngle(135);
    </script>
  </body>
  </html>

I tried overriding computeRotate with a delta approach (record startAngle + startNodeAngle in doActivate, return startNodeAngle + currentAngle - startAngle) which eliminates the jump, but it breaks the built-in snapping
since GoJS’s snap logic lives inside computeRotate.

Is there a supported way to fix this without losing snapping?

Thanks

Thanks for the sample. That’s weird – I tried it with different non-zero angles, and the only one that had the bad behavior you report is at 135 degrees. I’ll investigate.

[EDIT] Actually, the implementation has a comment saying that angles other than a multiple of 90 degrees doesn’t work well. I guess it’s something we forgot to improve. But in our defense, the documentation for RotatingTool.handleAngle specifies that the value must be a multiple of 90, so it’s technically not a bug. RotatingTool | GoJS API

How important is it to have RotatingTool.handleAngle not be a multiple of 90 degrees? In trying to implement it more generally, I can see why we gave up at the time.

1 Like

We will remove the restriction on the RotatingTool.handleAngle in version 4.0.