Comment démarrer la programmation dans Adobe Illustrator. Première partie

Je veux vous avertir tout de suite que cette série de publications n'est pas destinée aux programmeurs chevronnés, ni même aux programmeurs. Je comprends que cela semble extrêmement provocant, étant donné le thème informatique de la ressource, et laissez-moi quand même vous expliquer ... En tant que public, je vois des concepteurs ordinaires qui aimeraient commencer la programmation dans Adobe, mais pour une raison quelconque (par peur de inconnue, manque de confiance dans leurs capacités ou méconnaissance de la langue) ne peut pas faire les premiers pas dans cette direction. Je vois ma modeste tâche en les aidant à comprendre que «ce ne sont pas les dieux qui brûlent les pots» et toute personne suffisamment motivée peut apprendre à écrire du code de programme de travail. Il est possible que certains d'entre eux soient tellement emportés par ce jeu qu'ils décident de devenir de vrais développeurs. Quel code ne plaisante pas?


Cet article vous expliquera comment écrire votre propre petit outil (script JavaScript) pour créer votre propre outil unique dans Adobe Illustrator, ce qui réduira non seulement votre temps, mais améliorera également l'interaction avec ce merveilleux éditeur graphique. Tout d'abord, je formulerai le problème, puis je montrerai le code qui le résout et, ensuite, je vous expliquerai en détail comment il a été créé. Il ne discutera pas des bases de Javascript, des fonctionnalités du modèle objet Illustrator ou des divers éditeurs pour écrire / déboguer du code. Vous pouvez trouver ces informations vous-même si vous le souhaitez. L'essentiel, à mon avis, est une compréhension des principes de base des programmes d'écriture, qui est l'accent principal dans cet article. Si vous êtes prêt à sauter juste au-dessus de votre tête, bienvenue dans la coupe!


Adobe Illustrator dispose d'un outil Masque d'écrêtage qui fonctionne avec les masques d'écrêtage. Le masque d'écrêtage contient trois commandes: créer, relâcher et modifier le masque. Le premier crée un masque, le second - analyse, le troisième - vous permet d'éditer. Nous nous intéressons à la deuxième commande, qui divise l'objet Masque d'écrêtage en un contour et le contenu du masque. Très souvent, il est nécessaire non seulement de démonter le masque, mais également de se débarrasser du contour du masque, en ne laissant que le contenu. La commande régulière Release Masque d'écrêtage ne fait pas cela, donc après l'avoir appliquée, vous devez effectuer trois autres étapes:


  1. Supprimer la sélection des objets
  2. Sélectionner uniquement le contour du masque
  3. Supprimer le contour du masque

Si vous devez effectuer cette opération séquentielle assez souvent pendant la journée, la question se pose: est-il impossible de réduire en quelque sorte le nombre de ces actions pour obtenir le même résultat? Et le point ici n'est pas du tout la paresse, mais le manque de l'outil nécessaire. Imaginez maintenant une seconde que vous disposez d'un tel outil.


Ici, vous êtes brièvement distrait du travail et plongé dans des réflexions sur la façon dont ce serait cool s'il y avait une équipe dans l'arsenal d'Adobe Illustrator comme le Expand Clipping Mask qui a effectué toutes ces actions pour vous. Idée sympa! Vous devez rédiger un support technique pour Adobe, vous pensez. La pensée suivante: tout d'un coup, ils ont été écrits à ce sujet plusieurs fois? Et si un jour et peut-être qu'ils ajouteront un tel outil, qu'est-ce que cela vous fait? Cette équipe est nécessaire ici et maintenant!

Et voici le moment de vérité - vous pouvez écrire un script vous-même!

Aussitôt dit, aussitôt fait!


1 #target illustrator 2 if (app.documents.length > 0) { 3 var doc = app.activeDocument; 4 var sel = doc.selection; 5 var clipPath; 6 if (sel.length > 0) { 7 if (sel[0].typename == 'GroupItem' && sel[0].clipped == true) { 8 var clipGroup = sel[0].pageItems.length; 9 for (var i = 0; i < clipGroup; i++) { 10 if (sel[0].pageItems[i].typename == 'PathItem' && sel[0].pageItems[i].clipping == true) { 11 clipPath = sel[0].pageItems[i]; 12 break; 13 }; 14 }; 15 app.executeMenuCommand('releaseMask'); 16 clipPath.remove(); 17 } 18 else { 19 alert ('   -!'); 20 }; 21 } 22 else { 23 alert ('  !'); 24 }; 25 } 26 else { 27 alert ('  !'); 28 }; 

Voici un si petit code pour aider à résoudre ce problème. Au lieu de plusieurs, déjà dans l'ordre des actions ennuyées, vous n'avez qu'une seule chose à faire: exécuter le script Expand Clipping Mask. Vous disposez maintenant d'un outil pratique pour travailler avec des masques, fabriqué par le même bricoleur.


Bien sûr, ici, je suis un peu rusé. Premièrement, le script n'a pas été écrit par vous, et deuxièmement - il n'est pas aussi universel que nous le souhaiterions. Cependant, si vous êtes intéressé par la façon dont cela fonctionne, et surtout, comment apprendre à écrire de tels programmes vous-même, alors je serai heureux de vous en parler dans l'ordre et avec des commentaires détaillés.


Pour commencer, tout script (script / programme / code JavaScript) se compose de plusieurs blocs de code principaux: déclarations (initialisation) de variables, vérifications de base (conditions) et, disons, le «moteur de programme» - code qui implémente la principale fonction de travail script. Bien sûr, cette division est très arbitraire, car la partie fonctionnelle a également des contrôles, mais le principe structurel est le suivant. Naturellement, plus le programme est grand, plus il sera difficile de le diviser en blocs similaires. Mais dans notre cas, c'est possible. Les lignes 8 à 16 sont le moteur de script, les lignes restantes sont des déclarations de variables et diverses vérifications de base avec leur traitement. Si vous comptez, il s'avère que le nombre de lignes dans le bloc de vérification est supérieur au nombre de lignes dans le bloc fonction. Ces contrôles sont-ils vraiment importants?


Pourquoi avons-nous besoin de chèques?


Les programmeurs sérieux me comprendront et il sera utile pour les développeurs débutants de le découvrir. Des vérifications sont nécessaires afin d'assurer le fonctionnement normal de la partie fonctionnelle du programme. Si vous ne les écrivez pas, toute erreur lors de l'exécution du script entraînera une panne logicielle. Et ce n'est pas bon.


Bien sûr, les camarades sérieux mentionnés ci-dessus utilisent la construction try / catch à de telles fins, mais j'ai décidé que l'habituel if / else serait une construction laconique et plus compréhensible. Surtout pour les scénaristes novices.


Examinons en détail ce que font ces lignes. La première ligne est responsable du fait que même si le script n'est pas exécuté à partir d'Adobe Illustrator, il y sera exécuté. Par conséquent, si vous exécutez le script à partir d'Illustrator, cette ligne peut être omise.


 #target illustrator 

Ensuite, il recherche les documents ouverts dans Adobe Illustrator au moment de l'exécution du script. Ces lignes doivent être lues comme suit: si ( if ) dans l'application ( app ) le nombre de documents ( documents.length ) est supérieur à zéro (> 0), alors le code entre {...} doit être exécuté. Sinon ( else ), affichez le message ( alert ) 'Pas de documents ouverts!' et terminer le script.


 if (app.documents.length > 0) { ... ... } else { alert ('  !'); }; 

Le bloc de code suivant vérifie la sélection dans le document.


  if (sel.length > 0) { ... ... } else { alert ('  !'); }; 

Il convient de noter que si dans les exemples précédents, nous avons utilisé des noms réservés (tels que des app ou des documents ), nous utilisons ici la variable sel, que nous avons nous-mêmes déterminée aux lignes 3 et 4,


  var doc = app.activeDocument; var sel = doc.selection; 

doc est le lien vers le document Illustrator actif et sel est le lien vers le ou les objets sélectionnés dans le document actif.


Une référence (ou référence) est un pointeur vers un objet spécifique. Bien sûr, je suis bien conscient que le mot russe complètement inoffensif "pointeur" est capable d'introduire dans la stupeur toute personne qui n'est pas familière avec la POO (programmation orientée objet). Mais prenez un mot, tout n'est pas aussi compliqué qu'il n'y paraît. Les liens sont stockés dans des variables et sont utilisés pour accéder aux objets. Dans la variable doc , nous enregistrons (attribuez-lui une valeur à l'aide de l'opérateur d'affectation = ) un pointeur vers le document actif (activeDocument) de l'application (app), et dans la variable sel , nous enregistrons le pointeur vers la sélection (sélection) dans le document actif (activeDocument) de l'application (app). Pour éviter d'écrire à nouveau app.activeDocument, nous utilisons à la place la variable doc , qui contient déjà ce code. C'est pourquoi le lien ressemblera à sel = doc.selection . J'espère que je l'ai clairement expliqué.

Ainsi, dans cette condition, if (sel.length > 0) il est vérifié s'il y a des objets sélectionnés dans le document actif, et sinon, le message s'affiche: 'Il n'y a pas d'objets sélectionnés!'


Les lignes suivantes vérifient la véracité, désolé pour le jeu de mots, deux conditions à la fois. Le premier que l'objet sélectionné est un groupe ( GroupItem ) et (&&) le second que ce groupe est vraiment un masque d'écrêtage (la propriété clipped de cet objet est true ).


  if (sel[0].typename == 'GroupItem' && sel[0].clipped == true) { ... ... } else { alert ('   -!'); }; 

Ici, nous avons besoin d'une petite explication.


Qu'est-ce qu'un objet masque? C'est un groupe, mais pas un groupe ordinaire. Un groupe régulier est une collection d'objets différents qui est subordonnée, disons, à l'objet «principal» ou «parent». Quant à l'objet masque, il s'agit également d'un groupe, mais contrairement à l'habituel, il se compose de deux parties - le contour du masque et son contenu. Ainsi, pour déterminer à partir du script que devant vous se trouve un groupe régulier ou un groupe de masques, sa propriété clipped permet. Si la valeur de la propriété clippée est false (false), il s'agit d'un groupe normal; si true (true), alors il s'agit d'un groupe de découpage.

Les esprits curieux remarqueront qu'au lieu de la variable sel que nous avons définie précédemment, la construction sel[0] est utilisée. Cela s'explique par le fait que, du point de vue du script, une sélection est une collection (collection) d'éléments, et non un objet spécifique (même si un seul objet est sélectionné). Et pour vérifier que le type ( typename type) de cet objet correspond au type de l'élément de collection sélectionné, la construction sel[0] est utilisée, qui fait référence au premier élément [0] de la collection, c'est-à-dire, dans notre cas, le groupe sélectionné.


Par conséquent, si l'objet sélectionné est à la fois un groupe et un masque, le code suivant est exécuté, sinon le message s'affiche: «La sélection n'est pas un objet masque!


Avec des chèques - c'est tout. Allez-y.


Comment le code principal a-t-il été créé?


Dans cette partie de l'article, je vais essayer non seulement de commenter le fonctionnement du code, mais aussi de décrire le processus de sa création. Si ce n'est pas l'ensemble du processus, alors au moins quelques points clés. Commençons!


Auparavant, trois actions ont été décrites qui doivent être effectuées pour résoudre la tâche de «démontage» du masque d'écrêtage avec la suppression ultérieure du contour du masque. Ils seront complétés par une autre action (commande Release), à ​​partir de laquelle notre algorithme commencera. Je vais les répéter ici pour rafraîchir le contexte.


  1. Exécutez la commande Release Clipping Mask
  2. Supprimer la sélection des objets
  3. Sélectionner uniquement le contour du masque
  4. Supprimer le contour du masque

Si vous implémentez cette séquence d'actions strictement selon la liste, les deux premiers points peuvent être facilement résolus en appelant la méthode executeMenuCommand() . Mais ensuite, au troisième point, nous serons confrontés à un problème insoluble. Comment obtenir un lien vers le contour du masque, si après la première action (Release Clipping Mask) il n'y a plus de masque, mais seulement un ensemble d'objets sélectionnés? Oui, et il n'est pas structurellement le même qu'avant d'effectuer cette opération.


En général, la logique suggère que vous devez d'abord créer un lien (référence) vers l'objet de contour de masque. Après avoir réfléchi à ce qui PathItem contour de masque si unique par rapport au contour normal, nous trouverons la propriété d' clipping de la classe PathItem . Il ne nous reste plus qu'à PathItem tous les objets du groupe de masques dans la boucle (pour) et trouver le PathItem avec la propriété clipping = true . Ce sera le circuit souhaité. À la suite de l'exécution de ce code, nous obtiendrons un lien vers l'objet contour de masque et l'enregistrerons dans la variable clipPath .


  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; }; }; 

Et ensuite? Revenons à l'algorithme et écrivons le code de l'élément 1. Cette ligne exécute la commande Release Clipping Mask, mais pas via l'interface utilisateur, mais à partir du script. Oui, si simple!


  app.executeMenuCommand('releaseMask'); 

Nous sautons les étapes 2 et 3 (car nous avons déjà un contour de masque, ou plutôt un lien vers l'objet clipPath) et passons directement à l'étape 4. Ici, nous appelons la méthode remove() de l'objet clipPath . Cette méthode supprime le contour du masque.


  clipPath.remove(); 

C'est tout pour l'instant. Merci de votre attention!


J'espère que vous comprenez maintenant que commencer à programmer dans Adobe Illustrator n'est pas aussi difficile qu'il y paraît à première vue.


PS Bien sûr, le script résultant est loin d'être idéal. Il ne fonctionne pas avec les masques dont les contours sont représentés par des TextFrame CompoundPath , CompoundShape ou TextFrame . Lisez comment modifier le script pour qu'il devienne un outil à part entière dans la deuxième partie .

Source: https://habr.com/ru/post/fr452586/


All Articles