Un remake de peinture MS à base de pixels à pixel et plus encore ... essayez-le! Rejoignez ensuite le serveur Discord pour partager votre art!
JS Paint recrée tous les outils et menu de la peinture MS, et même des fonctionnalités peu connues, à un degré élevé de fidélité.
Il prend en charge les thèmes, les types de fichiers supplémentaires et les fonctionnalités d'accessibilité comme le mode de regard des yeux et la reconnaissance vocale.
Ah oui, bonne vieille peinture. Pas celui avec les rubans ou le nouveau skeuomorphe avec l'interface qui peut occuper près de la moitié de l'écran. (Et pas la peinture encore plus récente 3d.)
Les Windows 95, 98 et XP ont été les années d'or de peinture. Vous aviez une boîte à outils et une boîte de couleur, une couleur de premier plan et une couleur d'arrière-plan, et c'était tout ce dont vous aviez besoin.
Les choses étaient simples.
Mais nous voulons annuler plus de trois actions. Nous voulons modifier des images transparentes. Nous ne pouvons pas continuer à utiliser l'ancienne peinture.
C'est pourquoi je fais de la peinture JS. Je veux apporter une bonne vieille peinture à l'ère moderne.
Caractéristiques d'édition:
Améliorations diverses:
Quelques choses avec les outils ne sont pas encore terminées. Voir todo.md
La prise en charge complète du presse-papiers dans l'application Web nécessite un navigateur prenant en charge l'API du presse-papiers asynchrones avec des images, à savoir Chrome 76+ au moment de la rédaction.
Dans d'autres navigateurs, vous pouvez toujours copier avec Ctrl + C , coupé avec Ctrl + X et coller avec Ctrl + V , mais les données copiées à partir de la peinture JS ne peuvent être collées que dans d'autres cas de peinture JS. Les images externes peuvent être collées.
Contrairement à MS Paint, vous pouvez utiliser Edit> Annuler pour retourner les couleurs ou la réduction de la qualité de la sauvegarde. Cela n'annule pas l'enregistrement du fichier, mais vous permet ensuite d'économiser dans un format différent avec une qualité supérieure, en utilisant le fichier> Enregistrer sous .
L'économie en tant que PNG est recommandée car elle donne de petites tailles de fichiers tout en conservant une qualité complète.
Extension de fichier | Nom | Lire | Écrire | Palette de lecture | Palette d'écriture |
---|---|---|---|---|---|
.png | PNG | ✅ | ✅ | ||
.bmp, .dib | Bitmap monochrome | ✅ | ✅ | ✅ | |
.bmp, .dib | 16 couleurs bitmap | ✅ | ✅ | ✅ | |
.bmp, .dib | 256 couleurs bitmap | ✅ | ✅ | ✅ | |
.bmp, .dib | Bitmap 24 bits | ✅ | ✅ | N / A | N / A |
.tif, .tiff, .dng, .cr2, .nef | TIFF (charge la première page) | ✅ | ✅ | ||
PDF (charge la première page) | ✅ | ||||
.webp | Webp | ||||
.gif | Gif | ||||
.jpeg, .jpg | Jpeg | N / A | N / A | ||
.svg | SVG (seule taille par défaut) | ||||
.ico | ICO (seule taille par défaut) |
Les capacités marquées sont actuellement laissées au navigateur pour prendre en charge ou non. Si "Write" est marqué, le format apparaîtra dans la liste déroulante du type de fichier mais peut ne pas fonctionner lorsque vous essayez d'enregistrer. Pour l'ouverture des fichiers, consultez la table de support du format d'image du navigateur de Wikipedia pour plus d'informations.
Les capacités marquées peuvent arriver bientôt, et N / A signifie non applicable.
"Read Palette" fait référence au chargement automatiquement des couleurs dans la boîte de couleurs (à partir d'une image de couleur indexée), et "Write Palette" fait référence à l'écriture d'une image couleur indexée.
Avec les couleurs> Enregistrer les couleurs et les couleurs> Obtenez des couleurs, vous pouvez enregistrer et charger des couleurs dans de nombreux formats différents, pour une compatibilité avec une large gamme de programmes.
Si vous souhaitez ajouter un support de palette étendu à une autre application, j'ai rendu cette fonctionnalité disponible en bibliothèque: Anypalette.js
Extension de fichier | Nom | Programmes | Lire | Écrire |
---|---|---|---|---|
.copain | Palette de riff | MS Paint pour Windows 95 et Windows NT 4.0 | ✅ | ✅ |
.gpl | Palette GIMP | GIMP, Inkscape, Krita, Kolourpaint, Scribus, Cinepaint, Mypaint | ✅ | ✅ |
.ACO | Adobe Color Swatch | Adobe Photoshop | ✅ | ✅ |
.ASIQUE | Échange de Swatch Adobe | Adobe Photoshop, InDesign et Illustrator | ✅ | ✅ |
.SMS | Palette de peinture.net | Peinture.net | ✅ | ✅ |
.acte | Table de couleur Adobe | Adobe Photoshop et illustrateur | ✅ | ✅ |
.pal, .psppalette | Palette pro de peinture pro | Paint Shop Pro (JASC Software / Corel) | ✅ | ✅ |
.hpl | Palette de lieux de maison | Allaire Homesite / Macromedia Coldfusion | ✅ | ✅ |
.cs | Coloriage | Studio ColorSchemer | ✅ | |
.copain | Palette Starcraft | Starcraft | ✅ | ✅ |
.wpe | Palette de terrains Starcraft | Starcraft | ✅ | ✅ |
.Sketchpalette | Palette de croquis | Esquisser | ✅ | ✅ |
.spl | Palette de sk crayon | Skicry (anciennement appelé sketch) | ✅ | ✅ |
. | Couleurs étoilées | Staroffice, OpenOffice, LibreOffice | ✅ | ✅ |
.couleurs | Collection de couleurs Kolourpaint | Kolourpaint | ✅ | ✅ |
.couleurs | Palette de couleurs de bureau à plasma | Desktop plasma KDE | ✅ | |
.thème | Thème Windows | Windows Desktop | ✅ | |
.themepack | Thème Windows | Windows Desktop | ✅ | |
.css, .scss, .styl | Feuilles de style en cascade | Navigateurs Web / pages Web | ✅ | ✅ |
.html, .svg, .js | Tous les fichiers texte avec les couleurs CSS | Navigateurs Web / pages Web | ✅ |
Il existe un mode noir et blanc avec des motifs au lieu de couleurs dans la palette, que vous pouvez vous rendre à partir d'images> Attributs ...
Vous pouvez faire glisser la boîte de couleur et la boîte à outils si vous les saisissez au bon endroit. Vous pouvez même les faire glisser dans de petites fenêtres. Vous pouvez remonter les fenêtres sur le côté en double-cliquant sur leurs barres de titre.
En plus de la couleur de premier plan du premier clic gauche et de la couleur d'arrière-plan droit, il y a une troisième couleur à laquelle vous pouvez accéder en tenant Ctrl pendant que vous dessinez. Il commence sans couleur, vous devrez donc tenir Ctrl et sélectionner une couleur en premier. Ce qui est fantaisie à propos de cette machine à sous de couleur, c'est que vous pouvez appuyer et libérer CTRL pour changer de couleurs pendant le dessin .
Vous pouvez appliquer des transformations d'image comme Flip / Rotate, Stretch / Skew ou Invert (dans le menu de l'image) soit à l'image entière ou à une sélection. Essayez de griffonner avec l'outil de sélection de forme libre, puis de faire l'image> Invertir
Ces conseils et astuces d'un tutoriel pour MS Paint fonctionnent également dans JS Paint:
JS Paint peut être installé comme une application Web progressive (PWA), bien qu'elle ne fonctionne pas encore hors ligne. Recherchez l'invite d'installation dans la barre d'adresse.
Fonctionnalités PWA:
Caractéristiques manquantes:
Je l'ai également intégré à une application de bureau avec électron et électron Forge. Vous pouvez le télécharger à partir de la page des versions.
Caractéristiques de l'application électronique:
jspaint path/to/file.png
dans le terminaleditor_window.on("close")
Appeler preventDefault
et peut être une fonctionnalité mais doit afficher / concentrer la fenêtreCloner le repo.
Installez Node.js si vous ne l'avez pas, ouvrez une invite / terminal de commande dans le répertoire du projet.
Exécutez npm run lint
pour vérifier les erreurs d'orthographe, les erreurs de type, les problèmes de style de code et d'autres problèmes.
Exécutez npm run format
pour résoudre automatiquement les problèmes de formatage, ou npx eslint --fix
pour résoudre tous les problèmes auto-fixables.
Les règles de formatage sont configurées pour la compatibilité avec le formateur intégré de VS Code.
Exécutez npm test
pour exécuter des tests basés sur le navigateur avec Cypress. (Il est lent de démarrer et d'exécuter des tests, malheureusement.)
Exécuter npm run accept
pour accepter les modifications visuelles. Cela réduit malheureusement tous les tests, plutôt que d'accepter les résultats du test précédent, vous pouvez donc vous retrouver avec des résultats différents de celle du test précédent. Si vous utilisez GitHub Desktop, vous pouvez afficher des difficultés d'images, dans quatre modes différents.
Pour ouvrir l'interface utilisateur du cyprès, npm run test:start-server
, puis npm run cy:open
simultanément
Les tests sont également effectués en intégration continue avec Travis CI.
Après avoir installé des dépendances avec npm i
, utilisez npm run dev
pour démarrer un serveur de téléchargement en direct.
Assurez-vous que tous les styles importés de mise en page vont dans layout.css
. Lors de la mise à jour de layout.css
, une version droite à gauche de la feuille de style est générée, en utilisant RTLCSS.
Vous devez tester la disposition RTL en changeant la langue en arabe ou en hébreu. Allez dans Extras> Language> العربية ou עברית .
Voir les directives de contrôle pour contrôler la disposition RTL.
Il existe une tâche de lancement de code VS pour s'attacher à Chrome pour le débogage. Voir .vscode/launch.json
pour les instructions d'utilisation.
npm i
npm run electron:start
L'électron-debug est inclus, vous pouvez donc utiliser F5 / Ctrl + R pour recharger et f12 / ctrl + shift + i pour ouvrir les devtools.
Vous pouvez construire pour la production avec npm run electron:make
Il existe une tâche de lancement de code VS pour déboguer le processus principal de l'électron. Pour le processus de rendu, vous pouvez utiliser le chrome de Devtools intégré.
JS Paint peut être déployé à l'aide d'un serveur Web ordinaire.
Rien ne doit être compilé.
Facultativement, vous pouvez configurer un serveur CORS n'importe où, pour charger des images à partir du Web, si vous collez une URL dans JS Paint ou utilisez la fonction #load:<URL>
avec des images qui ne sont pas sur le même domaine.
Par défaut, il utilisera une instance CORS n'importe où configurée pour travailler avec jspaint.app.
Il est hébergé gratuitement sur Heroku, et vous pouvez configurer votre propre instance et le configurer pour travailler avec votre propre domaine.
Vous devrez trouver et remplacer https://jspaint-cors-proxy.herokuapp.com
avec votre propre URL d'instance.
Le support multijoueur s'appuie actuellement sur Firebase, qui n'est pas un logiciel open source.
Vous pouvez créer une instance de base de données Firebase en temps réel et modifier sessions.js
de JS Paint.js pour le pointer, en remplaçant la config
transmise à initializeApp
par la configuration de la console Firebase lorsque vous configurez une application Web.
Mais le mode multijoueur est très de mauvaise qualité jusqu'à présent. Il doit être remplacé par quelque chose d'open source, plus sécurisé, plus efficace et plus robuste.
Ajoutez ceci à votre HTML:
< iframe src =" https://jspaint.app " width =" 100% " height =" 100% " > </ iframe >
Vous pouvez le faire charger une image à partir d'une URL en ajoutant #load:<URL>
à l'URL.
< iframe src =" https://jspaint.app#load:https://jspaint.app/favicon.ico " width =" 100% " height =" 100% " > </ iframe >
Si vous souhaitez contrôler JS Paint, comment il enregistre / charge les fichiers ou accédez directement à la toile, il existe une API instable.
Vous devez d'abord cloner le dépôt, vous pouvez donc pointer un iframe
vers votre copie locale.
La copie locale de JS Paint doit être hébergée sur le même serveur Web que la page contenant, ou plus spécifiquement, il doit partager la même origine.
Avoir une copie locale signifie également que les choses ne se casseront pas à chaque fois que l'API change.
Si JS Paint est cloné dans un dossier appelé jspaint
, qui vit dans le même dossier que la page dans laquelle vous souhaitez l'intégrer, vous pouvez l'utiliser:
< iframe src =" jspaint/index.html " id =" jspaint-iframe " width =" 100% " height =" 100% " > </ iframe >
S'il vit ailleurs, vous devrez peut-être ajouter ../
au début du chemin, pour augmenter un niveau. Par exemple, src="../../apps/jspaint/index.html"
. Vous pouvez également utiliser une URL absolue, comme src="https://example.com/cool-apps/jspaint/index.html"
.
Vous pouvez remplacer les boîtes de dialogue enregistrés et ouvrir des fichiers avec l'API systemHooks
de JS Paint.
< script >
var iframe = document . getElementById ( "jspaint-iframe" ) ;
var jspaint = iframe . contentWindow ;
// Wait for systemHooks object to exist (the iframe needs to load)
waitUntil ( ( ) => jspaint . systemHooks , 500 , ( ) => {
// Hook in
jspaint . systemHooks . showSaveFileDialog = async ( { formats , defaultFileName , defaultPath , defaultFileFormatID , getBlob , savedCallbackUnreliable , dialogTitle } ) => { ... } ;
jspaint . systemHooks . showOpenFileDialog = async ( { formats } ) => { ... } ;
jspaint . systemHooks . writeBlobToHandle = async ( save_file_handle , blob ) => { ... } ;
jspaint . systemHooks . readBlobFromHandle = async ( file_handle ) => { ... } ;
} ) ;
// General function to wait for a condition to be met, checking at regular intervals
function waitUntil ( test , interval , callback ) {
if ( test ( ) ) {
callback ( ) ;
} else {
setTimeout ( waitUntil , interval , test , interval , callback ) ;
}
}
</ script >
Un blob représente le contenu d'un fichier en mémoire.
Une poignée de fichier est tout ce qui peut identifier un fichier. Vous pouvez posséder ce concept et définir comment identifier les fichiers. Il pourrait s'agir d'un index dans un tableau, à un ID de fichier Dropbox, à une URL IPFS, à un chemin de fichier. Cela peut être n'importe quel type, ou peut-être que cela doit être une chaîne, j'oublie.
Une fois que vous avez un concept de poignée de fichiers, vous pouvez implémenter des sélecteurs de fichiers à l'aide des crochets système et des fonctions pour lire et écrire des fichiers.
Commande | Crochets utilisés |
---|---|
Fichier> Enregistrer sous | systemHooks.showSaveFileDialog , puis lorsqu'un fichier est choisi, systemHooks.writeBlobToHandle |
Fichier> Ouvrir | systemHooks.showOpenFileDialog , puis lorsqu'un fichier est choisi, systemHooks.readBlobFromHandle |
Fichier> Enregistrer | systemHooks.writeBlobToHandle (ou identique à Fichier> Enregistrer comme s'il n'y avait pas encore de fichier ouvert) |
Modifier> Copier à | systemHooks.showSaveFileDialog , puis lorsqu'un fichier est choisi, systemHooks.writeBlobToHandle |
Modifier> Coller de | systemHooks.showOpenFileDialog , puis lorsqu'un fichier est choisi, systemHooks.readBlobFromHandle |
Fichier> Définir en papier peint (carrelé) | systemHooks.setWallpaperTiled si défini, else systemHooks.setWallpaperCentered si défini, sinon le fichier> Enregistrer en tant que |
Fichier> Définir en papier peint (centré) | systemHooks.setWallpaperCentered est défini, sinon le même que le fichier> Enregistrer en tant que |
Extras> Rendre l'histoire comme GIF | Identique au fichier> Enregistrer en tant que |
Couleurs> Enregistrer les couleurs | Identique au fichier> Enregistrer en tant que |
Couleurs> Obtenez des couleurs | Identique au fichier> Ouvrir |
Pour démarrer l'application avec un fichier chargé pour l'édition, attendez que l'application se charge, puis appelez systemHooks.readBlobFromHandle
avec une poignée de fichier et dites à l'application de charger ce blob de fichier.
const file_handle = "initial-file-to-load" ;
systemHooks . readBlobFromHandle ( file_handle ) . then ( file => {
if ( file ) {
contentWindow . open_from_file ( file , file_handle ) ;
}
} , ( error ) => {
// Note: in some cases, this handler may not be called, and instead an error message is shown by readBlobFromHandle directly.
contentWindow . show_error_message ( `Failed to open file ${ file_handle } ` , error ) ;
} ) ;
C'est maladroit, et à l'avenir, il peut y avoir un paramètre de chaîne de requête pour charger un fichier initial par sa poignée. (Remarque à soi: il devra attendre que les crochets système soient enregistrés, d'une manière ou d'une autre.)
Il y a déjà un paramètre de chaîne de requête à charger à partir d'une URL:
< iframe src =" https://jspaint.app?load:SOME_URL_HERE " > </ iframe >
Mais cela ne configurera pas la poignée du fichier pour enregistrer.
Vous pouvez définir deux fonctions pour définir le fond d'écran, qui sera utilisé par le fichier> défini comme fond d'écran (carrelé) et fichier> Définir en papier peint (centré) .
systemHooks.setWallpaperTiled
= (canvas) => { ... };
systemHooks.setWallpaperCentered
= (canvas) => { ... };
Si vous définissez uniquement systemHooks.setWallpaperCentered
, JS Paint tentera de deviner les dimensions de votre écran et la carrelage de l'image, en l'appliquant en appelant votre fonction systemHooks.setWallpaperCentered
.
Si vous ne spécifiez pas systemHooks.setWallpaperCentered
, JS Paint sera par défaut pour enregistrer un fichier ( <original file name> wallpaper.png
) à l'aide de systemHooks.showSaveFileDialog
et systemHooks.writeBlobToHandle
.
Voici un exemple complet soutenant un fond d'écran personnalisé persistant comme arrière-plan de la page de contenu:
const wallpaper = document . querySelector ( "body" ) ; // or some other element
jspaint . systemHooks . setWallpaperCentered = ( canvas ) => {
canvas . toBlob ( ( blob ) => {
setDesktopWallpaper ( blob , "no-repeat" , true ) ;
} ) ;
} ;
jspaint . systemHooks . setWallpaperTiled = ( canvas ) => {
canvas . toBlob ( ( blob ) => {
setDesktopWallpaper ( blob , "repeat" , true ) ;
} ) ;
} ;
function setDesktopWallpaper ( file , repeat , saveToLocalStorage ) {
const blob_url = URL . createObjectURL ( file ) ;
wallpaper . style . backgroundImage = `url( ${ blob_url } )` ;
wallpaper . style . backgroundRepeat = repeat ;
wallpaper . style . backgroundPosition = "center" ;
wallpaper . style . backgroundSize = "auto" ;
if ( saveToLocalStorage ) {
const fileReader = new FileReader ( ) ;
fileReader . onload = ( ) => {
localStorage . setItem ( "wallpaper-data-url" , fileReader . result ) ;
localStorage . setItem ( "wallpaper-repeat" , repeat ) ;
} ;
fileReader . onerror = ( ) => {
console . error ( "Error reading file (for setting wallpaper)" , file ) ;
} ;
fileReader . readAsDataURL ( file ) ;
}
}
// Initialize the wallpaper from localStorage, if it exists
try {
const wallpaper_data_url = localStorage . getItem ( "wallpaper-data-url" ) ;
const wallpaper_repeat = localStorage . getItem ( "wallpaper-repeat" ) ;
if ( wallpaper_data_url ) {
fetch ( wallpaper_data_url ) . then ( response => response . blob ( ) ) . then ( file => {
setDesktopWallpaper ( file , wallpaper_repeat , false ) ;
} ) ;
}
} catch ( error ) {
console . error ( error ) ;
}
C'est un peu récursif, désolé; Cela pourrait probablement être fait plus simple. Comme en utilisant simplement les URL de données. (En fait, je pense que je voulais utiliser des URL blob juste pour qu'il ne bloque pas l'inspecteur DOM avec une URL super longue. Ce qui est vraiment un bug de Devtools UX. Peut-être qu'ils ont amélioré cela?)
Vous pouvez charger un fichier qui a les dimensions souhaitées. Il n'y a pas d'API spéciale pour cela en ce moment.
Voir Chargement d'un fichier initialement.
Vous pouvez changer le thème par programme:
var iframe = document . getElementById ( "jspaint-iframe" ) ;
var jspaint = iframe . contentWindow ;
jspaint . set_theme ( "modern.css" ) ;
Mais cela rompra la préférence de l'utilisateur.
Le menu Extras> Thèmes fonctionnera toujours, mais la préférence ne persistera pas lors du rechargement de la page.
À l'avenir, il peut y avoir un paramètre de chaîne de requête pour spécifier le thème par défaut. Vous pouvez également déborder JSPAINT pour modifier le thème par défaut.
Semblable au thème, vous pouvez essayer de changer la langue par programme:
var iframe = document . getElementById ( "jspaint-iframe" ) ;
var jspaint = iframe . contentWindow ;
jspaint . set_language ( "ar" ) ;
Mais cela demandera en fait à l'utilisateur de recharger l'application pour modifier les langues.
Le menu Extras> Language fonctionnera toujours, mais l'utilisateur sera gêné de modifier la langue à chaque fois qu'il recharge la page.
À l'avenir, il peut y avoir un paramètre de chaîne de requête pour spécifier la langue par défaut. Vous pouvez également déborder JSPAINT pour modifier la langue par défaut.
Pas encore pris en charge. Vous pouvez débarquer Jspaint et ajouter vos propres menus.
Avec l'accès à la toile, vous pouvez implémenter un aperçu en direct de votre dessin, par exemple la mise à jour d'une texture dans un moteur de jeu en temps réel.
var iframe = document . getElementById ( "jspaint-iframe" ) ;
// contentDocument here refers to the webpage loaded in the iframe, not the image document loaded in jspaint.
// We're just reaching inside the iframe to get the canvas.
var canvas = iframe . contentDocument . querySelector ( ".main-canvas" ) ;
Il est recommandé de ne pas l'utiliser pour charger un document, car il ne modifiera pas le titre du document, ni ne réinitialise que l'historique d'annulation / refaire, entre autres. Utilisez plutôt open_from_file
.
Si vous voulez faire des boutons ou une autre interface utilisateur pour faire des choses au document, vous devriez (probablement) en faire un inconvénient. C'est très facile, enveloppez simplement votre action dans un appel à undoable
.
var iframe = document . getElementById ( "jspaint-iframe" ) ;
var jspaint = iframe . contentWindow ;
var icon = new Image ( ) ;
icon . src = "some-folder/some-image-15x11-pixels.png" ;
jspaint . undoable ( {
name : "Seam Carve" ,
icon : icon , // optional
} , function ( ) {
// do something to the canvas
} ) ;
systemHooks.showSaveFileDialog({ formats, defaultFileName, defaultPath, defaultFileFormatID, getBlob, savedCallbackUnreliable, dialogTitle })
Définissez cette fonction pour remplacer la boîte de dialogue Enregistrer par défaut. Ceci est utilisé à la fois pour enregistrer les images, ainsi que pour les fichiers de palettes et les animations.
Arguments:
formats
: un tableau d'objets représentant des types de fichiers, avec les propriétés suivantes:formatID
: une chaîne qui identifie uniquement le format (peut être la même que mimeType
)mimeType
(facultatif): type de support désigné du format de fichier, par exemple "image/png"
(les formats de palette n'ont pas cette propriété)name
: le nom du format de fichier, par exemple "WebP"
nameWithExtensions
: le nom du format de fichier suivi d'une liste d'extensions, par exemple "TIFF (*.tif;*.tiff)"
extensions
: un tableau d'extensions de fichiers, à l'exclusion du point, avec l'extension préférée d'abord, par exemple ["bmp", "dib"]
defaultFileName
(facultatif): un nom de fichier suggéré, par exemple "Untitled.png"
ou le nom d'un document ouvert.defaultPath
(Facultatif): une poignée de fichier pour un document qui a été ouvert, vous pouvez donc enregistrer facilement dans le même dossier. Instarmer: ce n'est peut-être pas un chemin, cela dépend de la façon dont vous définissez les poignées de fichiers.defaultFileFormatID
(facultatif): le formatID
d'un format de fichier à sélectionner par défaut.async function getBlob(formatID)
: une fonction que vous appelez pour obtenir un fichier dans l'un des formats pris en charge. Il prend un formatID
et renvoie une Promise
qui se résout avec un Blob
représentant le contenu du fichier à enregistrer.function savedCallbackUnreliable({ newFileName, newFileFormatID, newFileHandle, newBlob })
(facultatif): une fonction que vous appelez lorsque l'utilisateur a enregistré le fichier. Le newBlob
devrait provenir de getBlob(newFileFormatID)
.dialogTitle
(facultatif): un titre pour la boîte de dialogue Enregistrer. Remarquez l'inversion du contrôle ici: JS Paint appelle votre fonction systemHooks.showSaveFileDialog
, puis vous appelez la fonction getBlob
de JS Paint. Une fois que getBlob
a résolu, vous pouvez appeler la fonction savedCallbackUnreliable
qui est définie par JS Paint. (J'espère que je pourrai clarifier cela à l'avenir.)
Notez également que cette fonction est responsable de l'enregistrement du fichier, pas seulement de la sélection d'un emplacement de sauvegarde. Vous pouvez réutiliser votre fonction systemHooks.writeBlobToHandle
si elle est utile.
systemHooks.showOpenFileDialog({ formats })
Définissez cette fonction pour remplacer la boîte de dialogue ouverte par défaut. Ceci est utilisé pour ouvrir des images et des palettes.
Arguments:
formats
: Identique à systemHooks.showSaveFileDialog
Notez que cette fonction est responsable du chargement du contenu du fichier, pas seulement de la sélection d'un fichier. Vous pouvez réutiliser votre fonction systemHooks.readBlobFromHandle
si elle est utile.
systemHooks.writeBlobToHandle(fileHandle, blob)
Définissez cette fonction pour dire à JS Paint comment enregistrer un fichier.
Arguments:
fileHandle
: une poignée de fichier, telle que définie par votre système, représentant le fichier pour écrire.blob
: un Blob
représentant le contenu du fichier à enregistrer.Renvoie:
Promise
-vous qui résout avec true
si le fichier a été définitivement enregistré avec succès, false
si une erreur s'est produite ou que l'utilisateur a annulé, ou undefined
si on ne sait pas si le fichier a été enregistré avec succès, comme c'est le cas avec le téléchargement de fichiers avec <a href="..." download="...">
. La promesse ne doit pas rejeter; Les erreurs doivent être gérées en affichant un message d'erreur et en renvoyant false
. systemHooks.readBlobFromHandle(fileHandle)
Définissez cette fonction pour dire à JS Paint comment charger un fichier.
Arguments:
fileHandle
: une poignée de fichier, telle que définie par votre système, représentant le fichier à lire. systemHooks.setWallpaperTiled(canvas)
Définissez cette fonction pour dire à JS Paint comment régler le papier peint. Voir l'intégration de l'ensemble comme fond d'écran pour un exemple.
Arguments:
canvas
: un HTMLCanvasElement
avec l'image à définir comme fond d'écran. systemHooks.setWallpaperCentered(canvas)
Définissez cette fonction pour dire à JS Paint comment régler le papier peint. Voir l'intégration de l'ensemble comme fond d'écran pour un exemple.
Arguments:
canvas
: un HTMLCanvasElement
avec l'image à définir comme fond d'écran. undoable({ name, icon }, actionFunction)
Utilisez-le pour rendre une action annuelle.
Cette fonction prend un instantané de la toile, puis un autre état, puis appelle la fonction actionFunction
. Il crée une entrée dans l'histoire afin qu'elle puisse être annulée.
Arguments:
name
: un nom pour l'action, par exemple "Brush"
ou "Rotate Image 270°"
icon
(facultatif): une Image
à afficher dans la fenêtre d'histoire. Il est recommandé d'être 15x11 pixels.actionFunction
: une fonction qui ne prend aucun argument et modifie la toile. show_error_message(message, [error])
Utilisez-le pour afficher une boîte de dialogue Message d'erreur, éventuellement avec des détails d'erreur extensibles.
Arguments:
message
: texte brut à afficher dans la boîte de dialogue.error
(facultative): un objet Error
à afficher dans la boîte de dialogue, effondré par défaut dans une section extensible "Détails". open_from_file(blob, source_file_handle)
Utilisez-le pour charger un fichier dans l'application.
Arguments:
blob
: un objet Blob
représentant le fichier à charger.source_file_handle
: une poignée de fichier correspondante pour le fichier, tel que défini par votre système.Désolé pour l'API originale. L'API est nouvelle et certaines parties n'ont pas été conçues du tout. Ce n'était qu'un hack sur lequel je suis venu dépendre, atteignant les internes de JS Paint pour charger un fichier. J'ai décidé de le documenter comme la première version de l'API, car je veux un modificateur lors de la mise à niveau de mon utilisation de toute façon.
set_theme(theme_file_name)
Utilisez-le pour modifier l'application de l'application.
Arguments:
theme_file_name
: le nom du fichier de thème à charger, l'un des:"classic.css"
: le thème Windows98."dark.css"
: le thème sombre."modern.css"
: le thème moderne."winter.css"
: le thème d'hiver festif."occult.css"
: un thème satanique. set_language(language_code)
Vous pouvez en quelque sorte l'utiliser pour modifier la langue de l'application. Mais en fait, il montrera une invite à l'utilisateur pour modifier la langue, car l'application doit recharger pour appliquer le changement. Et si ce dialogue n'est pas dans la bonne langue, eh bien, ils seront probablement confus.
Arguments:
language_code
: le code linguistique à utiliser, par exemple "en"
pour l'anglais, "zh"
pour le chinois traditionnel, "zh-simplified"
pour les chinois simplifiés, etc. L'API changera beaucoup, mais les modifications seront documentées dans le Changelog.
Pas seulement un historique de changements, mais un guide de migration / mise à niveau.
Pour les nouvelles générales du projet, cliquez sur Extras> Project News dans l'application.
JS Paint est un logiciel gratuit et open source, sous licence de licence MIT permissive.