Unable to programmatically create a clipping mask in Illustrator with Extendscript - javascript

I am having trouble creating a clipping mask in Illustrator using ExtendScript, the problem is that im trying to create it by using compound path item.
In adobe illustrator i can group the compound path item with the background and press "Create new mask" and every thing works, but i cant do it programatically
If i use a path item (not compound path) and the next code:
newGroup1.clipped = true;
It works, but if i sustitute the path item for a compund path item, it doesnt work.
The code:
app.activeDocument.newGroup1.selected = true;
app.executeMenuCommand("makeMask");
With simple compound path items, it work, but with complex compound path items i get a message box that said that the paths are so complex and it could affect the preview. After i press ok it works, but this message box does not allow me to do a batch process.
Is there any way to programatically create clipping mask by using complex compound path items??

If I understand you correctly, your setup basically works, the only problem are the message boxes.
However, those can be supressed in a script by setting the app's userInteractionLevel:
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
If you do this, it's usually good practice to save the initial userInteractionLevel at the beginning of the script and then in the end, reset it to its initial value:
myUserInteractionLevel = app.userInteractionLevel;
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
// then do all your stuff
// and in the end, reset:
app.userInteractionLevel = myUserInteractionLevel;

Related

How to apply transformation to selection in Illustrator by scripting

I managed to select every thing I want in Illustrator with a ExtendScript Toolkit javascript code: lots of things (text, path, symbols, ...) in several layers. Now I want to resize them the same way, then move them.
I know how to apply a transformation to one object by code, but I want to avoid looping on each element because it would be very very long and transformation would be applied from the anchor point of each element, so my drawings wouldn't be cohesive.
So, I am looking for a way to do like in Illustrator UI: right click > transform > scale. Is there any UI command like this I could access from code (javascript)?
There are at least three ways to do this:
Record AI Actions that perform required transformations, and then play these Actions (by DoScript) from your script
Group selected objects and apply required transformations to the group as #Dane proposed. You need to backup the Layer object property to allow objects to be restored in original layers, as shown in VBA example below:
For i = Index_Lo To Index_Hi
Call Layers_Backup.Add(Item:=SelectedItems(i).Layer, Key:=Format(i))
Call SelectedItems(i).Move(Temp_Group, AiElementPlacement.aiPlaceAtEnd)
Next i
Call Temp_Group.Resize(scaleX:=120, scaleY:=120, changeLineWidths:=120)
For i = Index_Lo To Index_Hi
Call SelectedItems(i).Move(Layers_Backup(Format(i)), AiElementPlacement.aiPlaceAtEnd)
Next i
Call Windows API functions (like PostMessage (..., WM_COMMAND, ..., ...), SendDlgItemMessage, FindWindowEx etc) to show, fill and execute required AI transformations dialog boxes
IMHO, item #1 is the easiest to implement while item#2 is the most reliable
So I dont know if you can get away with not looping in some form or other. that said, if you dont mind putting your selection in to a group, it might be faster to loop through your selection adding to a group which might be faster than looping and through the selection and scale and moving each element. With the group object you can then do groupObject.scale() and .translate().
Here is a snippet i took from a script of mine.
#target "illustrator"
var aiApp = app.activeDocument;
var aSelection = aiApp.selection;
var aGroup = app.activeDocument.groupItems.add();
for (i=0; i < aSelection.length; i++){
aSelection[i].move( aGroup, ElementPlacement.INSIDE);
aSelection[i].move( aGroup, ElementPlacement.PLACEATEND);
}
//moves up 700 points and scales by 200
aGroup.translate(0,700)
aGroup.resize(200, 200, true , true, true, true, 200)

Drawing plots interactively in a web app

I am looking for a library preferably in JavaScript, that will allow a user to draw a plot (simple one consisting of vertical and horizontal steps) like this one:
The idea is that when the user is done with the plot I can generate data points from the graph and process them.
I don't know where to start, I am looking to start learning to do this within a JS based framework (meteor) but I can't find a library that allows for something like this. The closest library I found is d3.js but I couldn't find any example that allows for this.
Would anyone be able to point out to me a sample example to start from? Would you know of a better suited library to accomplish what I am asking for?
Here is a relatively simple fiddle which accomplishes some of what you asked for, excluding axis (which are relatively easy and has plenty of examples). It uses D3 for all the drawing and mouse event handling. On click it simply executes svg.append("circle").attr("r", 5), and if it's not the first click (i.e. linking points) then it also will create a path element using the previous mouse click coordinates:
svg.insert("path", "circle").attr("d", function () {
return [
"M", prevClickLoc[0], prevClickLoc[1],
"L", prevClickLoc[0], y,
"L", x, y].join(" ");
})
Where x and y are the current mouse coordinates. Also has an export button that will output a list in the form of cx,cy,cx,cy,... :: d,d,d,d,.... On import, you could easily split this array into two using indexOf("::") or whatever you choose if you want to change the formatting. Then just exectue for (x in circles) {svg.append("circle").attr("cx", function...).attr("cy", function...);} and do something similar for paths for (y in paths) {svg.append("path").attr("d", function(){return paths[y];});}. It would be even easier if on export you made the cxcy array in the format cx;cy,cx;cy since then you could simply split the array at each comma and then split each index of the resulting array at the semicolon for a nice nested array.
Small update in this version, you can only place points if the current mouse x is greater than the previous x coordinate, and it also has the line d3.event.stopPropagation(); which prevents accidental highlighting of the page.

InDesign extendScript: How do I transform the entire selection?

By using the simple array app.selection[x], you can apply a transformation to any object in the selection, independently. But how do I apply a transformation to the entire selection together?
For example: inside InDesign, I can select two side-by-side objects and flip them horizontally, causing them to switch places and flip.
Inside a script, I can target each object in the selection, but they will not switch places; they will remain in the same place and flip.
for ( var x = 0; x < app.selection.length; x++ ){
app.selection[x].absoluteFlip = Flip.HORIZONTAL;
}
I could possibly group the selection, apply a transformation, then ungroup when finished, but this seems like unnecessary bulk that could slow down the code. I can easily do it manually inside InDesign, so it should follow that there's some way to access app.selection as a single object instead of an array. Does such an object exist?
Not really a solution, but it's worth noting that I don't think absoluteFlip is the action being performed, but a state indicating if the item has ben flipped. It's writable so you can set the state, but I think what's happening when using the menu to flip is flipItem: http://jongware.mit.edu/idcs6js/pc_PageItem.html#flipItem,
in which you can set "around" coordinates.
Now getting the origin of the selection box isn't straightforward for some reason (or maybe it is but I don't know how), but you can either use first object coordinates to set the origin so you can flip it around different coordinates depending on order of selection. Or you can sort the array to find left most coordinates (or whichever is needed), like this:
var selection_array = app.selection;
selection_array.sort(function(a, b){return a.visibleBounds[1]-b.visibleBounds[1]})
var flip_origin = [selection_array[0].visibleBounds[1],selection_array[0].visibleBounds[0]]
for(i=0;i<app.selection.length;i++){
app.selection[i].flipItem(Flip.HORIZONTAL, flip_origin);
}
Not sure it's easier or faster than grouping and ungrouping though.
Consider resize. It has a "individual/global" parameter :
void resize (in: varies, from: varies, by: ResizeMethods, values: Array of varies[, resizeIndividually: bool=true][, consideringRulerUnits: bool=false])
Resize the page item.

how to get the html file of an edited canvas in html5

I am trying to make a website which helps its users to create a page by dragging and dropping elements on the canvas. The user should be able to save the html file of the edited canvas. I cannot figure how to convert the changes made to the canvas to an html file.
I don't think it's possible to get Markup out of canvas. I've searched it for a month but can't find a valid solution. but may be some experts may know. Best of luck buddy.
Canvas is basically just a bit-map image. Whatever you draw on the canvas is stored as pixels not as elements. So changes to the canvas are just changes in pixel values. To do what you wish you would need to store your 'elements' as 'objects' within your code where each 'object' stores all the required data for your 'element'.
it would then be possible to open a new window and export code into it using document.writeln
The code below may give you an idea of what sort of thing would be needed
newwindow=window.open('','_blank');
newwindow.document.writeln('<!DOCTYPE HTML>');
newwindow.document.writeln('<html>');
newwindow.document.writeln('<head>');
newwindow.document.writeln('<style>');
newwindow.document.writeln('#element0 {');
newwindow.document.writeln('background:'+ obj0.background+';');
newwindow.document.writeln('width:'+ obj0.width+';');
newwindow.document.writeln ('}');
newwindow.document.writeln('</style>');
newwindow.document.writeln('</head>');
newwindow.document.writeln('<body>');
newwindow.document.writeln('<div id="element0"></div>');
newwindow.document.writeln('</body>');
newwindow.document.writeln('</html>');
newwindow.document.writeln('<html>');
newwindow.document.close();
Hope this helps
Canvas won't help you here for anything other than to visualize the objects you have dropped onto it.
You need to record the objects you drop in a "shadow" structure behind the scene sort of. That is to say: build a object list internally which you then can use as source data to render:
Canvas visualization of it
Raw HTML code from it.
You can for example drop an image to the canvas and your code will record a new object (intention with the following code is to show the principle not to provide a full working solution):
var myObjects = [];
/// a drop occurred
var o = new myElement(x, y, width, height, id, type);
myElement is a pre-defined object that you set up in advance to hold the given arguments.
Then push the object to your object stack and render it to canvas:
myObjects.push(o);
for(var i = 0, o; o = myObjects[i]; i++) {
/// draw the look of this object here to canvas
}
When you then need a HTML version of it you do the same:
for(var i = 0, o; o = myObjects[i]; i++) {
var el = '<' + o.type + ' id="' + o.id + ' .... other things here
}
This way you can produce canvas graphics, HTML, send data over a socket etc.
The key in these sort things is to keep raw base data available. In this case it would be the element type you want to drop, its position and dimension. For HTML you also have to consider things as nesting etc. but that would require a bit more code than shown here.

Processing: how can shapes form a text?

i wonder how this is made: http://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage
Those spots form a text and when clicked , they explode.
How can shapes form a text? Can i achieve this with processing.js?
Thanks.
I guess one way is to have a model for each character. For example, manually create the letter 'A' via shapes. Then for each letter in the message, you would display the character model for the letters
I'm not sure if you want to write this in processing or in javascript. This is a javascript library, so you can use it in a javascript context. To make it on processing and use processingjs to display it on web you got to use processing resources to achieve the same result or manage to pass data from/to javascript and processing. There is this example from processingjs site on connecting your page with a processing sketch. Note that processingjs does not support use of processing libraries, so you can't use any of Precessing typography libraries in this workflow. I think that they could be very handy though...
As how doing this on processing, i think i would go for drawing letters in a not displayed PGraphics, and using a pixel color test on this surface to drive the drawings of the circles. This would allow to alter the text in run time. Like, in pseudo code
PGraphics matteImage = new PGraphics(size, size, render);//
matteImage.background(black);
matteImage.fill(255);
matteImage.text("A", x,y);
matteImage.loadPixels();
for(i; i < matteImage.length;i++)
{
color c = matteImage.pixels[i];
if ( c == white)
{
doDrawEllipses();
}
}
In drawing circles method/class i would add some noise/randomness, exploding handle...

Categories

Resources