Skip to main content
Ku11
Inspiring
January 3, 2022
Answered

How to change the StrokeCap of all objects in a few layers

  • January 3, 2022
  • 1 reply
  • 1209 views

hello,everyone.

i want to change the strokeCap of all objects in a particular layer.

var document = app.activeDocument;
var allLayers = app.activeDocument.layers; 
var testLayer = ["a", "b"];


function lineFormat(LayerName) {
    //Select objects in layer
    document.activeLayer = document.layers[LayerName]; 
    //document.activeLayer.hasSelectedArtwork = true; 
    //Change Style
    document.activeLayer.pathItems.stroked = true;    // open stroke
    document.activeLayer.pathItems.strokeCap = StrokeCap.BUTTENDCAP;//ROUNDENDCAP, PROJECTINGENDCAP
    document.activeLayer.pathItems.strokeJoin = StrokeJoin.ROUNDENDJOIN;//BEVELENDJOIN, MITERENDJOIN

    //Deselect objects in layer
    //document.activeLayer.hasSelectedArtwork = false;
}


for (var i = 0, il = allLayers.length; i < il; i++) {
    var curLayer = allLayers[i]
    if (curLayer = testLayer[i]) {
        //if layer name found
        lineFormat(testLayer[i]) 
    }
}   

then,i wrote the code as I understood it, but nothing happened to it for now, I don't know how to fix this code

Anyone can help me?

 

 

This topic has been closed for replies.
Correct answer Inventsable

Here is the test file

https://file.io/mbKXVsChYCgn


Sorry, had a typo and a faulty condition. Serves me right for so confidently offering recursion thinking I had cracked it so easily ha, I've verified the below on your file:

 

var targetLayers = ["Test"];

function getAllPathItems(parent) {
  var list = [];
  for (var i = 0; i < parent.pageItems.length; i++) {
    var item = parent.pageItems[i];
    if (item.pageItems && item.pageItems.length)
      list = [].concat(list, getAllPathItems(item));
    else if (/path/i.test(item.typename) && !/compound/i.test(item.typename))
      list.push(item);
  }
  return list;
}

function getLayer(layerName) {
  try {
    return app.activeDocument.layers.getByName(layerName);
  } catch (err) {
    return null;
  }
}

function restyleAllPathItemsWithin(layers) {
  app.selection = null;
  for (var i = 0; i < layers.length; i++) {
    var layer = getLayer(layers[i]);
    if (!layer) continue;
    else {
      var list = getAllPathItems(layer);
      for (var index = 0; index < list.length; index++) {
        var pathItem = list[index];
        pathItem.stroked = true; // open stroke
        pathItem.strokeCap = StrokeCap.BUTTENDCAP; //ROUNDENDCAP, PROJECTINGENDCAP
        pathItem.strokeJoin = StrokeJoin.ROUNDENDJOIN; //BEVELENDJOIN, MITERENDJOIN
      }
    }
  }
}

restyleAllPathItemsWithin(targetLayers);

 I'm not sure if you're wanting to target only specific layers by name or if you're just trying to change all document strokes -- you could do that though. If the goal is to change all strokes we could just feed a list of all the layers into the main function, and it might be easier to choose which layers (or names of annotation like "LWPOLYLINE") to exclude rather than include. Or target all "LINE" group children, etc.

1 reply

Inventsable
Legend
January 3, 2022

Hello, consider this:

 

var document = app.activeDocument;
var allLayers = app.activeDocument.layers;
var testLayers = ["Test"];

// Why do this? Because if we query a layer name that doesn't exist, it causes silent failure.
function getLayer(layerName) {
    try {
        return document.layers.getByName(layerName);
    } catch(err) {
        return null;
    }
}

function restyleAllPathItemsWithin(layers) {
    // An alternative to deselect all artwork, though it shouldn't actually matter here
    // because we can change the strokes regardless of whether other art is selected
    app.selection = null;

    // Iterate through our layer list:
    for (var i = 0; i < layers.length; i++) {
        // Get our target layer:
        var layer = getLayer(layers[i]);

        // If a layer wasn't found or there are no items to restyle, continue looping:
        if (!layer || !layer.pathItems.length) continue;
        else {
            // Layer.pathItems is a collection of objects, not a single one.
            // To restyle any given object, we have to iterate over them individually:
            for (var index = 0; index < layer.pathItems.length; index++) {
                var pathItem = layer.pathItems[index];
                pathItem.stroked = true;    // open stroke
                pathItem.strokeCap = StrokeCap.BUTTENDCAP;//ROUNDENDCAP, PROJECTINGENDCAP
                pathItem.strokeJoin = StrokeJoin.ROUNDENDJOIN;//BEVELENDJOIN, MITERENDJOIN
            }
        }
    }
}

restyleAllPathItemsWithin(testLayers);

Essentially you have everything correct here, but the issue is that you're trying to assign properties to an Array-like collection (pathItems) rather than one entry of that collection (i.e., pathItems[0]).

Ku11
Ku11Author
Inspiring
January 3, 2022

thanks you for you help!!!but it seems that the straight lines I import from DWG still need to be ungrouped before they work.

Inventsable
Legend
January 3, 2022

No worries. That's true, it has to do with how AI contains items. For instance:

  • layer.pathItems - This is a collection of root-level paths on the layer.
  • layer.pageItems - This is a collection of any type of root-level object on the layer.

 

Layer.pathItems is not every path inside of the layer, only every path whose parent is the layer. The issue would be that a group counts as a pageItem, so a path inside of a group would be something more like:

  • layer.pageItems[0].pathItems[2] <= Because the pathitem parent is the group, not the layer. Pathitems may exist only in this group

 

Layer.pathItems only contains paths that aren't in a group or a compound path, if the parent is explicitly the layer. We can fix this for shallow groups pretty easily:

 

function getAllPathItemsInLayer(layer) {
  var list = [];
  for (var i = 0; i < layer.pageItems.length; i++) {
    var item = layer.pageItems[i];
    // If this is a group or compound path, we need to add it's pathItems to our list:
    if (
      /group|compound/i.test(item.typename) &&
      item.pathItems &&
      item.pathItems.length
    ) {
      for (var e = 0; e < item.pathItems.length; e++)
        list.push(item.pathItems[e]);
    } else if (/path/i.test(item.typename)) {
      // Otherwise if this is a pathItem, we can add it to the list directly:
      list.push(item);
    }
  }
  return list;
}

function getLayer(layerName) {
  try {
    return document.layers.getByName(layerName);
  } catch (err) {
    return null;
  }
}

function restyleAllPathItemsWithin(layers) {
  app.selection = null;
  for (var i = 0; i < layers.length; i++) {
    var layer = getLayer(layers[i]);
    if (!layer || !layer.pathItems.length) continue;
    else {
      // We need to gather any children pathItems in case their parent is a Group/Compound Path
      var list = getAllPathItemsInLayer(layer);
      for (var index = 0; index < list.length; index++) {
        var pathItem = list[index];
        pathItem.stroked = true; // open stroke
        pathItem.strokeCap = StrokeCap.BUTTENDCAP; //ROUNDENDCAP, PROJECTINGENDCAP
        pathItem.strokeJoin = StrokeJoin.ROUNDENDJOIN; //BEVELENDJOIN, MITERENDJOIN
      }
    }
  }
}

restyleAllPathItemsWithin(testLayers);

 

But for complicated groups (pathItems within groups within groups or any dynamic nesting) then we'd have to do some recursion and it's likely going to look either very intimidating and confusing or very simple and confusing.