如何在Adobe Illustrator中开始编程。 第二部分

这篇文章是第一部分的续篇,在该部分中 ,我们展示并详细描述了“扩展剪切蒙版”脚本的作用和方式,并全面考虑了创建此类程序的基本原理。 在这一部分中,我将继续讲述如何为程序添加新功能,以便从“工件”获得“成品”的故事。 在这里,您必须深深地浸入主题区域,这是创建完整产品的必要条件之一。 因此,开始潜水!


以下图形基元可以用作Adobe Illustrator中的蒙版轮廓:简单轮廓(Path),复合轮廓(Compound Path),复合形状(Compound Shape)和文本对象(Point Text和Path上的Text)。 目前,该脚本仅适用于简单轮廓,如下面的代码所示,其中PathItem是对Path元素的调用。


  var clipGroup = sel[0].pageItems.length; for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PathItem' && sel[0].pageItems[i].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; 

在此之前,我们声明了变量clipPath ,但未为其分配值。


  var clipPath; 

这意味着尚未确定其值,即 它是undefined 。 如果现在我们选择一个轮廓为例如“复合路径”的遮罩并运行脚本,则程序将在脚本功能部分的最后一行产生错误,


  clipPath.remove(); 

由于将无法满足循环中的条件,因此clipPath变量将保持undefined ,并且无法将remove()方法应用于未定义的对象。 为了避免这种情况,我们将执行以下操作-将clipPath设置为null ,这与undefined不同,它已经是更具体的东西,您至少可以检查一下。


让我们考虑如何确定某些“复合路径”是否是蒙版的轮廓。 当我说“让我们思考”时,它意味着我建议您查阅文档并找到我们需要的属性。 类似于PathItem我们正在寻找clipping属性。 事实证明, CompoundPathItem对象没有这样的属性,但是有一个pathItems属性,通过它可以获取具有clipping属性的简单PathItem轮廓。

现在,我们可以将想法/搜索转换为代码。 首先,我们clipPath在先前的迭代中未定义clipPath ,然后复制已编写的代码块并对其进行少量更改。


  if (clipPath == null) { var clipGroup = sel[0].pageItems.length; for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; }; 

实际上,这些更改只会影响一行。 就像我们在这里看到的那样,“ PathItem”已更改为“ CompoundPathItem”,并且添加了新结构“ pathItems [0]”,在此我们引用了复合路径元素。


 if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) { 

以下是到目前为止已创建的功能代码块。


  var clipGroup = sel[0].pageItems.length; for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PathItem' && sel[0].pageItems[i].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; }; 

下一个“病人”是复合形状。 在这里变得非常有趣! 在文档中我们根本找不到这样的对象。 怎么办 首先,让我们定义它属于哪一类对象。 为了找出答案,我们将编写一个小的辅助代码,然后将其抛出。 如第一部分所述 ,我们没有解决用于编写/调试代码的工具的问题。 因此,假设这是一个单独的文件,然后将其直接放入垃圾箱。 代码如下:


 var obj = app.activeDocument.selection[0]; alert(obj.typename); 

在第一行中,我们创建到所选对象的链接,在第二行中,我们显示有关其类型的消息。 在Adobe Illustrator中选择遮罩的轮廓,即 相同的Compound Shape对象并运行脚本。 在消息框中,我们看到“复合形状”是一个PluginItem。 我们摆脱了辅助代码,再次返回文档,但是在PluginItem中找不到剪切属性或pathItems。 通常,没有什么可以帮助我们明确指出该对象是蒙版的轮廓。 从脚本中,您甚至无法确定它是哪种插件。 一些外部模块就是这样!


真是埋伏! -你内心惊呼。 大脑发狂地工作,希望解决一个无法解决的问题。 然后,浏览完所有可能和不可能的选项后,您拼命按Del键并删除讨厌的“复合形状”。 在这里,在“ Layers调板的视线之外,您会注意到,执行此操作后,蒙版容器(即Clip Group )变成了Group 。 什么意思 clipped对象的clipped属性从true变为false true 。 在这里,一个可行的解决方案! 当然,总的来说,这是一个骇客,但是如果它有助于确定所需的电路,它将产生什么不同。

确定由Composite Shape对象表示的蒙版轮廓的算法如下:循环遍历所有蒙版对象,当我们找到PluginItem时,将其删除,并检查蒙版容器的clipped属性是否已更改。 如果它变为false ,那么这就是我们的电路。 app.redraw()此hack起作用,唯一的事情是删除对象后更新DOM Illustrator,这可以使用app.redraw()方法完成。 然后,您仍然需要记住要返回远程对象,这是由app.undo()方法完成的。


下面是“复合形状”路径的代码:


  if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PluginItem') { sel[0].pageItems[i].remove(); app.redraw(); if (sel[0].clipped == false) { app.undo(); clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; 

现在,在可以作为遮罩轮廓的对象类型的所有可能选项中,仅保留文本(或Illustrator脚本参考中的TextFrameItem )。 我们一次又一次地转向文档,我们在那里找不到clipping属性。 但是这一次,我们不再对此太担心,可以平静地发现TextFrameItem具有用于确定文本对象类型( TextType )的kind属性。 我们发现可以有三种类型:AREATEXT,POINTTEXT和PATHTEXT。 第一种对我们来说并不有趣,因为它不能用作遮罩轮廓,而其他两种仍然很有趣。 剩下的只是找到一个hack,它将帮助我们现在确定轮廓,而不是轮廓,而是文本对象。 那个黑客将是转换为区域类型的团队,该团队会将POINTTEXT转换为AREATEXT。 与“复合形状”一样,对clipped属性的隐式更改clipped


因此,类型为POINTTEXT的TextFrameItem的代码如下:


  if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'TextFrame' && sel[0].pageItems[i].kind == 'TextType.POINTTEXT') { sel[0].pageItems[i].convertPointObjectToAreaObject(); app.redraw(); if (sel[0].clipped == false) { app.undo(); clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; 

只剩TextFrameItem类型为PATHTEXT的TextFrameItem。 不幸的是,将PATHTEXT转换为AREATEXT时,clipped属性clipped更改。 但是,由于这是标题“遮罩轮廓”的最后一个可能的候选者,因此可以使用这种行为。 也就是说,我们验证执行“ Convert To Area Type clippedclipped属性保持为true 。 以下是PATHTEXT类型的TextFrameItem的代码。


  if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'TextFrame' && sel[0].pageItems[i].kind == 'TextType.PATHTEXT') { sel[0].pageItems[i].convertPointObjectToAreaObject(); app.redraw(); if (sel[0].clipped == true) { clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; 

因此,如果我们将顺序编写的代码片段(包括一段检查代码)放在一起,我们将获得这样的代码,如文章第一部分所述 ,其执行将实现Adobe Illustrator中新的Expand Clipping Mask命令的操作。


 #target illustrator if (app.documents.length > 0) { var doc = app.activeDocument; var sel = doc.selection; var clipPath = null; if (sel.length > 0) { if (sel[0].typename == 'GroupItem' && sel[0].clipped == true) { var clipGroup = sel[0].pageItems.length; for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PathItem' && sel[0].pageItems[i].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PluginItem') { sel[0].pageItems[i].remove(); app.redraw(); if (sel[0].clipped == false) { app.undo(); clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'TextFrame' && sel[0].pageItems[i].kind == 'TextType.POINTTEXT') { sel[0].pageItems[i].convertPointObjectToAreaObject(); app.redraw(); if (sel[0].clipped == false) { app.undo(); clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'TextFrame' && sel[0].pageItems[i].kind == 'TextType.PATHTEXT') { sel[0].pageItems[i].convertPointObjectToAreaObject(); app.redraw(); if (sel[0].clipped == true) { clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; app.executeMenuCommand('releaseMask'); clipPath.remove(); } else { alert ('   -!'); }; } else { alert ('  !'); }; } else { alert ('  !'); }; 

在这里您可以结束。 不,分号更好。


希望通过这些文章,我可以帮助您更加接近您的目标-开始在Adobe Illustrator中进行编程。 感谢您的关注!

Source: https://habr.com/ru/post/zh-CN452614/


All Articles