Fermer

juillet 5, 2019

Comment construire un plugin Sketch avec JavaScript, HTML et CSS (Partie 1)


Si vous avez déjà travaillé avec Sketch, il y a de fortes chances que vous ayez pensé à de nombreux moments: «Si seulement Sketch pouvait faire cette chose en particulier, je pourrais accomplir la tâche à accomplir. beaucoup plus rapidement, plus facilement et mieux. »Eh bien, ne vous inquiétez plus! Dans cet article en deux parties, vous apprendrez à créer votre propre plug-in Sketch à partir de zéro – en vous donnant les compétences nécessaires pour résoudre exactement ce type de problèmes.

Ce tutoriel est destiné aux personnes qui connaissent et utilisent le Sketch. app et n'avez pas peur de barboter avec du code. Pour en tirer le meilleur parti, vous devez avoir au moins une expérience de base de l'écriture de JavaScript (et, éventuellement, de HTML / CSS).

Le plug-in que nous allons créer s'appelle «Mosaic». Dans la première partie, nous étudierons les fichiers de base d’un plug-in Sketch. nous allons écrire du code JavaScript et créer une interface utilisateur pour notre plugin à l’aide de HTML et de CSS. Le prochain article expliquera comment connecter l'interface utilisateur au code du plug-in principal, comment implémenter les fonctionnalités principales du plug-in et, à la fin de celui-ci, vous apprendrez également à optimiser le code et le fonctionnement du plug-in. [19659003] Je partagerai également le code du plugin (JS, HTML, CSS) et les fichiers que vous pourrez examiner et utiliser à des fins d'apprentissage.

Que sont les plugins Sketch et comment fonctionnent-ils? [19659006] Dans Sketch, les plugins sont un moyen d’ajouter des fonctionnalités qui ne sont pas présentes dans Sketch «prêtes à l’emploi». Considérant qu’il manquera presque toujours une fonctionnalité ou une intégration manquante dans un programme donné (surtout compte tenu du grand nombre ), on peut commencer à imaginer comment les plugins pourraient être particulièrement utiles et puissants. Les plugins Sketch sont capables de faire à peu près tout ce que vous attendez, comme manipuler la couleur, la forme, la taille, l'ordre, le style, le regroupement et les effets de calques, mais aussi de faire des requêtes comme des requêtes sur des ressources Internet, de présenter un utilisateur

Du côté de la programmation, tous les plugins Sketch sont écrits en code JavaScript. Eh bien, en fait, ce n'est pas tout à fait . Il est plus exact de dire que la plupart les plugins Sketch sont écrits en JavaScript, car il est également possible d'écrire un plugin Sketch dans l'un des langages de programmation d'Apple, Objective-C et Swift. même s'ils requièrent une petite connaissance de JavaScript.

Ne vous inquiétez pas. Dans cet article, nous allons nous concentrer sur la création de plug-ins Sketch à l'aide de JavaScript, HTML et CSS seul . Nous ne reviendrons pas sur les bases du HTML, du CSS ou de JavaScript – cet article suppose au moins des connaissances et de l’expérience dans ces trois domaines. Le site Web des développeurs MDN constitue un excellent endroit pour en savoir plus sur le développement Web .

Commençons!

Tout d'abord, que faisons-nous?

Dans ce tutoriel, je vais vous apprendre comment créer un plug-in de base, adapté aux débutants, capable de créer, dupliquer et modifier des couches, ainsi que de présenter à l'utilisateur une interface utilisateur conviviale. En faisant cela, mon but est d’établir une connaissance fondamentale sur laquelle vous pouvez vous appuyer et l’utiliser pour créer vos propres plugins.

Le plugin que nous allons construire s'appelle Mosaic, et est effectivement un "générateur de motif". Créez des motifs dans les couches, modifiez quelques paramètres et créez un motif:

 Image illustrant l'interface utilisateur du plug-in Mosaic et quelques exemples de motifs.
L'interface utilisateur de Mosaic ainsi que quelques exemples de motifs créés avec. ( Grand aperçu )

Si vous souhaitez installer et jouer avec Mosaic, vous pouvez télécharger le plug-in terminé de GitHub.

Un peu d'histoire: Mosaic s'inspire en grande partie d'un plug-in Adobe Fireworks ancien appelé Twist-and-Fade . Twist-and-Fade est assez puissant, capable de dupliquer un calque autant de fois que nécessaire en ajustant sa teinte, sa position, sa rotation, sa taille et son opacité. Le plugin était même capable de générer des GIF animés, comme celui de où il créait les cadres des deux éléments tournants de la cassette:

 Image montrant une cassette de musique avec tambours rotatifs
Cassette vidéo animée (source ). ( Image agrandie )

(Voici une vidéo mettant en vedette Twist and Fade si vous souhaitez savoir comment cela fonctionne.)

Pour les besoins de ce tutoriel, nous allons construire un plugin similaire pour Sketch, bien que volontairement simplifié afin de garder le tutoriel aussi accessible que possible. Plus précisément, notre plugin sera capable de:

  • dupliquer tout calque Sketch (bitmap ou vectoriel) et modifier la position, la rotation et l’opacité du calque des doublons. Cela nous donnera une introduction à la manipulation des couches à l'aide des API JavaScript de Sketch .
  • Affiche une interface utilisateur créée à l'aide de HTML, CSS et JS, qui vous apprendra comment créer facilement une interface pour le plugin. , en utilisant des technologies Web que vous connaissez peut-être déjà. L’interface du plug-in est très importante car c’est ainsi que nous allons rassembler les entrées de l’utilisateur concernant la manière dont il souhaite obtenir l’image mosaïque obtenue.

Création de notre plug-in de base en dix secondes à plat

Nous allons tout d'abord créer le “Base” (ou template) pour le plugin que nous voulons construire. Nous pourrions créer manuellement tous les fichiers et dossiers nécessaires pour constituer un plug-in, mais heureusement, ce n’est pas nécessaire, car Sketch peut le faire pour nous. Après avoir généré le plugin de modèle, nous pourrons le personnaliser comme bon nous semble.

Il existe une technique très simple et rapide que nous pouvons utiliser pour créer le plugin de modèle, ce qui est plutôt ma méthode préférée. quand j'ai besoin de combiner un plugin pour résoudre le problème auquel je suis confronté à un moment donné. Voici comment cela fonctionne:

Lorsque Sketch est ouvert, vérifiez la barre de menus en haut de l’écran et cliquez sur Plugins -> Run Script . Cela ouvrira une boîte de dialogue que nous pourrons utiliser pour tester et exécuter le code. Nous pouvons également enregistrer le code que nous entrons sous forme de plug-in, la partie qui nous intéresse plus particulièrement en ce moment.

Effacez le code déjà présent dans cette boîte de dialogue et remplacez-le par le code de démonstration suivant:

. const UI = require ("sketch / ui");

UI.message ("? Salut, fantastique développeur de plugins! C'est votre plugin! Vous parle depuis l'écran de l'ordinateur numérique! Dans Sketch! Tout simplement génial!");

Ensuite, appuyez sur Enregistrer le script en tant que plug-in dans le coin inférieur gauche de la fenêtre, entrez le nom de votre choix pour ce plug-in (dans notre cas, il s'agit de “Mosaic”), puis Enregistrer le script sous forme de plug-in une fois de plus.

Appuyez sur «Enregistrer» en bas à gauche de la fenêtre et entrez le nom de votre choix pour ce plug-in. ( Grand aperçu )

Croyez-le ou non, nous avons déjà terminé – il ne reste plus qu'à manger le gâteau que nous venons de faire cuire. Voici la partie amusante. En ouvrant le menu Plugins une fois de plus, vous devriez voir quelque chose comme ceci: votre plugin flambant neuf classé comme "Mosaic"! Cliquez dessus!

( Grand aperçu )

Félicitations, vous venez d'écrire votre premier plug-in Sketch!

Ce que vous devriez voir après avoir cliqué sur «Mosaïque» devrait ressembler à la courte vidéo ci-dessus, avec un message d’infobulle discret apparaissant au bas de l’écran et commençant par les mots «Hey there…» – c’est exactement ce que le code que nous avons collé lui dit de faire. C'est ce qui rend cette technique si géniale: il est facile à coller, modifier et tester du code sans avoir à construire un plugin à partir de zéro. Si vous connaissez déjà la console Web de votre navigateur ou si vous avez déjà joué à cette console, c’est essentiellement cela. Avoir cet outil dans votre poche arrière lorsque vous créez et testez du code est un must-have.

Faisons un rapide récapitulatif de ce que le code que vous avez ajouté fait:

Tout d'abord, il importe le croquis / ui [19659038] module de la bibliothèque JS intégrée de Sketch et l'assigne à la variable UI . Ce module contient quelques méthodes utiles liées à l’interface, dont nous utiliserons:

 const UI = require ("sketch / ui");

Ensuite, il appelle la méthode de message (qui fait partie du module sketch / ui ) avec la chaîne de texte que nous voulons voir affichée dans l'info-bulle que nous avons vue:

 UI.message ("? Salut, fantastique développeur de plugins! C'est votre plugin! Vous parle depuis l'écran de l'ordinateur numérique! Dans Sketch! Tout simplement génial!");

La méthode message () constitue un excellent moyen de présenter un message discret à l'utilisateur. c’est idéal dans les cas où vous n’avez pas besoin de voler le focus (non modal) et n’avez pas besoin de boutons ni de champs de texte sophistiqués. Il y a aussi d'autres façons de présenter des éléments d'interface utilisateur communs comme des alertes, des invites, etc. (19459051), dont nous utiliserons certains lors de la construction de Mosaic.

Personnalisation des métadonnées de notre plugin

plugin de base pour commencer, mais nous avons encore besoin de le peaufiner et de le rendre vraiment le nôtre. Notre prochaine étape sera de changer les métadonnées du plugin.

Pour cette étape, nous devrons jeter un coup d’œil à ce que l’on appelle le plugin bundle . Lorsque vous cliquez sur Enregistrer dans la fenêtre "Exécuter le script", Sketch enregistre votre plug-in dans un dossier nommé Mosaic.sketchplugin .
Répertoire ~ / Bibliothèque / Application Support / com.bohemiancoding.sketch3 / Plugins . C’est un peu long et ennuyant à retenir; En tant que raccourci, vous pouvez également le télécharger via Plugins -> Gérer les plugins -> (clic droit sur votre plugin) -> Reveal Plugins Folder . Même s’il apparaît dans le Finder sous forme de fichier unique, il s’agit en fait d’un dossier contenant tout ce dont notre plug-in a besoin pour que Sketch l’exécute. La raison pour laquelle il apparaît sous la forme d’un fichier unique alors que est un dossier, c’est que, lorsque vous avez installé Sketch pour la première fois, Sketch a enregistré l’extension .sketchplugin en tant que "paquet" (type spécial de dossier apparaît sous forme de fichier) et lui a demandé de s’ouvrir automatiquement dans Sketch lorsqu’il est ouvert.

Jetons un coup d’œil à l’intérieur. Cliquez avec le bouton droit de la souris sur Mosaic.sketchplugin puis cliquez sur «Afficher le contenu du paquet». A l'intérieur, vous devriez voir la structure de répertoire suivante:

 Sommaire /
Ressources /
└ Croquis /
  └ manifest.json
  └ script.cocoascript

Vous vous demandez peut-être pourquoi il existe un fichier portant l’extension .cocoascript . Ne vous inquiétez pas, c’est juste un fichier JavaScript classique, et ne contient que le code que nous avons entré précédemment. Allez-y et renommez ce fichier en index.js ce qui modifiera la structure des répertoires pour qu'elle ressemble à celle ci-dessous:

 Sommaire /
Ressources /
└ Croquis /
  └ manifest.json
  └ index.js

La manière la plus courante d'organiser les fichiers à l'intérieur d'un ensemble de plug-ins est la suivante: votre code (JavaScript) et manifest.json appartiennent à Sketch / et à des ressources (pensez images). , fichiers audio, fichiers texte, etc.) appartiennent à Ressources / .

Commençons par peaufiner le fichier nommé manifest.json . Ouvrez-le dans votre éditeur de code préféré, tel que Visual Studio Code ou Atom .

Vous constaterez qu’à l’heure actuelle, il y a relativement peu de contenu à l’intérieur, mais nous ajouterons plus à venir. Le manifeste de plug-in sert principalement à deux fins:

  1. Tout d'abord, il fournit des métadonnées décrivant le plug-in à l'utilisateur - des éléments tels que son nom, sa version, le nom de l'auteur, etc. Sketch utilise ces informations dans la boîte de dialogue Sketch -> Préférences -> Plug-ins pour créer une liste et une description de votre plug-in.
  2. Deuxièmement, il indique également à Sketch comment entrer en contact avec votre entreprise; c'est-à-dire qu'il indique à Sketch comment vous souhaitez que le menu de votre plug-in apparaisse, quelles touches de raccourci attribuer à votre plug-in et où réside le code de votre plug-in (pour que Sketch puisse l'exécuter). vous remarquerez probablement qu’à l’heure actuelle, aucune description ou n’a été donnée, ce qui serait source de confusion pour l’utilisateur et rendrait le plug-in difficile à identifier. Corrigeons cela en ajustant les valeurs des clés appropriées à:

     {
            "description": "Générez de superbes dessins et des motifs répétés à partir de vos calques!",
            "author": "=> Votre nom ici 

    Modifions ensuite l'identifiant du plug-in. Cet identifiant utilise ce que l'on appelle une" notation de domaine inversé ", qui est un moyen très concis (ou ennuyeux, à vous de choisir)" prenez le domaine de votre site, inversez l'ordre, puis mettez le nom de votre produit à la fin. »Cela donnera un résultat du genre: com.votre-entreprise-ou-votre-nom-ou-votre-nom-ce-n'est-pas-ce-grand-a -deal.votre produit .

    Vous n'êtes pas obligé de vous en tenir à cette convention de nommage - vous pouvez mettre ce que vous voulez ici, à condition qu'il soit assez unique pour éviter les conflits avec d'autres plugins (bien que ce soit probablement C'est une bonne idée de s'en tenir au format RDN, d'autant plus qu'il fournit un système simple et réutilisable pour vos identifiants de plug-in.)

    Pour ce faire, remplacez votre identifiant par com.votre-nom.mosaic :

     {
        "identifiant": "com.votre-nom.mosaique"
    }
    

    Personnellement, j'aime bien prendre toutes les clés liées aux métadonnées (titre, auteur, identifiant, etc.) et les regrouper en haut du manifeste pour qu'elles ne soient pas dispersées et ne me dissipent pas et me permettent de préserver ma santé mentale quand j'ai besoin de moi. pour les trouver.

    Ensuite, examinons les touches de menu et . Ces deux personnes sont responsables de dire à Sketch quel code appeler et en réponse à quoi.

    Si vous regardez la touche du menu vous verrez qu’elle contient une clé title La valeur correspondant au nom de notre plugin apparaîtra dans le menu Plugins . Il possède également une clé items qui est une liste d'identificateurs de commande :

     {
      "menu": {
        "titre": "Mosaïque",
        "articles": [
            "com.bohemiancoding.sketch.runscriptidentifier"
        ]
      }
    }
    

    À l’heure actuelle, un seul identificateur de commande figure dans cette liste, "com.bohemiancoding.sketch.runscriptidentifier" . Les identificateurs de commande pointent toujours vers une commande de la liste de commandes . Actuellement, notre plugin n'a qu'une seule commande, celle avec cet identifiant:

     {
      "commandes": [
        {
          "script" : "script.cocoascript",
          "name" : "Mosaic",
          "handlers" : {
                  "run" : "onRun"
          },
          "identifier" : "com.bohemiancoding.sketch.runscriptidentifier"
        }
      ]
    }
    

    Chaque fois que vous ajoutez un identifiant de commande à une entrée du menu Sketch recherchera l'entrée de commande portant cet identifiant et affichera la valeur de sa clé nommée (qui case est “Mosaic”) et le montrera dans le menu de votre plugin à la place de l'identifiant.

    En ce qui concerne les commandes de rôle, nous pouvons penser à une entrée de commande comme un moyen d'indiquer à Sketch quelle fonction est utilisée dans le code JavaScript de notre plugin. vouloir exécuter lorsque cette commande est appelée, l’invocation étant généralement le clic de l’utilisateur sur l’élément de menu associé. L'entrée de commande ne fait rien par elle-même, c'est juste JSON - elle fournit simplement une description à Esquisse indiquant où rechercher le code JavaScript dont il a besoin pour s'exécuter lorsque la commande est invoquée. Jusqu'ici, nous avons parlé de ce que les clés nom et identificateur identifient, mais il y a deux autres clés dans une commande qui doivent être adressées: script et gestionnaires .

    La clé de script indique à Sketch où se trouve le fichier JavaScript à exécuter. Notez que Sketch suppose que le fichier de script en question se trouve dans le dossier Sketch / . C’est pourquoi, pour simplifier, vous voulez vous assurer que tout votre code JavaScript se trouve quelque part sous le Sketch / [ dossier. Avant de passer de cette clé il est important de vous assurer de modifier la valeur de cette clé en index.js comme nous l'avions précédemment renommé. Sketch ne pourra sinon pas trouver et exécuter votre fichier JavaScript.

    La valeur de la clé handlers est ce que Sketch examine pour déterminer la fonction à appeler dans votre JavaScript. Ici, nous avons seulement un ensemble de gestionnaires: run avec la valeur onRun . run est le nom d'une action Sketch intégrée prédéfinie . Cette action run sera toujours appelée lorsqu'un utilisateur cliquera sur un élément de menu faisant référence à cette commande. onRun est le nom d'une fonction du fichier script.cocoascript généré automatiquement, que nous avons renommé en index.js ). et la fonction que nous voulons appeler lorsque l'événement run se produit, c'est-à-dire lorsque l'utilisateur clique sur l'élément de menu.

    Dans l'exemple que nous avons jusqu'ici, ce processus se déroule de la manière suivante: [19659053] L'utilisateur clique sur notre élément de menu.

  3. Sketch trouve la commande associée à cet élément de menu.
  4. Sketch trouve le fichier de script auquel la commande fait référence et l'exécute (ce qui signifie qu'il exécute le code JavaScript dans index.js ).
  5. Cette commande étant invoquée par un clic dans un élément de menu, elle est considérée comme une action exécutée . Cela signifie que Sketch examinera la valeur de la commande handlers.run pour la fonction à appeler ensuite, qui dans ce cas est onRun .
  6. Sketch appelle le onRun . ] La fonction.

Les commandes sont généralement appelées en réponse à un utilisateur qui clique sur l’un de vos éléments de menu, mais elles peuvent également être appelées en réponse à d’autres actions de l’utilisateur, telles que le changement de sélection ou la propriété d’un calque. . Cependant, pour ce plugin, nous n’utiliserons aucune de ces actions. (Pour en savoir plus sur les actions et leur fonctionnement, reportez-vous à la page d’aide Action API .)

Avant de passer de ce manifeste, nous voudrons faire deux autres ajustements. Actuellement, notre menu a la structure suivante:

 Mosaic
└ Mosaïque
 Image illustrant un élément de menu Mosaic imbriqué de manière redondante dans un autre menu nommé Mosaic
Joliment redondant, n'est-ce pas? ( Grand aperçu )

… ce qui est un peu redondant car notre plugin n'a qu'un seul élément de menu. Cela ajoute également un peu de friction inutile pour notre utilisateur car notre plugin nécessite maintenant deux clics pour en appeler plutôt qu'un. Nous pouvons résoudre ce problème en ajoutant à isRoot: true à notre menu :

 {
  "menu": {
    "titre": "Mosaïque",
    "articles": [
            "com.bohemiancoding.sketch.runscriptidentifier"
    ],
    "isRoot": true
}
}

Ceci indique à Sketch de placer le premier niveau d'éléments de menu directement sous le menu Plugins plutôt que de les imbriquer sous le titre du menu .

Cliquez sur enregistrer et revenir à Sketch. . Vous devriez voir que maintenant Mosaic -> Mosaic a été remplacé par Mosaic – parfait!

 Image montrant l’interface utilisateur du plug-in Mosaic
l’interface utilisateur de Mosaic. ( Grand aperçu )

En ce qui concerne notre deuxième modification, allons de l'avant et renommez cet identificateur de commande en quelque chose de moins maniable. Etant donné que les identificateurs de commande doivent uniquement être uniques dans le contexte d'un plug-in individuel, nous pouvons le renommer en quelque chose de plus concis et plus évident, comme "open" :

 {
  "commandes": [
    {
            ...
            "identifier" : "open"
    }
],

"menu": {
    ...
    "articles": [
            "open"
    ]
  }
}

Avant de poursuivre, il est utile de noter que les menus peuvent également contenir d’autres menus. Vous pouvez facilement créer un sous-menu en imbriquant une autre {titre: ..., éléments: ...} dans la liste des éléments du menu :

 {
  "menu": {
    "titre": "Mosaïque",
    "articles": [
      "open",
      {
        "title" : "I'm a sub-menu!",
        "items" : [
                "another-command-identifier"
        ]
      }
    ]
  }
}

Création de l'interface utilisateur du plug-in

Jusqu'à présent, nous avons écrit du code de démonstration et personnalisé le manifeste de notre plug-in. Nous allons maintenant passer à la création de son interface utilisateur, qui est essentiellement une page Web intégrée dans une fenêtre (de la même manière que les navigateurs que vous connaissez bien):

: la fenêtre du plugin. ( Grand aperçu )
 Image montrant les composants constituant l’interface de notre plugin: fenêtre et vue Web
Les composants constituant notre plugin. ( Grand aperçu )

La fenêtre

La conception de l’interface utilisateur de Mosaic a sa propre fenêtre, que nous pouvons considérer comme le composant le plus fondamental; nous allons commencer avec ça. Pour créer et afficher une fenêtre, nous devrons utiliser une classe intégrée par défaut à macOS, appelée NSWindow . Au cours de la suite de ce didacticiel, nous allons faire cela assez souvent (en utilisant des API intégrées telles que NSWindow ), ce qui peut sembler un peu intimidant si vous ne le connaissez pas, mais ne le faites pas. inquiétude – je vais tout expliquer en cours de route!

Note: Bien que nous parlions des API intégrées, la raison pour laquelle nous avons pu utiliser cette classe ] est grâce à un pont présent dans le runtime JavaScript utilisé par les plugins Sketch. Ce pont importe automatiquement ces classes, méthodes et fonctions intégrées qui ne seraient normalement disponibles que pour les applications natives.

Ouvrez Sketch / index.js dans votre éditeur de code, supprimez ce qui existe déjà, et coller dans les éléments suivants:

 function onRun (context) {
  const window = NSWindow.alloc (). initWithContentRect_styleMask_backing_defer_ (
    NSMakeRect (0, 0, 145, 500),
    NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
    NSBackingStoreBuffered,
    faux
  )

  window.releasedWhenClosed = false;

  window.makeKeyAndOrderFront (nil);
};

Voyons ce que fait ce premier bit de code:

 function onRun (context) {

Vous vous souvenez plus tôt lorsque nous avons parlé des commandes et de leur fonctionnement, et que nous avons dit à Sketch d'appeler en réponse à un clic sur un menu appelé onRun ? (Si vous avez besoin d'un rappel, revenez à la partie ci-dessus, puis revenez.) Tout ce que fait ce bit, c'est créer cette fonction. Vous remarquerez également que notre fonction onRun prend un argument relatif au contexte . C’est un argument que Sketch appellera vos gestionnaires de commandes et qui pourront nous fournir certaines informations. Nous l’utiliserons plus tard pour obtenir l’URL de notre ensemble de plug-ins sur l’ordinateur de l’utilisateur.

 const window = NSWindow.alloc (). InitWithContentRect_styleMask_backing_defer (
  NSMakeRect (0, 0, 145, 500),
  NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
  NSBackingStoreBuffered,
  faux
)

En fait, nous faisons quelques choses:

  1. Premièrement, nous appelons alloc () sur NSWindow ; cela signifie fondamentalement “mettre de côté de la mémoire pour une instance de NSWindow”. Il suffit de savoir que vous devrez le faire pour à chaque instance d’une classe autochtone que vous souhaitez créer. La méthode alloc est disponible dans toutes les classes autochtones.
  2. Ensuite, nous appelons la méthode initializer de NSWindow (c'est-à-dire la méthode qui crée réellement une instance de NSWindow ), nommée initWithContentRect: styleMask: sauvegarde: différée: . Vous remarquerez que cela diffère de ce que nous appelons dans notre code ci-dessus – il y a un tas de deux points (: ) entre chaque argument. Comme nous ne pouvons pas utiliser cette syntaxe en JavaScript, Sketch la renomme en quelque chose que nous pouvons utiliser en remplaçant les deux-points par des traits de soulignement, ce qui explique le nom JS initWithContentRect_styleMask_backing_defer .
  3. Ensuite, nous passons dans chacun des arguments nécessaires à la méthode. Pour le premier argument, contentRect nous fournissons un rectangle de taille suffisante pour notre interface utilisateur.
  4. Pour styleMask nous utilisons un masque de bits qui dit que nous voulons que notre fenêtre ait un bouton de fermeture, une barre de titre et qu'elle soit redimensionnable.
  5. Les deux arguments suivants, supports et différés sont toujours . va être réglé sur NSBackingStoreBuffered et false nous n'avons donc pas vraiment besoin de nous en inquiéter. (La documentation de cette méthode explique plus en détail pourquoi.)
 window.releasedWhenClosed = false;

window.makeKeyAndOrderFront (null);

Nous définissons ici NSWindow ’s libéréWhenClosed propriété sur false ce qui signifie:“ Hé! ne supprimez pas cette fenêtre de la mémoire simplement parce que l'utilisateur la ferme. ”Ensuite, nous appelons makeKeyAndOrderFront (null) ce qui signifie:“ Déplacez cette fenêtre à l'avant-plan et donnez-lui le clavier focus. ”

Web View: L'interface

Pour faciliter les choses, j'ai déjà écrit les codes HTML et CSS de l'interface utilisateur Web du plug-in que nous allons utiliser. le seul code restant que nous devrons ajouter à cela consistera à nous assurer que nous pourrons communiquer entre nous et le code de notre plugin Sketch.

Ensuite, téléchargez le code HTML et CSS . . Une fois que vous l'avez téléchargé, extrayez-le, puis déplacez le dossier nommé "web-ui" dans le dossier Resources de notre plugin.

Note : L'écriture et l'optimisation du code HTML / CSS actuel est en dehors du cadre de ce didacticiel, car il est centré sur JavaScript, qui alimente les principales fonctionnalités du plugin; mais il y a une tonne de tutoriels sur le web sur ce sujet, si vous voulez en savoir plus.

Si vous exécutez notre plugin maintenant, vous verrez qu'il montre une fenêtre – oui progrès! Mais c’est vide, sans titre, et pas encore très utile. Nous devons l'obtenir pour afficher notre interface Web. Pour ce faire, nous devrons utiliser une autre classe native, WKWebView qui est une vue spécialement conçue pour afficher du contenu Web.

Nous ajouterons le code nécessaire à la création de notre . ] WKWebView sous le code que nous avons écrit pour notre fenêtre:

 function onRun (context) {
    // Créer une fenêtre

    const window = NSWindow.alloc (). initWithContentRect_styleMask_backing_defer (
            NSMakeRect (0, 0, 145, 500),
            NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
            NSBackingStoreBuffered,
            faux
    )

    window.releasedWhenClosed = false;

    // Créer une vue Web et la définir comme vue pour notre fenêtre à afficher

    const webView = WKWebView.alloc (). init ();

    window.contentView = webView;

    // Charger notre interface utilisateur dans la vue Web

    const webUIFolderURL = context.scriptURL
            .URLByDeletingLastPathComponent ()
            .URLByAppendingPathComponent ("../ Resources / web-ui /");

    const indexURL = webUIFolderURL.URLByAppendingPathComponent ("index.html");

    webView.loadFileURL_allowingReadAccessToURL (indexURL, webUIFolderURL);

    // Crée la clé de la fenêtre et passe au premier plan

    window.makeKeyAndOrderFront (nil);
};

Si nous exécutons notre plugin maintenant, nous verrons que nous avons maintenant une fenêtre ouverte qui affiche notre interface utilisateur Web.

Encore une fois, avant de poursuivre, examinons ce que le code ajouté ajoute:

 const webView = WKWebView.alloc (). Init ();

Cela devrait vous sembler familier – c’est fondamentalement la même chose que lorsque nous avions créé notre NSWindow : allouer de la mémoire pour une vue Web, puis l’initialiser.

 window.contentView = webView;

Cette ligne de code indique à notre fenêtre d'afficher la vue Web que nous venons de créer.

 const webUIFolderURL = context.scriptURL
  .URLByDeletingLastPathComponent ()
  .URLByAppendingPathComponent ("../ Resources / web-ui /");

Notre objectif est de créer une URL pointant vers le dossier web-ui que nous avons créé précédemment. Afin d’obtenir cette URL, nous avons besoin d’un moyen de déterminer où se trouve le paquet de notre plugin dans le système de fichiers de l’utilisateur. Nous utilisons ici la propriété context.scriptURL qui nous donne l'URL du script en cours d'exécution . Cependant, cela ne nous donne pas un JavaScript String comme on pourrait s'y attendre, mais une instance d'une classe native, NSURL qui comporte quelques méthodes permettant de manipuler des chaînes d'URL

Nous devons transformer ce que context.scriptURL nous donne –

 fichier: //path-to-your-plugin/Contents/Sketch/index.js

– dans:

 fichier: // chemin d'accès à votre plugin / Contenu / Ressources / web-ui /

Pas à pas:

  1. Appeler URLByDeletingLastPathComponent () nous donne la première fois Fichier: // chemin d'accès à votre plugin / Contenu / Esquisse /
  2. L'appel de URLByDeletingLastPathComponent () nous donne à nouveau fichier: // chemin d'accès à votre plugin / Sommaire /
  3. Et enfin, ajout de Resources / web-ui / [ à la fin en utilisant URLByAppendingPathComponent ("Ressources / web-ui /") nous donne le fichier: // chemin-à-votre-plugin / Contenu / Ressources / web-ui /

Nous devons également créer une deuxième URL pointant directement sur le fichier index.html :

 const indexURL = webUIFolderURL.URLByAppendingPathComponent ("index.html"). ;

Enfin, nous demandons à notre vue Web de charger index.html et de lui donner accès au contenu du dossier web-ui :

 webView.loadFileURL_allowingReadAccessToURL (indexURL, webUIFolderURL);

Très bien. Jusqu'à présent, nous avons une fenêtre qui affiche notre interface utilisateur Web, exactement comme nous le souhaitions. Cependant, ce n’est pas encore tout à fait terminé – notre conception originale ne comporte pas de barre de titre (ou « chrome »), mais notre fenêtre actuelle en contient. Il y a aussi le fait que lorsque nous cliquons à l'intérieur d'un document Sketch, ce document se déplace devant notre fenêtre, ce qui n'est pas ce que nous souhaitons. Nous voulons que l'utilisateur puisse interagir avec la fenêtre du plugin et . le document Sketch sans devoir constamment se recentrer d’une fenêtre à l’autre.

Pour résoudre ce problème, nous devons d’abord éliminer le chrome par défaut de la fenêtre et ne conserver que les boutons. Adding the two lines of code below will get rid of the title bar.

Note: Like before, all of the properties and methods we’re using below are documented in NSWindow’s documentation page.

window.titlebarAppearsTransparent = true;
window.titleVisibility = NSWindowTitleHidden;

These next two lines of code will remove the window buttons (also known as “traffic lights” in MacOS lingo) that we don’t need — “zoom” and “minimize” — leaving only the “close” button:

window.standardWindowButton(NSWindowZoomButton).hidden = true;
window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true;

While we’re at it, let’s also go ahead and change the window’s background color to match that of our web UI:

window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1);

Next, we need to do something to keep our floating plugin window on top of other windows, so the user can interact with their Sketch documents without having to worry about the Mosaic’s window disappearing. We can use a special type of NSWindow for this, called NSPanelwhich is able to “stay on top” of other windows. All that’s needed for this is to change NSWindow to NSPanelwhich is a single-line code change:

const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(

Now we tell our panel window to float (stay on top of all others), and only take keyboard/mouse focus when necessary:

window.floatingPanel = true;
window.becomesKeyOnlyIfNeeded = true;

We can also tweak our window so that it automatically reopens in the last position it was at:

window.frameAutosaveName = "mosaic-panel-frame";

This line basically says “remember this window’s position by saving it with Sketch’s preferences under the key mosaic-panel-frame”.

All together, we now have the following code:

function onRun(context){
    //        Create window

    const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(
            NSMakeRect(0, 0, 145, 500),
            NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
            NSBackingStoreBuffered,
            faux
    )

    window.becomesKeyOnlyIfNeeded = true;
    window.floatingPanel = true;

    window.frameAutosaveName = "mosaic-panel-frame";

    window.releasedWhenClosed = false;

    window.standardWindowButton(NSWindowZoomButton).hidden = true;
    window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true;

    window.titlebarAppearsTransparent = true;
    window.titleVisibility = NSWindowTitleHidden;

    window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1);

    //        Create web view, and set it as the view for our window to display

    const webView = WKWebView.alloc().init();

    window.contentView = webView;

    //        Load our UI into the webview

    const webUIFolderURL = context.scriptURL
            .URLByDeletingLastPathComponent()
            .URLByAppendingPathComponent("../Resources/web-ui/");

    const indexURL = webUIFolderURL.URLByAppendingPathComponent("index.html");

    webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL);

    //        Make window key and move to front

    window.makeKeyAndOrderFront(nil);
};

Organizing The Code

Before we move to the next part, it’s a good idea to organize our code so that it’s easier to navigate and tweak. Since we still have a lot more code to add and we want to avoid index.js becoming a messy dumping ground for all of our code, let’s split things up a bit and move our UI-specific code into a file named ui.jsunder the Sketch folder. We’ll also extract some of the UI tasks we do, like creating the web view and window, into their own functions.

Create a new file called ui.js and insert the code below inside it:

//        Private

var _window;

function createWebView(pageURL){
        const webView = WKWebView.alloc().init();

        webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent());

        return webView;
};

function createWindow(){
        const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(
                NSMakeRect(0, 0, 420, 646),
                NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
                NSBackingStoreBuffered,
                faux
        )

        window.becomesKeyOnlyIfNeeded = true;
        window.floatingPanel = true;

        window.frameAutosaveName = "mosaic-panel-frame";

        window.releasedWhenClosed = false;

        window.standardWindowButton(NSWindowZoomButton).hidden = true;
        window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true;

        window.titlebarAppearsTransparent = true;
        window.titleVisibility = NSWindowTitleHidden;
        
        window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1);

        return window;
};

function showWindow(window){
        window.makeKeyAndOrderFront(nil);
};

//        Public

function loadAndShow(baseURL){
        if(_window){
                showWindow(_window);

                return;
        }

        const pageURL = baseURL
                .URLByDeletingLastPathComponent()
                .URLByAppendingPathComponent("../Resources/web-ui/index.html");

        const window = createWindow();
        const webView = createWebView(pageURL);

        window.contentView = webView;
        
        showWindow(_window);

        _window = window;
};

function cleanup(){
        if(_window){
                _window.orderOut(nil);
                _window = null;
        }
};

//        Export

module.exports = { loadAndShow, cleanup };

There are a couple of key changes we made here that are important to note. Besides the fact that we’ve created specific functions for the creation, hiding and showing of our window and its web view, we’ve also modularized our user interface code.

Notice the module.exports = { loadAndShow, cleanup } line at the bottom? This is a way for us to specify exactly what objects and functions scripts who import this UI code can use (and hiding those we don’t want to them to worry about), which means we now have a more organized API for interacting with, showing and destroying our UI.

Recommended reading: Unleashing The Full Potential Of Symbols In Sketch

Let’s see what this looks like in practice. Back in index.jsremove the old code and add the following:

const UI = require("./ui");

function onRun(context){
        UI.loadAndShow(context.scriptURL);
};

We’re using a special function that Sketch automatically makes available to us, requireto import our ui.js code and assign the returned module to the UI variable. This gives us access to a simplified API for triggering our user interface. Things are much tidier now and easy to find!

Conclusion

Well done — you’ve come far! In the next part of this tutorial, we’ll give our web UI the ability to send us a message when the “Apply” button is clicked, and we’ll focus on the main plugin functionality: actually generating layer mosaics!

Smashing Editorial(mb, yk, il)




Source link