Illustrator ExtendScript set FILL opacity of selection - javascript

Is there any way to access a pathItem's fill opacity with javascript? I can access the overall opacity, but I want to lower the opacity of the fill while keeping the stroke fully opaque.
I can't find anything in the documentation, nor can I find anyone else asking this question.
I can set the overall opacity like so:
var selection = app.activeDocument.selection;
selection[0].opacity = 50;
I've tried every variant of "fillOpacity" that I can think of, like this:
var selection = app.activeDocument.selection;
selection[0].fillOpacity = 50;
selection[0].FillOpacity = 50;
selection[0].fill.opacity = 50;
...but it doesn't work.
Am I going about this wrong, or is this just not possible?

You cannot access it, as you cannot access it normally even in illustrator. This is a Photoshop property only. I checked the documentation as well just to make sure. What you could do is this though and it would accomplish same thing:
doc = app.activeDocument;
i = 0
var selection = doc.selection[i];
var storedColor = doc.selection[i].fillColor;
//new object with only fill, we send it to back so it doesn't overlap stroke, if there is one
var newObject = app.selection[i].duplicate(doc, ElementPlacement.PLACEATEND);
//turn off fill for first object
doc.selection[i].filled = false;
i = i + 1;
newObject.stroked = false;
//apply stored color from earlier to new shape
newObject.fillColor = storedColor;
newObject.opacity = 50;
newObject.name = "50p fill";

What I did to solve the problem is to apply a spotcolor to the objects where I uses the tint property
var docRef = app.activeDocument;
var selectedObjects = docRef.selection;
var theTint;
var fillwithSwatch = function (pathItems, sname ){
for (var i=0;i< pathItems.length; i++){
pathItems[i].fill = true;
theTint = pathItems[i].fillColor.gray;
pathItems[i].fillColor = docRef.swatches.getByName ( sname ).color ;
pathItems[i].fillColor.tint = theTint;
}
}
theTint = fillTint(selectedObjects);
// the spotcolor should be in the swatchpallet already
fillwithSwatch (selectedObjects, "myBlue" );

Related

How to declare several CANVAS with different contexts (ctx) in an array?

I'm using several CANVAS in a HTML file and I want to declare them in an Array. This is the (not array) declaration:
var canvas0 = document.getElementById('canvas0');
var ctxPaint0 = canvas0.getContext('2d');
var canvas1 = document.getElementById('canvas1');
var ctxPaint1 = canvas1.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxPaint2 = canvas2.getContext('2d');
var canvas3 = document.getElementById('canvas3');
var ctxPaint3 = canvas3.getContext('2d');
To optimize this, I'm trying to use For loops, but it doesn't work:
var canvasArray = ["canvas0","canvas1","canvas2","canvas3"];
for (var i = 0; i < canvasArray.length; i++) {
window["canvas"+i] = document.getElementById(canvasArray[i]);
window["ctxPaint"+i] = canvasArray[i].getContext('2d');
}
It outputs this error:
Uncaught TypeError: canvasArray[i].getContext is not a function
EDIT:
Thanks to RSchneyer, changing the Array of strings to an Array of Canvas works fine now:
let canvasArray = Array.from(document.getElementsByTagName("canvas"));
for (var i = 0; i < canvasArray.length; i++) {
window["canvas"+i] = document.getElementById(canvasArray[i]);
window["ctxPaint"+i] = canvasArray[i].getContext('2d');
}
You could do like
const ctxArray = [...document.querySelectorAll('[id^="canvas"]')].map(cvs => cvs.getContext('2d'));
which will result to an array holding all the canvases context - which is all you need, since to get the original canvas out of its context all you need is i.e.:
let i = 0; // or any desired index
const canvas = ctxArray[i].canvas;
canvasArray is an array of strings, which don't have a getContext() function. Try replacing the canvasArray[i] in window["ctxPaint"+i] = canvasArray[i].getContext('2d'); with window["canvas"+i], or create another array to hold your actual canvas variables

web browser crashes invoking REST for Image Data in Uint8ClampedArray JavaScript

In my Project, I have multiple Graphs (max 15 of different plots like Bar , Chart , Bubble, Line) that are being plotted using javascript (Open/SAP UI-5) in HTML5 below is the code for the same
press: function() {
var arrCanvas = document.getElementsByTagName("canvas");
for(var i=0; i<arrCanvas.length; i++){
var canvas = arrCanvas[i];
if(canvas.width!==0 && (typeof imageNames[i] !== 'undefined')){
var imageDetail = {};
var uint8ArrayClamped = canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height).data;
imageDetail.byteData = uint8ArrayClamped;
imageDetail.title = "graph-"+i;
imageDetail.height = canvas.height;
imageDetail.width = canvas.width;
arrImageByte.push(imageDetail);
}
}
}
When I pass this arrImageByte to Ajax call the browser (tested on chrome) crashes with "oh snap" message.
while adding below line to the code
press: function() {
var arrCanvas = document.getElementsByTagName("canvas");
for(var i=0; i<arrCanvas.length; i++){
var canvas = arrCanvas[i];
if(canvas.width!==0 && (typeof imageNames[i] !== 'undefined')){
var imageDetail = {};
var uint8ArrayClamped = canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height).data;
//I belive somwhow This does the trick
imageDetail.byteData = [].slice.call(uint8ArrayClamped);
imageDetail.title = "graph-"+i;
imageDetail.height = canvas.height;
imageDetail.width = canvas.width;
arrImageByte.push(imageDetail);
}
}
}
Copying the unit8ArrayClamped into another empty array does the trick, now the code work and REST is being called, I wonder why this is happening?
but again copying such a huge data into another takes time and for multiple graphs, it takes almost 6-7 seconds, how to reduce this to minimal?
Is there another approach besides copying the byte array into another new array?

Javascript Adobe Illustrator script -change strokewidth of all items

I have around 200 SVG files on which I need to change the strokecolor to gray and change the strokewidth of all lines to .2pt.
I would like to script out the equivalent of doing in the interface - 'Select ALL' and then entering the .2 pt for the strokewidth manually.
Right now, my script is changing all the colors to gray (working fine) and SOME of the lines to a stroke width of .2pt.
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
var doc = app.activeDocument;
for ( i = 0; i <doc.pathItems.length; i++ ) {
pathArt = doc.pathItems[i];
pathArt.strokeWidth = .2;
pathArt.strokeColor = makeColor(153,153,153);
pathArt.filled = false;
}
function makeColor(r,g,b){
var c = new RGBColor();
c.red = r;
c.green = g;
c.blue = b;
return c;
}
Perhaps I am not selecting all objects through the script correctly?
Is selecting the pathitems as I have done above the correct approach to achieve the equivalent of a CTRL-A, and then some operation manually?
Thanks so much for your time!
As of AI CS3, when a path is not stroked, the .strokeColor property applies while the .strokeWidth property doesn't.
Add the code pathArt.Stroked = True; to fix your problem
Also note that you don't iterate CompoundPathItems
Here is the complete script, that will ask you to select the folder. So select folder that has 200 SVG files. This script will process all SVG files in the selected folder and change stroke color to gray and also change its width.
var folder = Folder.selectDialog();
if (folder) {
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
var color = makeColor(153, 153, 153);
var files = folder.getFiles("*.svg");
for (var j = 0; j < files.length; j++) {
app.open(files[j]);
var doc = app.activeDocument;
for (i = 0; i < doc.pathItems.length; i++) {
pathArt = doc.pathItems[i];
pathArt.stroked = true;
pathArt.strokeWidth = .2;
pathArt.strokeColor = color;
pathArt.filled = false;
}
doc.close(SaveOptions.SAVECHANGES);
doc = null;
}
}
function makeColor(r, g, b) {
var c = new RGBColor();
c.red = r;
c.green = g;
c.blue = b;
return c;
}
You can change the script for locked and hidden items as well if you want to handle for locked and hidden items.

Identify each drawn path in Fabric JS

I am trying to identify each drawing.
For example after I draw an object I want that object to have the propriety name = "My Drawing 1" so I can easily refer to it later by
canvas.getObjectByName('My Drawing Name');
getObjectByName function
fabric.Canvas.prototype.getItemByName = function(name) {
var object = null, objects = this.getObjects();
for (var i = 0, len = this.size(); i < len; i++) {
if (objects[i].name && objects[i].name === name) {
object = objects[i];
break;
}
}
return object;
};
The code that activates drawing function:
canvas.isDrawingMode = true;
var img = $("#patternImg")[0];
var texturePatternBrush = new fabric.PatternBrush(canvas);
texturePatternBrush.source = img;
texturePatternBrush.selectable = true;
texturePatternBrush.name = img.getAttribute("data-name");
canvas.freeDrawingBrush = texturePatternBrush;
canvas.freeDrawingBrush.width = img.getAttribute("data-height");
Using the code above I can check if can verify if a drawing exists by:
fabric.Canvas.prototype.getDrawByName = function(name) {
var object = null, objects = this.getObjects();
for (var i = 0, len = this.size(); i < len; i++) {
if (objects[i].canvas.freeDrawingBrush.name && objects[i].canvas.freeDrawingBrush.name === name) {
object = objects[i];
break;
}
}
return object;
};
The problem is each time I am drawing an object that has another name canvas.FreeDrawingBrush.name will be the same for each object on my canvas.
I am not so familiar with FabricJS and I don't even know if what I am trying to do is even possible. At least I made myself clear what I am trying to do ?
When accessing the canvas property of a fabric.Object, you are simply getting a reference to the fabric.Canvas element that this object is rendered on. The freeDrawingBrush property of this fabric.Canvas element will always be the current free drawing brush.
Instead, I would set this name property onto each individual object, when it is done drawing. (This could be when you exit from drawing mode, or perhaps right before you switch to a different brush) using fabric.Object.set method.
Doing it this way, you aren't relying on an object's canvas property in any way.

How do I set the style of SVG CSS attributes in Javascript?

I'm trying to dynamically determine the length of an array of SVG paths and then insert this value into the HTML DOM style object for the attributes stroke-dasharray and stroke-dashoffset.
var horizontals = document.getElementsByClassName('hLine');
for (var i = 0; i < horizontals.length; i++ ) {
var drawingComponent = horizontals[i],
length = svgPiece.getTotalLength();
horizontals[i].style.strokeDasharray = length;
horizontals[i].style.strokeDashoffset = length;
}
In the example found here, all the .hLine paths (all the horizontal lines) should animate, but they do not.
Is this because strokeDasharray and strokeDashoffset aren't supported?
For a start, there are some things wrong with that Javascript:
var horizontals = document.getElementsByClassName('hLine');
Your SVG doesn't have any elements with the class 'hLine'.
length = svgPiece.getTotalLength();
'svgPiece' is not defined anywhere.
Try something like this:
var horizontals = document.querySelectorAll('#horizontal path')
for (var i = 0; i < horizontals.length; i++ ) {
var path = horizontals[i],
length = path.getTotalLength();
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
}
Demo here - although there is still some work to do to get the animation working properly.
You can always also just fix the path length by setting pathLength (https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/pathLength) to a value (like 100 for easy percent-based modification).

Categories