[AI CC-CC2022] Скрипт изменения размера объекта

Грей Нортон

Участник
Топикстартер
Сообщения
10
Реакции
1
Добрый вечер, ребят. В вопросе скриптинга в люстре я совсем новенький. На просторах интернета нашел себе скприт меняющий размер высоты всех выбранных объектов, по высоте самого нижнего. Возможно ли сделать скрипт, чтобы объект мог вписаться в определенный квадрат? То есть в зависимости от ширины или высоты, он вписывался бы в квадрат.
Примерно логику поведения скрипта понимаю. Выбрать объект, дать указание сравнить ширину и высоту. Если больше ширина, то дать ей определенное значение (его можно по шаблону или по меню), если же высота больше, то дать это значение ей. Буду очень благодарен ответам. Хотелось бы много еще узнать.
 
Комментарий модератора:
5. На форуме запрещается:
5.16 Использовать сленговые и искаженные названия программ.

На просторах интернета нашел себе скприт меняющий размер высоты всех выбранных объектов
Лучше сразу ссылку на него дать, лично мне проще чуток подправить под Ваши нужды скрипт, чем писать с нуля.
Речь об этом скрипте?
UPD: точно не о нём, ну да ладно.

Даже если не о нём, то всё равно из него можно получить нужное.
Вот этот вариант попробуйте:
JavaScript:
/////////////////////////////////////////////////////////////////
//  Set All The Things v.1.2 -- CS,CS2,CS3,CS4
//>=--------------------------------------
// Wanna Batch Transform objects?  Illustrator has built in tools to resize each selected item,
// but only by percentage, not by hard values. I made this script because I could find no
// native way to set the width of all selected objects to 100px at once.
//
// This script can accept multiple parameters at once.
// To change, for instance, both width and height at the same time,
// at the 'attributes' prompt, enter <b>width,height</b>
// then at the 'values' prompt, enter a comma separated value list like <b>20,30</b>
//  If a single value is passed for 'values', that value will be applied to all chosen properties.
//
// Common legal parameter names include, but are not limited to: <b>width,height,top,left</b>.
// Install and use <a href='http://wundes.com/JS4AI/#explore.js'>explore.js</a> on an object to see what other properties can be set.
//
// Update: Based on feedback from user Jode, You are now given the option to transform objects from center.
// You can now also use whatever standard units you like and the script will convert them into pixels.
//  e.g., you can enter "30mm" or "12in" and the script will know what you mean.
//  v1.2 adds decimal support and explicit 'px' and 'pt' units to the regex. (thanks to Cristofer Cruz for noticing the bug)
//>=--------------------------------------
// JS code (c) copyright: John Wundes ( john@wundes.com ) www.wundes.com
//copyright full text here:  http://www.wundes.com/js4ai/copyright.txt
//////////////////////////////////////////////////////////////////
var centerObjects= false;
function main(){
    var item,center_point;
    var toPixels=function(v){
  
    var units={
                        'in':72,
                        'mm':2.8346455078125,
                           'px':1,
                           'pt':1,
            },re = /(\d*[.]*\d+)(mm|in|ft|cm|px|pt)/i,m,u,rep;
        //derivitave
        units['cm'] = units['mm']*10;
        units['ft'] = units['in']*12;

        while(m=v.match(re)){
            u = m[2].toLowerCase();
            if (units[u]){
                rep = (m[1]*units[u]);
                v = v.replace(re,rep);
            }
        }
        return v;
    }

    var trace = function (m){alert(m)};
    if(activeDocument == null){trace("No open document found. Please open a document.");return;}
    if(activeDocument.selection.length == 0){trace("Nothing selected. Please select one or more items.");return;}
    var i = "width,height";
    var v = prompt("What value do you want to assign?","100");
    if (v === null ){return false;}
    centerObjects=confirm("Transform Objects around center?");
    v=toPixels(v);
    // here's where we walk through all objects.
    var assign = function (i,v){
        for (var x=0 ; x < activeDocument.selection.length ; x++){
      
                item = activeDocument.selection[x];
                //get top and left width and height values
                center_point = [item.top-(item.height/2),item.left+(item.width/2)];
              
              if (item.width >= item.height) {
                    item.height = item.height * eval(v) / item.width;
                    item.width = eval(v);   
              } else {             
                    item.width = item.width * eval(v) / item.height;
                    item.height = eval(v); 
                  }
      
          
            if(centerObjects){
                item.top = center_point[0] + (item.height/2);
                item.left = center_point[1] - (item.width/2);
            }
        };
    }
    if(  i.indexOf(',') !== -1){  i =  i.split(',');}
    //split if a list, but not if function is found.
    if( v.indexOf(',') !== -1){ v = v.split(',');}
  
    if(typeof i !== "string")
    {
        for ( var len=i.length,c=0;c<len;c++)
        {
            assign(i[c],typeof v !== 'string' ? v[c] : v);
        }
    } else
    {
        assign(i,v);
    }
    redraw();
    return true;
  
}
main();
 
Последнее редактирование:
Здравствуйте. Прошу прощение за допущение ошибок в сообщении выше. Действительно все так и есть. Этот скрипт идеально подходит. Только вот у меня вопрос. И касается он в целом написания скриптов. Но в примере я хотел бы привести опять таки этот скрипт и второй, который создан, чтобы располагать объекты по определенному контуру (пути). Так вот, оба скрипта (тот, что выше прислан вами и тот, что отправлю в следующем сообщении) показывают меню. Вопрос мой заключается в том, как можно избавиться от меню?
Просто я лишь записываю операции (actions) и хотел бы их туда "вставить", но постоянное всплывающее окошко, будет требовать внимание каждый файл. Я понимаю, что написать скрипт будет легче, но пока что оптимальный вариант для меня только операции.
 
А вот и второй скрипт:

Код:
// distributeOnThePath.jsx

function main(){
   
    var conf = {
        invert: false,
        extract_groups: false
    }
    
    if(documents.length < 1) return;
    
    var sels = activeDocument.selection;
    if( sels.length < 2 ) return;
        
    var target_path = sels[0];
    if( target_path.typename != "PathItem" ){
        alert("The foreground object is not a path.\r"
              + "A path to distribution must be at the foreground in the selection.");
        return;
    }

    var previewed = false;
    
    var clearPreview = function(){
        if(previewed){
            undo();
            previewed = false;
        }
    }
    
    var drawPreview = function(){
        try{
            distributreOnThePath( sels, conf );
            previewed = true;
        }catch(e){
            alert(e);
        }
    }
    
    var win = new Window("dialog", "distributeOnThePath");
    win.alignChildren = "fill";
    
    win.invertChk = win.add("checkbox", undefined, "invert path direction");
    win.ExtractChk = win.add("checkbox", undefined, "extract groups");
    win.previewChk = win.add("checkbox", undefined, "preview");

    win.btnGroup = win.add("group", undefined );
    win.btnGroup.alignment = "center";
    win.btnGroup.okBtn = win.btnGroup.add("button", undefined, "OK");
    win.btnGroup.cancelBtn = win.btnGroup.add("button", undefined, "Cancel");

    var getValues = function(){
        conf.invert = win.invertChk.value;
        conf.extract_groups = win.ExtractChk.value;
    }

    var processPreview = function( is_preview ){
        if( ! is_preview || win.previewChk.value){
            win.enabled = false;
            getValues();
            clearPreview();
            drawPreview();
            if( is_preview ) redraw();
            win.enabled = true;
        }
    }
    
    win.previewChk.onClick = function(){
        if( win.previewChk.value ){
            processPreview( true );
        } else {
            if(previewed){
                clearPreview();
                redraw();
            }
        }
    }
    win.invertChk.onClick = function(){
        win.previewChk.onClick();
    }
    win.ExtractChk.onClick = function(){
        win.previewChk.onClick();
    }
    
    win.btnGroup.okBtn.onClick = function(){
        processPreview( false );
        win.close();
    }
    
    win.btnGroup.cancelBtn.onClick = function(){
        win.enabled = false;
        clearPreview();
        win.enabled = true;
        win.close();
    }
    win.show();
}

function distributreOnThePath( sels, conf ){
  
    var target_path = sels[0];

    var objs;
    if( conf.extract_groups ){
        objs = extractGroup( sels.slice(1) );
    } else {
        objs = sels.slice(1);
    }

    var sortfunc = conf.invert
        ? function(a,b){ return b.left - a.left }
        : function(a,b){ return a.left - b.left };
      
   
    objs = objs.sort( sortfunc );

  
    var d = target_path.length / (objs.length - (target_path.closed ? 0 : 1));
    if( d == 0 ) return;

  
    var points = getPointsForDistribution( target_path, d );

   
    if( points.length < objs.length ){
        points.push( new Point().setr(
            target_path.pathPoints[ target_path.pathPoints.length - 1 ].anchor));
    }

   
    var i;
    for(i = 0; i < points.length; i++){
        moveToPoint( objs[i], getCenter( objs[i] ), points[i].toArray() );
    }

    // brings objects above of the target_path
    for(i = 1; i < sels.length; i++){
        sels[i].move( target_path, ElementPlacement.PLACEBEFORE );
    }

    // sometimes the selection state changes after execution.
    // I don't know why it happens. fixes it anyway.
    activeDocument.selection = sels;
}

// -----------------------------------------------
function moveToPoint(obj, p1, p2){
    obj.translate( p2[0] - p1[0], p2[1] - p1[1],
                   true, true, true, true);
}

// -----------------------------------------------
function getCenter(p){
    return [p.left + p.width / 2,
            p.top - p.height / 2];
}

// -----------------------------------------------
function getPointsForDistribution( path, d ){ // path:PathItem, d:desired length
    var p = path.pathPoints;
    var spec = { pnts:[], d:d, ini_d:0 };
    
    for(var i=0; i < p.length; i++){
        var next_idx = parseIdx(p, i + 1);
        if( next_idx < 0 ) break;

        var cv = new Curve(path, i, next_idx);

        cv.getEquallySpacedPoints( spec );
    }
    return spec.pnts;
}

// -----------------------------------------------
var Point = function(){
    this.x = 0;
    this.y = 0;
}
Point.prototype = {
    set : function(x, y){
        this.x = x;
        this.y = y;
        return this;
    },
    setr : function(xy){ // set with an array
        this.x = xy[0];
        this.y = xy[1];
        return this;
    },
    setp : function(p){ // set with a Point
        this.x = p.x;
        this.y = p.y;
        return this;
    },
    addp : function(p){
        return new Point().set( this.x + p.x, this.y + p.y );
    },
    subp : function(p){
        return new Point().set( this.x - p.x, this.y - p.y );
    },
    mul : function(m){
        return new Point().set( this.x * m, this.y * m );
    },
    rotate : function(rad){
        var s = Math.sin(rad);
        var c = Math.cos(rad);
        return new Point().set( this.x * c - this.y * s, this.x * s + this.y * c );
    },
    getAngle : function(){
        return Math.atan2( this.y, this.x ); // radian
    },
    normalize : function(){
        var d = Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
        var p = new Point();
        if( d == 0 ){
            p.set(0,0);
        } else {
            p.set(this.x / d, this.y / d);
        }
        return p;
    },
    toArray : function(){
        return [this.x, this.y];
    }
}

// -----------------------------------------------
var Curve = function(path, idx1, idx2){
    var pts = path.pathPoints;
    
    this.p1 = new Point().setr(pts[idx1].anchor);
    this.rdir = new Point().setr(pts[idx1].rightDirection);
    this.ldir = new Point().setr(pts[idx2].leftDirection);
    this.p2 = new Point().setr(pts[idx2].anchor);
    
    this.q = [this.p1, this.rdir, this.ldir, this.p2];
    this.params = null;
    this.length = null;
}
Curve.prototype = {
    bezier : function(t){
        var u = 1 - t;
        return new Point().set(
            u*u*u * this.p1.x + 3*u*t*(u* this.rdir.x + t* this.ldir.x) + t*t*t * this.p2.x,
            u*u*u * this.p1.y + 3*u*t*(u* this.rdir.y + t* this.ldir.y) + t*t*t * this.p2.y);
    },
    setParams : function(){
        var m = [this.p2.x - this.p1.x + 3 * (this.rdir.x - this.ldir.x),
                 this.p1.x - 2 * this.rdir.x + this.ldir.x,
                 this.rdir.x - this.p1.x];
        var n = [this.p2.y - this.p1.y + 3 * (this.rdir.y - this.ldir.y),
                 this.p1.y - 2 * this.rdir.y + this.ldir.y,
                 this.rdir.y - this.p1.y];
        
        this.params = [ m[0] * m[0] + n[0] * n[0],
                        4 * (m[0] * m[1] + n[0] * n[1]),
                        2 * ((m[0] * m[2] + n[0] * n[2]) + 2 * (m[1] * m[1] + n[1] * n[1])),
                        4 * (m[1] * m[2] + n[1] * n[2]),
                        m[2] * m[2] + n[2] * n[2]];
    },
    getLength : function(t){
        //if( !this.params ) this.setParams();
        var k = this.params;
    
        var h = t / 128;
        var hh = h * 2;
        
        var fc = function(t, k){
            return Math.sqrt(t * (t * (t * (t * k[0] + k[1]) + k[2]) + k[3]) + k[4]) || 0 };
        
        var total = (fc(0, k) - fc(t, k)) / 2;
        
        for(var i = h; i < t; i += hh){
            total += 2 * fc(i, k) + fc(i + h, k);
        }
        
        return total * hh;
    },
    getTforLength : function(len){
        //if( !this.params ) this.setParams();
        var k = this.params;

        //if( !this.length) this.length = this.getLength(1);
        if(len <= 0){
            return 0;
        } else if(len > this.length){
            return -1;
        }
        
        var t, d;
        var t0 = 0;
        var t1 = 1;
        var torelance = 0.001;
        
        for(var h = 1; h < 30; h++){
            t = t0 + (t1 - t0) / 2;
            d = len - this.getLength(t);
            
            if(Math.abs(d) < torelance) break;
            else if(d < 0) t1 = t;
            else t0 = t;
        }
        
        return Math.min(1, t);
    },
    getEquallySpacedPoints : function( spec ){
        // spec = { pnts:pnts, d:d, ini_d:0 }
        if( !this.params ) this.setParams();
        if( !this.length ) this.length = this.getLength(1);

        var total_d = spec.ini_d;
        var t;
        
        if( total_d < this.length ){
            while( 1 ){
                t = this.getTforLength( total_d );
                if( t < 0 ) break;
                spec.pnts.push( this.bezier(t) );
                total_d += spec.d;
            }
            spec.ini_d = total_d - this.length;
        } else {
            spec.ini_d -= this.length;
        }
    }
}

// ----------------------------------------------
// return the index of pathpoint. when the argument is out of bounds,
// fixes it if the path is closed (ex. next of last index is 0),
// or return -1 if the path is not closed.
function parseIdx(p, n){ // PathPoints, number for index
  var len = p.length;
  if( p.parent.closed ){
    return n >= 0 ? n % len : len - Math.abs(n % len);
  } else {
    return (n < 0 || n > len - 1) ? -1 : n;
  }
}
// ----------------------------------------------
function extractGroup( s, r ){
    if( r == undefined ) r = [];
    
    for( var i = 0; i < s.length; i++){
        if( s[i].typename == "GroupItem" ){
            extractGroup( s[i].pageItems, r );
        } else {
            r.push( s[i] );
        }
    }
    
    return r;
}
main();
 
показывают меню. Вопрос мой заключается в том, как можно избавиться от меню?
Где?
В том что Анюта прислала из всех элементов интерфейса только prompt и confirm - уберите их и скрипт будет работать абсолютно молча
 
А вот и второй скрипт:
Тут диалоговое окно присутствует однако обратите внимание, код висящий на кнопке Ok выглядит следующим образом
JavaScript:
win.btnGroup.okBtn.onClick = function(){
        processPreview( false );
        win.close();
    }
Первую строку и надо вызывать, разумеется, установив перед этим все настройки программно
 
Прочитав ваши ответы, еще больше почувствовал себя человеком, далеким от всего этого)
Что значит "установив перед этим все настройки программно"?
 
у вас в диалоге установки человек задает, вы хотите диалог убрать, установки откуда-то должны взяться все равно, логично?
 
JavaScript:
conf.invert = win.invertChk.value;
conf.extract_groups = win.ExtractChk.value;
Ну вот например
Эти параметры (сходу не пойму их физическую природу) явно выбираются из диалогового окна
А вам придется их жестко устанавливать безо всякого диалога прямо непосредственно из кода
 
JavaScript:
conf.invert = win.invertChk.value;
conf.extract_groups = win.ExtractChk.value;
Ну вот например
Эти параметры (сходу не пойму их физическую природу) явно выбираются из диалогового окна
А вам придется их жестко устанавливать безо всякого диалога прямо непосредственно из кода

Да-да. Все верно. Я так и понял. По сути в этом и заключался мой вопрос. Я не разбираюсь в конкретных командах. Там в меню 3 пункта всего для выставления галочек. Которые говорят о том, разгруппировать ли объекты, изменить направление и предосмотр. И по сути я могу подготовить файлы для того,чтобы мне не было необходимо делать разгруппировку. Я пытался уже вручную что-то там менять, где он ссылается в коде на результаты выбора в меню. Но это не давало результатов. Ибо я, скорее всего, делал абсолютно неправильно. И отсюда вопрос. Как я могу это сделать?
 
у вас в диалоге установки человек задает, вы хотите диалог убрать, установки откуда-то должны взяться все равно, логично?

Понимаю, что логично. Простите, если не так выразился, но вопрос в том, что и куда вписать, чтобы оттуда он брал эту информацию. Я имею ввиду стандартную, без вариаций.
 
для начала надо определиться со значениями )
 
для начала надо определиться со значениями )

Не, ну значения функции стандартные. То есть не выбрано ничего. Как я уже выше описал, мне в принципе нужно, будто я нажал на эту кнопку "OK" без поставленных галочек.:)
 
Тогда везде false разумеется
 
Тогда везде false разумеется

Самое забавное, что именно так я и сделал. Вот только он в конечном итоге ничего не заработал совсем. Я конечно прошу многого, но не могли бы вы взглянуть, где именно мне ввести эти данные, чтобы получился нужный мне результат?
 
а вы покажите свой код с этими изменениями
 
Вместо win.show поставить processPreview(false);
Ну а перед этим эти две инициализации тоже в false
Написал бы сам полностью но пишу с утюга
 
а вы покажите свой код с этими изменениями

Боюсь показывать то и нечего)
Ибо, повторюсь, я совсем чайник в этом и скорее это было похоже на поиск знакомых слов и их удаление. А там где было написано "win" и ссылки на них, я тупо после "равно" ставил "False")
 
Вместо win.show поставить processPreview(false);
Ну а перед этим эти две инициализации тоже в false
Написал бы сам полностью но пишу с утюга

Прекрасно. Все заработало именно так, как и хотелось. Спасибо большое. Очень было приятно с вами всеми обсудить эту тему. Надеюсь в будущем мне удастся справляться с подобными задачами и самому. Однако реальность сурова и скорее всего я вернусь за советами, если конечно вы не будете против.
 
  • Спасибо
Реакции: ~RA~