Search code examples
paperjs

How to access symbol definition attributes to perform transformation in paperjs


I am having issues rotating my symbol around a specific pivot point.

Here is my code :

    var path_tank_left_track = new Path({
      segments: [[0,0], [10, 0], [10,40], [0,40]], strokeColor: 'black',
      closed: true
    });

    var path_tank_right_track = new Path({
      segments: [[40,0], [50, 0], [50,40], [40,40]], strokeColor: 'black',
      closed: true
    });

    var path_tank_body = new Path({
      segments: [[10,5], [40,5], [40,35], [10,35]], strokeColor: 'black',
      closed: true
    });

    var path_tank_gun = new Path({
      segments: [[23,15], [23,0], [27, 0], [27, 15]],
      strokeColor: 'black',
      pivot: [25,15],
      name: 'gun'
    });

    var path_arena_separation = new Path(new Point(view.size.width/2,0),
    new Point(view.size.width/2, view.size.height));
    path_arena_separation.strokeColor = 'black';
    path_arena_separation.closed = true;

    var whole_tank = new Group();
    whole_tank.addChild(path_tank_left_track);
    whole tank.addChild(new Point(5,20)); // trying to add the middle of the left track pivot point
    whole_tank.addChild(path_tank_body);
    whole_tank.addChild(path_tank_right_track);
    whole tank.addChild(new Point(50,20)); // trying to add the middle of the right track pivot point
    whole_tank.addChild(path_tank_gun);

    // Create a symbol definition from the path:
    var definition = new SymbolDefinition(whole_tank);

    var instance1 = definition.place();
    instance1.position = new Point(view.size.width/4, view.size.height/2);
    var instance2 = definition.place();
    instance2.position = new Point(3*view.size.width/4, view.size.height/2);

    function onFrame(event) {
      instance1.rotate(1, instance1.definition.item.children[1]);
    }

As you can see, at the onFrame function, I'm trying to rotate the instance by 1 degree every frame around the point I created earlier. But I get an error saying the item_remove is not a function in the paper-full.js.

I'm confused, I tried to create a path with a single point and add it to the group but it did not let me.

If I modify the code to make the gun rotate on it's pivot instead, it does work :

function onFrame(event) {
  instance1.definition.item.children['gun'].rotate(1, instance1.definition.item.children['gun'].pivot);
}

The gun does rotate around the proper pivot and the pivot stays attached to the symbol even if the symbol moves around. How could I achieve that behavior but turning the whole tank around a specific point relative to the center of the tank?

Thank you for your help, let me know if I should include more detail.


Solution

  • Your code is crashing because you try to add a point (and not a path containing a single point as you seems to be trying to) as a group child, which is not what API expects.

    To create a path containing a single point, you have to do this:

    var path = new Path(new Point(x,y));
    

    But I think the idea of adding a single point path as a child to later retrieve its position to use it as a pivot point is wrong in your case.
    The fact that you are creating each tank as a Symbol implies that you won't have access to its own children.
    You can instead, before placing your symbols, store 2 vectors: one from center to left and one from center to right. They will later help you calculating left / right track positions.

    Here is a Sketch adapted from your code, demonstrating this.

    var path_tank_left_track = new Path({
        segments   : [ [ 0, 0 ], [ 10, 0 ], [ 10, 40 ], [ 0, 40 ] ],
        strokeColor: 'black',
        closed     : true
    });
    
    var path_tank_right_track = new Path({
        segments   : [ [ 40, 0 ], [ 50, 0 ], [ 50, 40 ], [ 40, 40 ] ],
        strokeColor: 'black',
        closed     : true
    });
    
    var path_tank_body = new Path({
        segments   : [ [ 10, 5 ], [ 40, 5 ], [ 40, 35 ], [ 10, 35 ] ],
        strokeColor: 'black',
        closed     : true
    });
    
    var path_tank_gun = new Path({
        segments   : [ [ 23, 15 ], [ 23, 0 ], [ 27, 0 ], [ 27, 15 ] ],
        strokeColor: 'black',
        pivot      : [ 25, 15 ],
        name       : 'gun'
    });
    
    var path_arena_separation         = new Path(new Point(view.size.width / 2, 0), new Point(view.size.width / 2, view.size.height));
    path_arena_separation.strokeColor = 'black';
    path_arena_separation.closed      = true;
    
    var whole_tank = new Group();
    whole_tank.addChild(path_tank_left_track);
    whole_tank.addChild(path_tank_left_track);
    whole_tank.addChild(path_tank_body);
    whole_tank.addChild(path_tank_right_track);
    whole_tank.addChild(path_tank_gun);
    
    // store vectors from bounds center to tracks middle points
    var tankCenter       = whole_tank.bounds.center;
    var leftTrackCenter  = new Point(5, 20);
    var rightTrackCenter = new Point(50, 20);
    var leftVector       = leftTrackCenter - tankCenter;
    var rightVector      = rightTrackCenter - tankCenter;
    
    // Create a symbol definition from the path:
    var definition = new SymbolDefinition(whole_tank);
    
    var instance1      = definition.place();
    instance1.position = new Point(view.size.width / 4, view.size.height / 2);
    var instance2      = definition.place();
    instance2.position = new Point(3 * view.size.width / 4, view.size.height / 2);
    
    function onFrame(event)
    {
        // calculate pivot point position
        // first we rotate vector accordingly to instance current rotation
        var rotatedVector = rightVector.rotate(instance1.rotation);
        // then we add it to current tank center
        var point = instance1.bounds.center + rotatedVector;
    
        // turn right
        instance1.rotate(1, point);
    }