[AI CC2022] Редактирование скрипта для автоматического обрезания и удаления векторных объектов вне артбордов

Ant-3

Участник
Топикстартер
Сообщения
57
Реакции
2
Доброго дня!
Недавно наткнулся в интернетах на скрипт для автоматического обрезания и удаления векторных объектов вне главного артборда.
Он практически моментально справляется со своей задачей при наличии большого количества объектов, что для меня важно.

У меня в данный момент имеется несколько альтернативных скриптов, но у каждого из них при работе с большим количеством объектов возникают глюки или работают очень медленно:

Скрипт "Cropulka" зависает намертво,
Скрипты "Cropper FREE" и "Super Magic Eraser" работают очень долго.


Ниже скрипт, который мне понравился, но в данном виде он работает только на один артборд. Может его можно заставить работать сразу на все артборды в документе (ну или чтобы он поэтапно проходился по каждому артборду)? Самостоятельно не понял как это сделать.
И надеюсь, что если его переделать, то он как "Cropper FREE" и "Super Magic Eraser" не станет так же медленно работать, на 4 артборда порой у этих скриптов уходит 10-15 минут.


Код:
function is_on_border(ol, or, ot, ob, h, w)
{
    var a = ((ob<0) && (ot>-h));
    var b = ((or>0) && (ol<w));
    if ((!a)||(!b))
    {
        return 2;
    }
    if (((ol < 0) && (or > 0)) || ((ol < w) && (or > w)) )
    {
        if (a)
        {
            //на границе
            return 1;
        }
        else
        {
            //за границей
            return 2;
        }
       
    }
    if (((ot > 0) && (ob < 0)) || ((ot > -h) && (ob < -h)))
    {
        if (b)
        {
            //на границе
            return 1;
        }
        else
        {
            //за границей
            return 2;
        }
    }
    return 0;
}

function process_objects(pageItems, newGroup, h, w)
{  
    var thisItem;
    for(var i = pageItems.length - 1; i > -1;  i--){
            thisItem = pageItems[i];                    
            res = is_on_border(thisItem.left, thisItem.left + thisItem.width, thisItem.top, thisItem.top - thisItem.height, h, w);
            if ((res==1)&&(thisItem!=newGroup))
            {      
                thisItem.move(newGroup, ElementPlacement.PLACEATBEGINNING);            
            }
            else if (res==2)
            {
                thisItem.remove();
            }          
        };
}

function ArtboardCrop(){
    app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
    if(app.documents.length  > 0){
        var doc = app.activeDocument;
       
        var newGroup = doc.groupItems.add();    
        h = doc.height;
        w = doc.width;

        process_objects(doc.layers[0].pageItems, newGroup, h, w);
        var activeArtboardIndex = doc.artboards.getActiveArtboardIndex();
        var rc =  doc.artboards[activeArtboardIndex].artboardRect;
        var newRect = doc.pathItems.rectangle(rc[1],rc[0],rc[2],-rc[3]);
        newRect.filled = false;
        newRect.stroked = false;
        newRect.move(newGroup, ElementPlacement.PLACEATBEGINNING);
        newGroup.selected = true;
        //app.executeMenuCommand("selectall");
       
        app.executeMenuCommand("Live Pathfinder Crop");
        app.executeMenuCommand("expandStyle");
    }
}
ArtboardCrop();
 
Последнее редактирование:

Drawer

Участник
Сообщения
1 754
Реакции
773
Наверное так
JavaScript:
for (var a=0; a < app.activeDocument.artboards.length; a++) {
    app.activeDocument.artboards.setActiveArtboardIndex(a);
    ArtboardCrop();
}
Но чет у меня он и на одном артборде спотыкается... :) Но если Вас устраивает, то ок :)
 

creold

Сергей Осокин
Сообщения
27
Реакции
36
Скрипты работают долго (смотря какое железо) потому, что охватывают много вариантов объектов. Говоря о cropulka, там и предварительное сохранение и восстановление статусов всех объектов (залочен, видим — из-за этих функций в большом документе сильно замедляется), и резка растров, мешей, и т.д. У найденного тобой меньше возможностей — от того и быстрый. Первое что бросается в глаза:
1) создает группу, куда помещает все объекты — что плохо, если у пользователя объекты намеренно разложены по разным слоям.
2) Режет только простые векторные объекты (не умеет клиппинг маски, меши, растры)
Если для твоих файлов этого скрипта достаточно, то как-то так по-быстрому по всем артбордам им пройтись можно. Поменять чуть функцию обрезки и циклом, как предлагал Drawer:
JavaScript:
function artboardCrop(idx) {
    app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
    var doc = app.activeDocument;
    selection = null;
    doc.artboards.setActiveArtboardIndex(idx);
    doc.selectObjectsOnActiveArtboard();
    var newGroup = selection[0].layer.groupItems.add();
    h = doc.height;
    w = doc.width;
    process_objects(selection, newGroup, h, w);
    var rc =  doc.artboards[idx].artboardRect;
    var newRect = doc.pathItems.rectangle(rc[1],rc[0],rc[2],-rc[3]);
    newRect.filled = false;
    newRect.stroked = false;
    newRect.move(newGroup, ElementPlacement.PLACEATBEGINNING);
    newGroup.selected = true;
    
    app.executeMenuCommand("Live Pathfinder Crop");
    app.executeMenuCommand("expandStyle");
}
if (app.documents.length > 0) {
    for (var i = 0; i < app.activeDocument.artboards.length; i++) {
        artboardCrop(i);
    }
}
 
Последнее редактирование:
  • Спасибо
Реакции: Drawer

Ant-3

Участник
Топикстартер
Сообщения
57
Реакции
2
Скрипты работают долго (смотря какое железо) потому, что охватывают много вариантов объектов. Говоря о cropulka, там и предварительное сохранение и восстановление статусов всех объектов (залочен, видим — из-за этих функций в большом документе сильно замедляется), и резка растров, мешей, и т.д. У найденного тобой меньше возможностей — от того и быстрый. Первое что бросается в глаза:
1) создает группу, куда помещает все объекты — что плохо, если у пользователя объекты намеренно разложены по разным слоям.
2) Режет только простые векторные объекты (не умеет клиппинг маски, меши, растры)
Если для твоих файлов этого скрипта достаточно, то как-то так по-быстрому по всем артбордам им пройтись можно. Поменять чуть функцию обрезки и циклом, как предлагал Drawer:
JavaScript:
function artboardCrop(idx) {
    app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
    var doc = app.activeDocument;
    selection = null;
    doc.artboards.setActiveArtboardIndex(idx);
    doc.selectObjectsOnActiveArtboard();
    var newGroup = selection[0].layer.groupItems.add();
    h = doc.height;
    w = doc.width;
    process_objects(selection, newGroup, h, w);
    var rc =  doc.artboards[idx].artboardRect;
    var newRect = doc.pathItems.rectangle(rc[1],rc[0],rc[2],-rc[3]);
    newRect.filled = false;
    newRect.stroked = false;
    newRect.move(newGroup, ElementPlacement.PLACEATBEGINNING);
    newGroup.selected = true;
  
    app.executeMenuCommand("Live Pathfinder Crop");
    app.executeMenuCommand("expandStyle");
}
if (app.documents.length > 0) {
    for (var i = 0; i < app.activeDocument.artboards.length; i++) {
        artboardCrop(i);
    }
}

Привет, спасибо большое за помощь! Да, все верно, мне это нужно только для большого количества простых векторных объектов.

Этот отрывок, как я понял, нужно за место этого вставить:
Код:
function ArtboardCrop(){
    app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
    if(app.documents.length  > 0){
        var doc = app.activeDocument;
       
        var newGroup = doc.groupItems.add();    
        h = doc.height;
        w = doc.width;

        process_objects(doc.layers[0].pageItems, newGroup, h, w);
        var activeArtboardIndex = doc.artboards.getActiveArtboardIndex();
        var rc =  doc.artboards[activeArtboardIndex].artboardRect;
        var newRect = doc.pathItems.rectangle(rc[1],rc[0],rc[2],-rc[3]);
        newRect.filled = false;
        newRect.stroked = false;
        newRect.move(newGroup, ElementPlacement.PLACEATBEGINNING);
        newGroup.selected = true;
        //app.executeMenuCommand("selectall");
       
        app.executeMenuCommand("Live Pathfinder Crop");
        app.executeMenuCommand("expandStyle");
    }
}
ArtboardCrop();

Не понял только за место чего или куда именно вот это вставлять:

Код:
for (var a=0; a < app.activeDocument.artboards.length; a++) {
    app.activeDocument.artboards.setActiveArtboardIndex(a);
    ArtboardCrop();
}

Drawer кстати тоже благодарствую за помощь.
 
Последнее редактирование:

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
  • Спасибо
Реакции: Drawer

Ant-3

Участник
Топикстартер
Сообщения
57
Реакции
2
Какой отрывок? creold полный скрипт выложил
хм, просто он у меня с ошибкой запускается, я и подумал, что это отрывок. Вот что пишет:
Error 24: process_objects не является функцией. Line: 10
process_objects(selection, newGroup, h, w);
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
А, точно, добавьте все что выше строки
function ArtboardCrop()
 

creold

Сергей Осокин
Сообщения
27
Реакции
36
Чтобы не путаться, тогда вот целиком скрипт
JavaScript:
function is_on_border(ol, or, ot, ob, h, w) {
  var a = ((ob < 0) && (ot > -h));
  var b = ((or > 0) && (ol < w));
  if ((!a) || (!b)) {
    return 2;
  }
  if (((ol < 0) && (or > 0)) || ((ol < w) && (or > w))) {
    if (a) {
      //на границе
      return 1;
    } else {
      //за границей
      return 2;
    }
  }
  if (((ot > 0) && (ob < 0)) || ((ot > -h) && (ob < -h))) {
    if (b) {
      //на границе
      return 1;
    } else {
      //за границей
      return 2;
    }
  }
  return 0;
}

function process_objects(pageItems, newGroup, h, w) {
  var thisItem;
  for (var i = pageItems.length - 1; i > -1; i--) {
    thisItem = pageItems[i];
    res = is_on_border(thisItem.left, thisItem.left + thisItem.width, thisItem.top, thisItem.top - thisItem.height, h, w);
    if ((res == 1) && (thisItem != newGroup)) {
      thisItem.move(newGroup, ElementPlacement.PLACEATBEGINNING);
    } else if (res == 2) {
      thisItem.remove();
    }
  };
}

function artboardCrop(idx) {
  var doc = app.activeDocument;
  selection = null;
  doc.artboards.setActiveArtboardIndex(idx);
  doc.selectObjectsOnActiveArtboard();

  var newGroup = selection[0].layer.groupItems.add();
  h = doc.height;
  w = doc.width;
  process_objects(selection, newGroup, h, w);

  var rc = doc.artboards[idx].artboardRect;
  var newRect = doc.pathItems.rectangle(rc[1], rc[0], rc[2], -rc[3]);
  newRect.filled = false;
  newRect.stroked = false;
  newRect.move(newGroup, ElementPlacement.PLACEATBEGINNING);

  newGroup.selected = true;
  app.executeMenuCommand("Live Pathfinder Crop");
  app.executeMenuCommand("expandStyle");
  if (selection[0].typename == "GroupItem" && !selection[0].pageItems.length) {
    selection[0].remove();
  }
}

if (app.documents.length > 0) {
  var docCoord = app.coordinateSystem;
  app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
  for (var i = 0; i < app.activeDocument.artboards.length; i++) {
    artboardCrop(i);
  }
  selection = null;
  app.coordinateSystem = docCoord;
}
 
Последнее редактирование:
  • Спасибо
Реакции: Drawer и ITIT

Ant-3

Участник
Топикстартер
Сообщения
57
Реакции
2
Чтобы не путаться, тогда вот целиком скрипт
JavaScript:
function is_on_border(ol, or, ot, ob, h, w) {
  var a = ((ob < 0) && (ot > -h));
  var b = ((or > 0) && (ol < w));
  if ((!a) || (!b)) {
    return 2;
  }
  if (((ol < 0) && (or > 0)) || ((ol < w) && (or > w))) {
    if (a) {
      //на границе
      return 1;
    } else {
      //за границей
      return 2;
    }
  }
  if (((ot > 0) && (ob < 0)) || ((ot > -h) && (ob < -h))) {
    if (b) {
      //на границе
      return 1;
    } else {
      //за границей
      return 2;
    }
  }
  return 0;
}

function process_objects(pageItems, newGroup, h, w) {
  var thisItem;
  for (var i = pageItems.length - 1; i > -1; i--) {
    thisItem = pageItems[i];
    res = is_on_border(thisItem.left, thisItem.left + thisItem.width, thisItem.top, thisItem.top - thisItem.height, h, w);
    if ((res == 1) && (thisItem != newGroup)) {
      thisItem.move(newGroup, ElementPlacement.PLACEATBEGINNING);
    } else if (res == 2) {
      thisItem.remove();
    }
  };
}

function artboardCrop(idx) {
  var doc = app.activeDocument;
  selection = null;
  doc.artboards.setActiveArtboardIndex(idx);
  doc.selectObjectsOnActiveArtboard();

  var newGroup = selection[0].layer.groupItems.add();
  h = doc.height;
  w = doc.width;
  process_objects(selection, newGroup, h, w);

  var rc = doc.artboards[idx].artboardRect;
  var newRect = doc.pathItems.rectangle(rc[1], rc[0], rc[2], -rc[3]);
  newRect.filled = false;
  newRect.stroked = false;
  newRect.move(newGroup, ElementPlacement.PLACEATBEGINNING);

  newGroup.selected = true;
  app.executeMenuCommand("Live Pathfinder Crop");
  app.executeMenuCommand("expandStyle");
  if (selection[0].typename == "GroupItem" && !selection[0].pageItems.length) {
    selection[0].remove();
  }
}

if (app.documents.length > 0) {
  var docCoord = app.coordinateSystem;
  app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
  for (var i = 0; i < app.activeDocument.artboards.length; i++) {
    artboardCrop(i);
  }
  selection = null;
  app.coordinateSystem = docCoord;
}
Работает вообще классно, благодарствую еще раз помощь!
 

ITIT

15 лет на форуме
Сообщения
500
Реакции
194
Работает действительно классно,НО есть и ,,ложка дёгтя,,.
При повторном запуске скрипта на ,,обрезанных,, только что артбордах удаляет все обьекты оставшиеся на них.
Это мелочи жизни если быть внимательным и всегда есть Ctrl+Z
 

creold

Сергей Осокин
Сообщения
27
Реакции
36
Понятно. Чтобы это пофиксить, надо добавить сброс селекшена со всех объектов на артборде, перед строкой которая выбирает собранную группу "newGroup" для кропа. Иначе накладывается, что в выделении может быть и новая группа, и просто какая-то старая группа объектов на этом артборде. И тогда эффект кропа ко всем группам применится, что не нужно.
JavaScript:
selection = null;
newGroup.selected = true;
 
Последнее редактирование:
  • Спасибо
Реакции: ITIT