Skip navigation
alexthebake
Currently Being Moderated

How would I scale every object to some percent?

Jul 11, 2012 8:53 AM

Tags: #script #javascript #indesign #indesign_cs5.5 #scripting #object #scale #automation

Hi,

 

I'm working on a script that creates elements, and occasionally changes the size of the page. I want to add a parameter to my Dialog box called "scale." It should be a percentage value, and it should simply scale all objects to that percentage.

The point of this parameter would be to accomodate InDesign Page size limit. The only way I can think of to implement this would be to multiply every single number I have by that percent. However, this seems like a lot of work, and it seems like the sub-optimal approach.

 

Is there some other way to implement this?

 
Replies
  • Currently Being Moderated
    Jul 11, 2012 1:44 PM   in reply to alexthebake

    One approach might be to group all the items on the page, scale the group and then ungroup.

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 12:55 AM   in reply to Larry G. Schneider

    And to refine this approach that Larry mentioned:

    do the grouping of the objects layer by layer, so you will not have all the objects in one layer after ungrouping.

     

    To start  all that, you do not work directly with the page object, but with the window object and set its activePage to the page you want. As a second ingredience of this recipe we have the "activeLayer" object of the window object.

     

    var myDoc = app.documents[0];
    var myActivePage = myDoc.windows[0].activePage = myPageThatIsChangedInSize;
     
    //Loop through all the layers of "myDoc":
    for(var n=0;n<myDoc.layers.length;n++){
        var myActiveLayer = myDoc.windows[0].activeLayer = myDoc.layers[n];
     
        //Case 1: there are more than 1 page items in the active layer:
        if(myActiveLayer.pageItems.length>1){
            //Unlock all pageItems:
            myActiveLayer.pageItems.everyItem().locked = false;
            //Add a group with all page items on the active layer:
            var myGroup = myActivePage.groups.add(myActiveLayer.pageItems.everyItem());
            //myGroup.scale();
            //myGroup.ungroup();
            };
     
        //Case 2: there is only 1 page item in the active layer and you cannot group 1 single item:
        if(myActiveLayer.pageItems.length==1){
            //No need to group something, just scale:
            myActiveLayer.pageItems[0].locked = false;
            //myActiveLayer.pageItems[0].scale();
            }; 
     
        };
    

     

    As center of the scaling you have to use the center of your active page.
    Caution: With that approach all objects on the pasteboard are also scaled.

     

    Of course you can further refine the script and store the IDs of all locked pageItems in an array for locking again after scaling them.

     

    Hope that helps…

     

    Uwe

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 4:42 AM   in reply to Laubender

    Uwe

     

    Nice answer but won't you run into problems of grouping groups if there are groups already on the page, which is if I remember a bit complicated.

     

    Trevor

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 4:49 AM   in reply to Laubender

    Sorry Uwe

     

    My mistake, does work with grouped objects, (I decided to test the script)

     

    However you do have to change the second line to

    var myActivePage  = myPageThatIsChangedInSize = myDoc.windows[0].activePage;

     

    Trevor

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 7:10 AM   in reply to Trevorׅ

    @Trevor – that "myPageThatIsChangedInSize" is just a dummy variable.

    You can set it to any value provided it is a valid page object.

     

    //Example for the first page of your document:
    var myActivePage = myDoc.windows[0].activePage = myDoc.pages[0];
    

     

    Uwe

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 9:20 AM   in reply to Laubender

    Uwe

     

     

    I should have understood that.

     

    Just 2 points

     

    1) Case 2 should come before case 1 otherwise case 2 will always be applied after the grouping and the object will be scaled twice

    2) When the active layer has graphics on other pages (could well happen ) then the line

    var myGroup = myActivePage.groups.add(myActiveLayer.pageItems.everyItem())
    

    is no good

     

    Trevor

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 10:56 AM   in reply to Trevorׅ

    I will chip in as I have tried this before but not full sucess… May be someone can see the errors of my ways? Some parts I just can't get to play…

    Firstly I don't like the idea of grouping to scale/transform ( goofs layers and no need ). You can use the scale tool on selection and scale without grouping?

    If you want page items then you could just target by page that way it no effect the pasteboard items…

    If you want to apply a scale factor to pre-existing art why not transform it? Thats what I would do in the GUI…

    Anyhows you can try this snippet it scales all the page stuff in my basic test file… But I can only get it to do so from page centre? You could move it all after but that was not what I was trying to achieve…

     

    #target indesign
    #targetengine muppet
     
    app.activate();
     
    app.transformPreferences.whenScaling = WhenScalingOptions.APPLY_TO_CONTENT;
    app.transformPreferences.adjustStrokeWeightWhenScaling = true;
    app.transformPreferences.dimensionsIncludeStrokeWeight = true;
    app.transformPreferences.transformationsAreTotals = false;
    app.transformPreferences.showContentOffset = false;
     
    var scMat = app.transformationMatrices.add( 1.5, 1.5 ); //150% scale matrix
     
    var doc = app.activeDocument;
     
    //$.writeln( doc.layoutWindows.item(0).transformReferencePoint );
     
    doc.layoutWindows.item(0).transformReferencePoint = [0,0]; // Can't get this to play?
                                   
    var pItems = doc.pages.item(0).pageItems.everyItem().getElements();
     
    //var p = doc.pages.item(0).allPageItems; Wrong one… not the same as above
     
    for ( var i = 0; i < pItems.length; i++ ) {
      
              $.writeln( pItems[i].visibleBounds[0] + ' ' + pItems[i].visibleBounds[1] );
      
              try {
      
              pItems[i].transform( CoordinateSpaces.SPREAD_COORDINATES,
      
                        [ -pItems[i].visibleBounds[0], -pItems[i].visibleBounds[1] ], scMat ); // Hum what I do wrong here?
      
              } catch(e) { $.writeln(e) }; // This value would cause one or more objects to leave the pasteboard.
      
    };
    
     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 11:55 AM   in reply to Muppet Mark

    I agree that grouping seems like an unnecessary and potentially destructive step to accomplish this.

     

    You need to set the second ("from") argument to transform to the same point for every transform() call. So, this:

     

    var origin = doc.pages.item(0).resolve(AnchorPoint.TOP_LEFT_ANCHOR,CoordinateSpaces.SPREAD_COORDINATES)[0];
    

     

    after your doc declaration, to anchor everything to the top left of the page. (You could set it to the top-left of your top-leftmost page item or somewhere else instead.)

     

    And then this:

     

    pItems[i].transform( CoordinateSpaces.SPREAD_COORDINATES, origin, scMat );
    

     

    for your transform() call.

     

    See this post from Marc: http://forums.adobe.com/message/4179133#4179133 .

     

    Jeff

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 12:13 PM   in reply to absqua

    Oh thanks Jeff not seen that… I will take a look and see where I went wrong… I would have expected my negative use of bounds to have been the page origin… may be not?

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 12, 2012 10:59 PM   in reply to Trevorׅ

    @Trevor – you are absolutely right. I used the wrong scope with the layer object, that includes all pages. That would only work in one spread documents or documents with objects only on one spread.

     

    To make this all work with groups (you see, I still have not abandoned the idea of scaling groups completely) we could go through all page items of the page we want to scale using the itemLayer property to sort after layer and act on that information for building groups…

     

    Uwe

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points