Keeping the nodes inside group boundaries without resizing the group

The group has fixed size. I want to move nodes inside the group. Problem is when I am moving the nodes they go out of group boundaries and group also moving in the background (like parallax background). I can’t use grid layout because nodes can be randomly positioned inside the group and have to save their position even when they are rotated. This is before and after image :

here’s my template code :

var _0degreeGroupTemplate =
                        $(go.Group, "Horizontal",
                            {
                                rotatable: true,
                                locationSpot: go.Spot.Center,
                                rotateObjectName: "GROUP_RECTANGLE",
                                resizable: false,
                                //layout: $(go.GridLayout, { comparer: go.GridLayout.smartComparer, spacing: go.Size.parse(5), isOngoing: false })
                            }, new go.Binding("location", "loc").makeTwoWay(),
                            new go.Binding("angle", "angle").makeTwoWay(),
                            $(go.Panel, "Auto", { name: "GROUP_RECTANGLE" },
                                $(go.Shape, "Rectangle", { name: "SHAPE", parameter1: 10, height: 85 + 20, fill: "lightyellow" },
                                    new go.Binding("width", "nodeCount", function (v) { return v * 75 + 50; })),
                                $(go.Shape, "TopFrontSide", { name: "FRONTLINE", parameter1: 10, strokeWidth: 2, height: 85 + 20 },
                                    new go.Binding("stroke", "frontcolor"), new go.Binding("width", "nodeCount", function (v) { return v * 75 + 50; })),
                                $(go.TextBlock, { margin: 5, alignment: go.Spot.TopLeft, font: "Bold 12pt Sans-Sherif", width: 20 }, new go.Binding("text", "key")),
                                $(go.Placeholder, { padding: 5})  
                                    
                            )
                        );

You don’t show your node template. Try setting its Part.dragComputation to limit how far the user can drag it. I suggest that you start with the stayInGroup function provided as an example at https://gojs.net/latest/api/symbols/DraggingTool.html. You may need to adapt the code somewhat to meet your needs regarding the rotated rectangle of the containing Group.

While it is working fine when the group is horizontal, when I rotate the Group the nodes can be dragged out of the rectangle. For stayinGroup function I have tried setting resizeObjectName to SHAPE without success.

let _0degreeGroupTemplate =
                    $(go.Group, "Auto",
                        {
                            rotatable: true,
                            locationSpot: go.Spot.Center,
                            rotateObjectName: "GROUP_RECTANGLE",
                            resizable: false,
                            computesBoundsIncludingLinks: false,
                            computesBoundsAfterDrag: false,
                            resizeObjectName: "SHAPE",
                        }, new go.Binding("location", "locGroup").makeTwoWay(),
                        $(go.Panel, "Auto", { name: "GROUP_RECTANGLE" },
                            $(go.Shape, "Rectangle", { name: "SHAPE", parameter1: 10, height: 85 + 20, fill: "lightyellow" },
                                new go.Binding("width", "nodeCount", function (v) { return v * 75 + 50; })),
                            $(go.Shape, "TopFrontSide", { name: "FRONTLINE", parameter1: 10, strokeWidth: 2, height: 85 + 20 },
                                new go.Binding("stroke", "frontcolor"), new go.Binding("width", "nodeCount", function (v) { return v * 75 + 50; })),
                            $(go.TextBlock, { margin: 5, alignment: go.Spot.TopLeft, font: "Bold 12pt Sans-Sherif", width: 20 }, new go.Binding("text", "key"), new go.Binding("angle", "angle", function (n) { return -n; })),
                            $(go.Placeholder, { padding: 5 }),
                            new go.Binding("angle", "angle").makeTwoWay()
                        )
                    );
 let _0degreeNodeTemplate =
                    $(go.Node, "Auto",
                        {
                            rotatable: false,
                            deletable: false,
                            locationSpot: new go.Spot(0, 0, 0, 0),
                            dragComputation: scope.stayInGroup,
                            movable: true,
                            canMove: false,
                            margin: 1
                        },
                        new go.Binding("location", "loc").makeTwoWay(),
                        new go.Binding("angle", "angle").makeTwoWay(),
                        $(go.Panel, "Auto", { name: "NODE_RECTANGLE" },
                        $(go.Shape, "Rectangle", {
                            toMaxLinks: 1,
                            fromMaxLinks: 1,
                            width: 75,
                            height: 75,
                            stroke: "black",
                            strokeWidth: 1,
                            fromSpot: go.Spot.TopSide,
                            toSpot: go.Spot.TopSide,
                            portId: "",
                            cursor: "pointer",
                            fromLinkable: true, fromLinkableSelfNode: false, fromLinkableDuplicates: false,
                            toLinkable: true, toLinkableSelfNode: false, toLinkableDuplicates: false
                        }, new go.Binding("fill", "color"),
                            ),
                        $(go.TextBlock, "Default text", { margin: 6, font: "bold 18px sans-serif" },
                            new go.Binding("text", "name").makeTwoWay(), new go.Binding("angle", "angle", function (n) { return -n; })),
                        $(go.TextBlock, "Default text", { name:"TEXT_BLOCK", margin: 6, alignment: go.Spot.TopLeft, font: "10px sans-serif" },
                            new go.Binding("text", "ID_COLONNE").makeTwoWay(), new go.Binding("angle", "angle", function (n) { return -n; })),
                        )

                    );

That’s why I said about that stayInGroup function:

Yes noticed that. In that function it states that given the background shape it is trying to be within the shape… what is pt in the function parameter? and how dragComputation is done on every move ? the function working is not very obvious to me…

// try to stay within the background Shape of the Group
    var back = grp.resizeObject;

Yes, the dragComputation function is called for each moved Node during the drag. I think you only care about the Node and the proposed new location arguments, and you can ignore the third argument that is the new location point snapped to a grid.