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

Adding stops to a gradient based on bounding box

Explorer ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

So, I'm not a script writer but am able to build what I need from various sources. This time I tried to have openai write a script for me and I have a feeling this is close based on my middling knowledge of Illustrator's JS.

 

Essentially what I'd like is to add gradient stops to an object where the gradient starts and ends way beyond the object. I want to add a stop at the left and right bounding box edges. This works easily manually by just clicking on the gradient band, but I have dozens that need to be updated.


This is what i was able to get openai to output from a couple of revised inputs, it runs up to CREATE NEW GRADIENT STOPS AT THE BOX EDGES. Any thoughts would be greatly appreciated.

 

// Get a reference to the current document
var doc = app.activeDocument;

// Iterate through all selected objects
var selectedItems = doc.selection;
for (var i = 0; i < selectedItems.length; i++) {
  var item = selectedItems[i];

  // Check if the item is a path or compound path
  if (item.typename === "PathItem" || item.typename === "CompoundPathItem") {
    // Check if the item has a fill gradient and it is CMYK
    if (item.fillColor && item.fillColor.gradient && item.fillColor.gradient instanceof Gradient && item.fillColor.gradient.type === GradientType.LINEAR && item.fillColor.gradient.gradientStops.length > 1 && item.fillColor.gradient.gradientStops[0].color instanceof CMYKColor) {
      var gradient = item.fillColor.gradient;

      // Get the bounding box of the item
      var bounds = item.geometricBounds;

      // Calculate the coordinates of the bounding box edges
      var leftEdge = bounds[0];
      var topEdge = bounds[1];
      var rightEdge = bounds[2];
      var bottomEdge = bounds[3];

      // Create new gradient stops at the bounding box edges
      var colorStopLeft = new GradientStop();
      colorStopLeft.color = new CMYKColor();
      colorStopLeft.color.cyan = gradient.gradientStops[0].color.cyan;
      colorStopLeft.color.magenta = gradient.gradientStops[0].color.magenta;
      colorStopLeft.color.yellow = gradient.gradientStops[0].color.yellow;
      colorStopLeft.color.black = gradient.gradientStops[0].color.black;
      colorStopLeft.opacity = gradient.gradientStops[0].opacity;
      colorStopLeft.location = 0;

      var colorStopRight = new GradientStop();
      colorStopRight.color = new CMYKColor();
      colorStopRight.color.cyan = gradient.gradientStops[gradient.gradientStops.length - 1].color.cyan;
      colorStopRight.color.magenta = gradient.gradientStops[gradient.gradientStops.length - 1].color.magenta;
      colorStopRight.color.yellow = gradient.gradientStops[gradient.gradientStops.length - 1].color.yellow;
      colorStopRight.color.black = gradient.gradientStops[gradient.gradientStops.length - 1].color.black;
      colorStopRight.opacity = gradient.gradientStops[gradient.gradientStops.length - 1].opacity;
      colorStopRight.location = 100;

      // Add the new gradient stops to the existing gradient
      gradient.gradientStops = [colorStopLeft].concat(gradient.gradientStops).concat(colorStopRight);

      // Apply the modified gradient to the item's fill
      item.fillColor = gradient;
    }
  }
}

 

TOPICS
Scripting

Views

1.0K

Translate

Translate

Report

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

Enthusiast , Jun 29, 2023 Jun 29, 2023

Knowing the color of the start and end gradient stops and the distance to the new stops, we can use linear interpolation to calculate the color at those points. This is what Adobe itself does with rounding. wrote about this "Get SpotColor tint color".

addGradientStops.gif

 

 

main();

function main() {
  var item = app.selection[0]; // select item

  var origin = item.fillColor.origin[0];
  var length = item.fillColor.length;
  var bounds = item.geometricBounds;
  var bound1 = bounds[0];
  var bound2 = bounds[0] + (b
...

Votes

Translate

Translate
Adobe
Guide ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

A gradientColor has an origin property and a length property, which should allow you to control where a gradient annotator starts and ends.  But the last time I tried them, neither of them worked.  So you may be out of luck. 

Votes

Translate

Translate

Report

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
Explorer ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

I dont want to change where it starts or ends (at least not as part of this script) just add a point along the gradient so I can get the color value at the edge of the object bounds.

Votes

Translate

Translate

Report

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
Guide ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

Then I'm not sure what you are trying to do.  When you create a gradient with a script, start and end stops are automatically created.  Do you want to add additional stops in between? 

Votes

Translate

Translate

Report

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
Explorer ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

So the gradient and object already exist, so the script doesn't need to create the gradient. Yes, I do want to add stops in between, but not at chosen or specific percentages. I wanted to know if I could script it to determine bounding box of object and add a two new stops at points equivelent to that object's bounding box. See picture.Screen Shot 2023-06-29 at 2.59.05 PM.png

Votes

Translate

Translate

Report

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
Guide ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

// select item
var item = app.selection[0];
var origin = item.fillColor.origin[0];
var length = item.fillColor.length;
var bounds = item.geometricBounds;
var bound1 = bounds[0];
var bound2 = bounds[0] + (bounds[2] - bounds[0]);
var gradient1 = item.fillColor.gradient;
stop1 = gradient1.gradientStops.add();
stop1.rampPoint = (bound1 - origin) / length * 100;
stop2 = gradient1.gradientStops.add();
stop2.rampPoint = (bound2 - origin) / length * 100;

Votes

Translate

Translate

Report

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
Explorer ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

This is fantastic and so close, thank you for taking the time to help. I have one last question, the script as shared adds the stop exactly where I expect them, but the fill isn't the value that exists at that point, its adding a stop with the end point color. Is this possible?Screen Shot 2023-06-29 at 4.00.54 PM.png

Votes

Translate

Translate

Report

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
Enthusiast ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

Knowing the color of the start and end gradient stops and the distance to the new stops, we can use linear interpolation to calculate the color at those points. This is what Adobe itself does with rounding. wrote about this "Get SpotColor tint color".

addGradientStops.gif

 

 

main();

function main() {
  var item = app.selection[0]; // select item

  var origin = item.fillColor.origin[0];
  var length = item.fillColor.length;
  var bounds = item.geometricBounds;
  var bound1 = bounds[0];
  var bound2 = bounds[0] + (bounds[2] - bounds[0]);

  var gradient1 = item.fillColor.gradient;
  var start = gradient1.gradientStops[0].color;
  var end = gradient1.gradientStops[gradient1.gradientStops.length - 1].color;

  var stop1 = gradient1.gradientStops.add();
  stop1.rampPoint = (bound1 - origin) / length * 100;
  stop1.color = setLerpColor(start, end, stop1.rampPoint);
  
  var stop2 = gradient1.gradientStops.add();
  stop2.rampPoint = (bound2 - origin) / length * 100;
  stop2.color = setLerpColor(start, end, stop2.rampPoint);
}

function setLerpColor(start, end, dist) {
  var t = dist / 100;
  var arr = [];
  var newColor;

  for (var key in end) {
    if (typeof end[key] === 'number') {
      arr.push( Math.round( lerp(start[key], end[key], t) ) );
    }
  }

  if (/rgb/i.test(activeDocument.documentColorSpace)) {
    newColor = new RGBColor();
    newColor.red = arr[0];
    newColor.green = arr[1];
    newColor.blue = arr[2];
  } else {
    newColor = new CMYKColor();
    newColor.cyan = arr[0];
    newColor.magenta = arr[1];
    newColor.yellow = arr[2];
    newColor.black = arr[3];
  }

  return newColor;
}

function lerp(start, end, t) {
  return start + (end - start) * t;
}

 

 

 

Votes

Translate

Translate

Report

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
Explorer ,
Jul 05, 2023 Jul 05, 2023

Copy link to clipboard

Copied

@Sergey OsokinThis worked perfectly on a quick test with a simple gradient. Is the expectation that the gradient only have 2 points previously? Will the script still work if there are multiple stops already on the band? See screen.

Votes

Translate

Translate

Report

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
Enthusiast ,
Jul 05, 2023 Jul 05, 2023

Copy link to clipboard

Copied

The solution was a two-point gradient. I know about your error with multiple gradient stops. The reason is that each time a new color is added to the gradient, the indexes in the array are rearranged and the new color is added to the end and cannot be moved to the left of the stop with index 2, for example. It will be necessary to move all the old and new stops, swapping their properties.

Votes

Translate

Translate

Report

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
Explorer ,
Jul 05, 2023 Jul 05, 2023

Copy link to clipboard

Copied

Yep, I figured it had to do with the index number associated with `stop.1` and `stop.2`. I may be able to workaround this, are the numbers for the stops sequential as you add them (example 2, 5, 3, 1) or variable based on how many you have and their relative position in the gradient, say left to right (1, 2, 3, 4)?

Votes

Translate

Translate

Report

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
Enthusiast ,
Jul 05, 2023 Jul 05, 2023

Copy link to clipboard

Copied

LATEST

In this example, after adding black, we need to move the purple color (1) to where we want to put black (2) and assign it a black color. Then we need to place the black color (2) on the position (1) and replace the black color with the purple color. I solved this problem in another script.

stops-indexes.png

Votes

Translate

Translate

Report

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 ,
Jun 29, 2023 Jun 29, 2023

Copy link to clipboard

Copied

quote

… So the gradient and object already exist, so the script doesn't need to create the gradient. …

… I wanted to know if I could script it to determine bounding box of object and add a two new stops at points equivelent to that object's bounding box…


By @culver-king

 

No. That is IMHO not possible with the current DOM (if the gradient exceeds the object boundaries).

 

That seems to be the only solution at the moment:

Remove the old gradient and create a new one with your desired values, as @femkeblanco  has already mentioned.

 

Interesting.

I have never used an origin or length for gradients. Excellent solution @femkeblanco

[ edited by pixxxelschubser ]

 

Votes

Translate

Translate

Report

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
Engaged ,
Jun 30, 2023 Jun 30, 2023

Copy link to clipboard

Copied

I have my own agenda on using this script (and thank you for trying to build a solution for this and posting it here, so others could help you), but I wonder still — what is the task you are having that requires this function? Please tell the story!

Votes

Translate

Translate

Report

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
Explorer ,
Jul 05, 2023 Jul 05, 2023

Copy link to clipboard

Copied

To recreate artwork consistently. Essentially, the gradient was built using two swatches but stretched way far out and beyond the bounding box of the object. So while the endpoints could be recreated, positioning them to match the values would have proven just guesswork. Now, using the master artwork(s) it will mathematically place markers exactly at those points and now I'd be able to create two new swatches that will now serve as gradient end points added as a swatch to any new object with the perceptual value of the original gradient.

Votes

Translate

Translate

Report

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