Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Select object based on its opacity and change opacity to set value.

Participant ,
Aug 06, 2018 Aug 06, 2018

I am trying to create some javascript code but cannot find any references online relating to this specific instance.

What i am attempting to do is have the script find an object(s) based on its opacity in the transparency window and then if it is 80% i want to change it to be 60%.

This would be done for every opacity value from 99% to 1% and then changing it to a specific value.

Any thoughts on where to start?

Thanks!

TOPICS
Scripting
3.6K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Aug 06, 2018 Aug 06, 2018

function test()

{

    var docRef = app.activeDocument;

    var layers = docRef.layers;

    var opacityRelationships = {

        "80": 60

        //put in the rest of your relationships here

        //left side is the current opacity of an object

        //right side is what you want to change it to

    }

    function updateOpacity(item)

    {

        var curOpacity = Math.floor(item.opacity).toString();

        item.opacity = opacityRelationships[curOpacity];

    }

    for(var x=0,len = layers.length;x<len;x++

...
Translate
Adobe
Participant ,
Aug 06, 2018 Aug 06, 2018

After looking further into this code it appears all you have to do is add a select all in front of this and run the code. Duplicating the code provided for each instance i need worked perfectly.


THANK YOU!!

EDIT* Also for reference my final code looks like this:

var doc = app.activeDocument;

if (app.documents.length>0)

doc.selectObjectsOnActiveArtboard();

function eighty() { 

  var o1 = 80; 

  var o2 = 60 

    if (!selection.length) return; 

    var sel = selection; 

      function changeOpacity(items) { 

          for(var n = 0; n < items.length; n++) { 

            if (Math.round(items.opacity) == o1) { 

              items.opacity = o2; 

            } 

          } 

      } 

      changeOpacity(sel); 

if (app.documents.length) {eighty();} 

function seventy() { 

  var o1 = 70; 

  var o2 = 30 

    if (!selection.length) return; 

    var sel = selection; 

      function changeOpacity(items) { 

          for(var n = 0; n < items.length; n++) { 

            if (Math.round(items.opacity) == o1) { 

              items.opacity = o2; 

            } 

          } 

      } 

      changeOpacity(sel); 

if (app.documents.length) {seventy();} 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Aug 15, 2018 Aug 15, 2018

Finally finished the code to select and modify both solid fill colors and gradient stops transparency from one value to another via an array.

thank you williamadowling​ for helping me get started!

For reference, in case this happens for anyone else, my final code is below: (could probably still be simplified but its working as intended)

function test() {

    var docRef = app.activeDocument;

    var layers = docRef.layers;

    var paths = docRef.pathItems;

    var items = docRef.selection;

    var opacityRelationships = {

     "100": 100, "99":70,

       // rest of relationships go here e.g.

    }

   

    for (var i=0,len = paths.length;i<len;i++) {

        if (paths.fillColor == '[GradientColor]') {

    for (var z = 0; z < paths.fillColor.gradient.gradientStops.length; z++) {

            function updateOpacityGradient(item){

                var curOpacity = Math.floor(item.opacity);

        item.opacity = opacityRelationships[curOpacity];

    }

updateOpacityGradient(paths.fillColor.gradient.gradientStops);

  }

}

   }

  

    for (var j=0,len = paths.length;j<len;j++) {

    for (var r=0,len = layers.length;r<len;r++){

if (paths.fillColor == '[SpotColor]') {

   for (var y=0,yLen = layers.pageItems.length;y<yLen;y++) {

    function updateOpacitySpot(item2){

                var curOpacity = Math.floor(item2.opacity).toString();

        item2.opacity = opacityRelationships[curOpacity];

    }

updateOpacitySpot(layers.pageItems);

   }

        }

   }

   }

}test();

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 15, 2018 Aug 15, 2018

looking good. if it's working, awesome. but if you're interested in some simplifications or improvements, i'll share them here, unsolicited, and you can do with that knowledge what you will. Hopefully it may help others as well.

This code looks a LOT like code i wrote when i was at your stage of coding. But i ran into some things along the way that perhaps you may be able to avoid without learning the hard way like i did.

You're on the right track by thinking "this code could be simplified". This is almost always true. However, don't get caught in the trap of "i need to make this code as simplified as possible". There is a threshold beyond which further simplifying code will actually make it less intuitive, harder to debug and harder for another coder to read. A good goal to strive for is that your code is highly readable (for me, this means that your functions and variables are named in a very clear and unambiguous way. for example, don't use a variable name like "io" to store the opacity of a given item.. use "itemOpacity" so your variables don't need to be decoded. this is probably a poor example, but you get the point.), while also minimizing inefficiencies.

The first part of that goal looks great in your code. your variable names and functions are clearly named. The second part is where we are going to look at some improvements.

The very first thing that stood out to me when i looked at your code here, is that your function declarations occur inside of for loops. Inside nested for loops at that. This means that every time you meet the conditions of running one of these functions, you are re-declaring the function. This is inherently inefficient since the function itself is not changing. When you write a loop, ask yourself "is there anything inside the body of this loop that never changes?". If the answer is yes, that portion should not be inside the loop. Your function declarations should exist in the top-level scope of the test() function. For our purposes, I will refer to this scope as "script-global" because this scope encompasses everything we need for this script.

So, now that we've identified that the function declarations remain static throughout the execution of the script, we can pull those out to script-global scope. This will help eliminate clutter, make your code easier to read, and improve efficiency.

Another efficiency improvement could be found by taking a step back and really analyzing your "j" for loop. In this loop, you're beginning by looping every pageItem in the document (special note.. be careful any time you do this because at the document scope, pathItems is an array of every single pathItem in that document, including pathItems that are nested inside groups or compound paths. It's generally a good idea to identify a more narrow scope to process as this will help prevent extremely long execution times on larger files). Then for each pathItem in the document, you are looping every layer in the document. and for every layer, you're performing a check on the same pathItem. So if you had 10 layers in your document, you'd be checking the same pathItem 10 times to see whether it is a spot color. This is inherently inefficient. It's generally a good idea to work top down when traversing the DOM. the "larger" elements should come first in your nesting order, otherwise you risk redundancy. In this case, since your second loop (the one with the variable "r") has no relationship to it's parent loop, it's gotta go. As a fun experiment, you can get a more comprehensive view of the inefficiency i'm talking about by adding a console log message to the beginning of each of these loops. Just add something simple like $.writeln("j = " + j);Then run the script again and watch the console. I think you'll find that even in a relatively small document, there's a lot more happening than you think.

the TLDR of the above paragraph is as follows.. You start by looping every path item. then you loop the layers in the document. then you loop the pageItems of each layer. Since you're looping the pageItems of the layers, you should remove either the "j" loop, or the "y" loop.

Next, let's look at your loop structure. Surely many people will have their own opinions about this, but my opinion is that if you find yourself nesting two for loops directly inside one another, it's probably a good opportunity to create a function instead. Otherwise your loop variables can get confusing. This is an issue of readability as well as an issue of ease of debugging. I couldn't tell you how much time i spent debugging some code because i used the wrong loop variable somewhere inside a nested for loop.

I feel like i'm rambling too much here, so I'll just post what i would consider to be the cleaner and more efficient code. Then you can ask questions if it doesn't seem to make sense.

function test()

{

    var docRef = app.activeDocument;

    var layers = docRef.layers;

    var paths = docRef.pathItems;

    //this doesn't change throughout this script,

    //so let's declare it at the script-global scope.

    var pathLen = paths.length;

    var opacityRelationships = {

        "100": 100,

        "99": 70,

        // rest of relationships go here e.g. 

    }

    function updateOpacityGradient(item)

    {

        var stops = item.fillColor.gradient.gradientStops;

        var curOpacity; //it's generally agreed that when possible, variables should be declared outside of loops

        for (var x = 0, len = stops.length; x < len; x++)

        {

            curOpacity = Math.floor(stops.opacity);

            stops.opacity = opacityRelationships[curOpacity];

        }

    }

    function updateOpacitySpot(item)

    {

        var curOpacity = Math.floor(item.opacity).toString();

        item.opacity = opacityRelationships[curOpacity];

    }

    //first let's process the gradient stops

    for (var i = 0; i < pathLen; i++)

    {

        //in this first condition, you should always protect yourself against

        //runtime errors by first checking that a given path is 'filled' before

        //you try to access it's fillColor.

        if (paths.filled && paths.fillColor == "[GradientColor]")

        {

            updateOpacityGradient(paths);

        }

    }

    //now let's look at the opacity of non-gradient pathItems

    for (var i = 0; i < pathLen; i++)

    {

        //again, make sure it's filled before you check the fillColor

        if (paths.filled & paths.fillColor == "[SpotColor]")

        {

            updateOpacitySpot(paths);

        }

    }

}

test();

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Aug 15, 2018 Aug 15, 2018

You have been unbelievably helpful. I cannot thank you enough for your time and dedication you have for this forum. After playing around with this script for the past week I've actually learned a lot more than i thought from trial and error and will be definitely following your advice above moving forward. A lot of that made way more sense seeing it written out rather than just staring at the code and trying to see "it".

Thank you so much again!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 15, 2018 Aug 15, 2018
LATEST

anytime. i owe my livelihood to other helpful folks on this forum. paying it forward to the "next generation", as it were, is the best way i know how to pay back my debt. 😃

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines