### Install Painterro with npm Source: https://github.com/devforth/painterro/blob/master/README.md Install Painterro using npm in a JavaScript project. ```bash npm install painterro --save ``` -------------------------------- ### Start hot-reload dev server Source: https://github.com/devforth/painterro/blob/master/README.md Run this command to start the hot-reload development server for Painterro. After starting, open http://localhost:3000 to view the demo page. ```bash npm run dev ``` -------------------------------- ### Install Painterro dependencies Source: https://github.com/devforth/painterro/blob/master/README.md Installs Node modules after cloning the repository. All build configurations are included in the repo. ```bash cd painterro npm ci ``` -------------------------------- ### Install Node.js 16 with nvm Source: https://github.com/devforth/painterro/blob/master/README.md Commands to install and use Node.js version 16, which is the latest supported version for Painterro development. ```bash nvm install 16 nvm use 16 ``` -------------------------------- ### Watch build for Painterro source Source: https://github.com/devforth/painterro/blob/master/README.md Run this command in the Painterro source folder to start a watch build, which automatically rebuilds the library when you make changes. ```bash watch npm run build ``` -------------------------------- ### Install eslint-plugin-import Source: https://github.com/devforth/painterro/blob/master/README.md Install the eslint-plugin-import package, required when your side app uses ESLint and you want to edit Painterro source from a webpack app. ```bash npm i eslint-plugin-import ``` -------------------------------- ### Painterro colorScheme configuration example Source: https://github.com/devforth/painterro/blob/master/README.md Configures Painterro UI colors by passing a colorScheme object to the Painterro constructor. The example sets the main panel color to light-yellow and control color to a custom orange. ```javascript Painterro({ colorScheme: { main: '#fdf6b8', // make panels light-yellow control: '#FECF67' // change controls color } }).show() ``` -------------------------------- ### Set language for Painterro Source: https://github.com/devforth/painterro/blob/master/README.md Pass a language parameter to set the UI language. Example uses Spanish ('es'). ```javascript Painterro({ language: 'es' // Spanish }).show() ``` -------------------------------- ### Scale to fill width and height Source: https://github.com/devforth/painterro/blob/master/README.md Scale the image to fill the given width and height, potentially cropping. For example, 50x32 becomes 11x15. ```javascript .doScale({width: 11, height: 15}) ``` -------------------------------- ### Binary save handler with XMLHttpRequest Source: https://github.com/devforth/painterro/blob/master/README.md Example of a save handler that posts image as binary multipart/form-data using raw XMLHttpRequest. Call done(true) to hide Painterro, done(false) to leave it open. ```javascript var ptro = Painterro({ saveHandler: function (image, done) { var formData = new FormData(); formData.append('image', image.asBlob()); // you can also pass suggested filename // formData.append('image', image.asBlob(), image.suggestedFileName()); var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://127.0.0.1:5000/save-as-binary/', true); xhr.onload = xhr.onerror = function () { // after saving is done, call done callback done(true); //done(true) will hide painterro, done(false) will leave opened }; xhr.send(formData); } }) ptro.show(); ``` -------------------------------- ### Scale to match width Source: https://github.com/devforth/painterro/blob/master/README.md Scale the image to match the given width, preserving aspect ratio. For example, 50x32 becomes 100x64. ```javascript .doScale({width: 100}) ``` -------------------------------- ### Scale by factor Source: https://github.com/devforth/painterro/blob/master/README.md Scale the image by a given factor. For example, 11x12 becomes 22x24. ```javascript .doScale({ scale: 2 }) ``` -------------------------------- ### Custom translation strings Source: https://github.com/devforth/painterro/blob/master/README.md Pass a translation object to override UI strings. The example sets the name to 'ua' and overrides the 'apply' string. ```javascript Painterro({ translation: { name: 'ua', strings: { apply: 'Застосувати' // other strings } } }).show() ``` -------------------------------- ### Save as PNG or JPEG based on alpha channel Source: https://github.com/devforth/painterro/blob/master/README.md Uses image.hasAlphaChannel() to choose PNG or JPEG format when getting a blob for upload. This optimizes file size by using JPEG when no transparency is present. ```JavaScript var ptro = Painterro({ saveHandler: function (image, done) { image.asBlob(image.hasAlphaChannel() ? 'image/png' : 'image/jpeg'); // upload blob } }) ``` -------------------------------- ### Exportable image object structure Source: https://github.com/devforth/painterro/blob/master/README.md Structure of the exportable image object passed to event callbacks like onChange and saveHandler. Contains methods to get blob, data URL, suggested file name, alpha channel info, original mime type, width, and height. ```javascript { image: { asBlob: ƒ asBlob(type, quality) // returns blob asDataURL: ƒ asDataURL(type, quality) // returns e.g. "data:image/jpeg;base64,/9j/4AAQS...." suggestedFileName: ƒ suggestedFileName(type) // returns string hasAlphaChannel(): ƒ suggestedFileName() // returns true or false getOriginalMimeType: ƒ getOriginalMimeType() // e.g. image/jpeg; getWidth: ƒ getWidth() // integer getHeight: ƒ getHeight() // integer } operationsDone: int // integer } ``` -------------------------------- ### Initialize Painterro with custom configuration Source: https://github.com/devforth/painterro/blob/master/build/index.html Creates a Painterro instance with Ukrainian language, custom color scheme, and a save handler, then shows it. ```javascript window.p = Painterro({ language: 'uk', backgroundFillColorAlpha: 0, hideByEsc: true, colorScheme: { main: '#8B817A', control: '#1A1A1A', controlContent: '#fff', controlShadow: 'none', activeControl: '#6F6762', activeControlContent: '#fff', hoverControl: '#6F6762', hoverControlContent: '#fff', }, //defaultTool : 'brush', //how_to_paste_actions: ['extend_right'], /*hiddenTools: [ 'select', 'crop', 'pixelize', 'line', 'arrow', 'rect', 'ellipse', // 'brush', // 'eraser', 'text', 'rotate', 'resize', // 'save', 'open', // 'close', // 'undo', 'redo', // 'zoomin', // 'zoomout', 'bucket', 'clear', 'settings', ], */ saveHandler: this._onPainterroSave, }); window.p.show() ``` -------------------------------- ### Show Painterro instance Source: https://github.com/devforth/painterro/blob/master/README.md Create and show a Painterro instance. ```javascript var p = Painterro() p.show() ``` -------------------------------- ### Authenticate and set credentials for publishing Source: https://github.com/devforth/painterro/blob/master/Release.md Commands for authenticating and setting environment variables for publishing. First, log in to npm. Then, read the GitHub token from ~/.ghtoken into GH_PASS, and read the WordPress password from ~/.wppassword into WP_PASSWORD. ```bash npm login ``` ```bash GH_PASS=`cat ~/.ghtoken` ``` ```bash WP_PASSWORD=`cat ~/.wppassword` ``` -------------------------------- ### Initialize Painterro with custom color scheme and backplate image Source: https://github.com/devforth/painterro/blob/master/build/contained.html Sets up a container element with fixed dimensions and initializes Painterro with a custom color scheme and a background image. The container ID must match the 'id' option in the Painterro call. ```css html,body,#wrapper { height:100%; margin:0; padding:0; background-color: lightgray; } #conatiner { position: relative; height: 300px; width: 300px; } ``` ```javascript Painterro({ id: 'conatiner', backgroundFillColor: '#eee', backplateImg: 'https://images.pexels.com/photos/3653762/pexels-photo-3653762.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940', colorScheme: { main: '#faf', control: '#d5d', activeControl: '#572257', inputBackground: '#cf99ca', } }).show(); ``` -------------------------------- ### Configure Painterro with parameters Source: https://github.com/devforth/painterro/blob/master/README.md Pass configuration parameters to the Painterro constructor. ```js Painterro({ activeColor: '#00ff00', // default brush color is green // ... other params here }) ``` -------------------------------- ### Import and show Painterro Source: https://github.com/devforth/painterro/blob/master/README.md Import Painterro and show the editor in your code. ```js import Painterro from 'painterro' ... Painterro().show() ``` -------------------------------- ### Build Painterro library Source: https://github.com/devforth/painterro/blob/master/README.md Builds the Painterro library, producing four versions of the library. The main result for script import is build/painterro.min.js. ```bash npm run build ``` -------------------------------- ### HTML and CSS layout for Painterro demo Source: https://github.com/devforth/painterro/blob/master/build/index.html Sets up the page layout with full-height containers and a flex holder for the editor. ```html Painterro().show() ``` -------------------------------- ### Save to TinyMCE WYSIWYG editor Source: https://github.com/devforth/painterro/blob/master/README.md Initializes TinyMCE and Painterro, inserting the captured image as an HTML img tag into the active editor. The done callback hides the editor after insertion. ```JavaScript tinymce.init({ selector:'textarea', }); var ptro = Painterro({ saveHandler: function (image, done) { tinymce.activeEditor.execCommand('mceInsertContent', false, ''); // after saving is done, call done callback done(true); //done(true) will hide painterro, done(false) will leave opened } }) ``` -------------------------------- ### Integrate Painterro with TinyMCE Source: https://github.com/devforth/painterro/blob/master/example/templates/paste_to_tinymce.html Integrates Painterro with TinyMCE. The first block initializes TinyMCE with a custom button and command that opens Painterro. The second block configures Painterro to insert the edited image into the editor via mceInsertContent when saved. ```javascript tinymce.init({ selector: 'textarea', plugins: [ 'fullscreen' ], toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table | fontsizeselect | painterro', height : "700", setup: function(editor) { editor.addButton("painterro", { title: "Open Painterro", cmd: "painterro_cmd", 'icon': "painterro ptro-icon ptro-icon-painterro", }); //button functionality. editor.addCommand("painterro_cmd", function () { ptro.show(); }); } }); ``` ```javascript var ptro = Painterro({ defaultSize: '500x400', saveHandler: function (image, done) { tinymce.activeEditor.execCommand('mceInsertContent',false, ''); done(true) } }) ``` -------------------------------- ### Open Painterro on paste event Source: https://github.com/devforth/painterro/blob/master/README.md Listens for paste events, reads the pasted file as a data URL, and opens Painterro with that image. Prevents multiple instances by checking window.painterroOpenedInstance. ```JavaScript document.onpaste = (event) => { const { items } = event.clipboardData || event.originalEvent.clipboardData; Array.from(items).forEach((item) => { if (item.kind === 'file') { if (!window.painterroOpenedInstance) { // if painterro already opened - it will handle onpaste const blob = item.getAsFile(); const reader = new FileReader(); reader.onload = (readerEvent) => { window.painterroOpenedInstance = Painterro({ onHide: () => { window.painterroOpenedInstance = undefined; }, saveHandler: (image, done) => { console.log('Save it here', image.asDataURL()); // you could provide your save handler done(true); }, }).show(readerEvent.target.result, item.type); }; reader.readAsDataURL(blob); } } }); }; ``` -------------------------------- ### Configure Painterro with saveHandler to Upload Base64 Image Source: https://github.com/devforth/painterro/blob/master/example/templates/paste_as_base64.html Configures Painterro with a saveHandler that posts the edited image as a base64 data URL to the local server endpoint /save-as-base64/, then reloads the page on success. ```javascript var ptro = Painterro({ saveHandler: function (image, done) { var xhr = new XMLHttpRequest() xhr.open('POST', 'http://127.0.0.1:5000/save-as-base64/') xhr.setRequestHeader('Content-Type', 'application/json') xhr.send(JSON.stringify({ image: image.asDataURL('image/png') })) xhr.onload = function (e) { done(true) window.location.reload() } } }) ``` -------------------------------- ### Include Painterro script tag Source: https://github.com/devforth/painterro/blob/master/README.md Include the Painterro script in your HTML head. ```html ``` -------------------------------- ### Painterro saveHandler with XHR POST Source: https://github.com/devforth/painterro/blob/master/README.md Initializes Painterro with a saveHandler that sends the image as a base64 data URL via XMLHttpRequest to a backend endpoint. The done callback hides or keeps the editor open based on its argument. ```JavaScript var ptro = Painterro({ saveHandler: function (image, done) { // of course, instead of raw XHR you can use fetch, jQuery, etc var xhr = new XMLHttpRequest(); xhr.open("POST", "http://127.0.0.1:5000/save-as-base64/"); xhr.setRequestHeader("Content-Type", "application/json"); xhr.send(JSON.stringify({ image: image.asDataURL() })); xhr.onload = function (e) { // after saving is done, call done callback done(true); //done(true) will hide painterro, done(false) will leave opened } }, activeColor: '#00b400' // change active color to green }); ptro.show(); ``` -------------------------------- ### Flask backend for binary save Source: https://github.com/devforth/painterro/blob/master/README.md Python Flask backend endpoint that saves the uploaded image file. The same can be implemented with any technology. ```python @app.route("/save-as-binary/", methods=['POST']) def binary_saver(): filename = '{:10d}.png'.format(int(time())) # generate some filename filepath = os.path.join(get_tmp_dir(), filename) request.files['image'].save(filepath) return jsonify({}) ``` -------------------------------- ### Listen for active tool change events Source: https://github.com/devforth/painterro/blob/master/build/index.html Adds an event listener to the app element to log when the active tool changes. ```javascript const el = document.getElementById('app') el.addEventListener('changeActiveTool',(e)=>{console.log('activeToolHasBeenCHanged',e)}) ``` -------------------------------- ### Replace import path for Painterro Source: https://github.com/devforth/painterro/blob/master/README.md Replace the default import from 'painterro' with the absolute path to the commonjs2 build file in your side app. This allows you to use the source version during development. ```javascript import Painterro from 'painterro'; ``` ```javascript import Painterro from '/home/ivan/devforth/painterro/build/painterro.commonjs2.js'; ``` -------------------------------- ### Regenerate icons font Source: https://github.com/devforth/painterro/blob/master/README.md Run this command to regenerate the icon font after adding or editing icons in the 'res' folder. ```bash npm run buildfont ``` -------------------------------- ### Access Painterro canvas context and commented drawing code Source: https://github.com/devforth/painterro/blob/master/build/index.html Retrieves the canvas context from the Painterro instance and includes commented-out drawing and paste handling code. ```javascript const ctx = window.p.ctx; // ctx.beginPath(); // ctx.moveTo(0,0); // ctx.lineTo(300,150); // ctx.strokeStyle="#FF0000"; // ctx.stroke(); // document.onpaste = (event) => { // const { items } = event.clipboardData || event.originalEvent.clipboardData; // Array.from(items).forEach((item) => { // if (item.kind === 'file') { // if (!window.painterroOpenedInstance) { // // if painterro already opened - it will handle onpaste // const blob = item.getAsFile(); // const reader = new FileReader(); // reader.onload = (readerEvent) => { // window.painterroOpenedInstance = Painterro({ // initText: 'Press PrtScr, Ctrl+V to paste screenshot.
Press Ctrl+S to save', // // todo: different for os-es // onHide: () => { // window.painterroOpenedInstance = undefined; // }, // saveHandler: (image, done) => { // console.log('Save it here', image.asDataURL()); // // you could provide your save handler // done(true); // }, // }).show(readerEvent.target.result, item.type); // }; // reader.readAsDataURL(blob); // } // } // }); // }; ``` -------------------------------- ### Exclude Painterro from linting in package.json Source: https://github.com/devforth/painterro/blob/master/README.md Add this eslintIgnore configuration to your side app's package.json to exclude the compiled Painterro file from linting. Replace the path with your actual Painterro source folder. ```json "eslintIgnore": [ "/home/ivan/devforth/painterro/build/painterro2.commonjs.js" ], ``` -------------------------------- ### Backend endpoint to save base64 image Source: https://github.com/devforth/painterro/blob/master/README.md Flask route that receives a base64-encoded image from Painterro, decodes it, and saves it as a PNG file. The image data is expected in the JSON field 'image' with a data URL prefix. ```Python @app.route("/save-as-base64/", methods=['POST']) def base64_saver(): filename = '{:10d}.png'.format(int(time())) # generate some filename filepath = os.path.join(get_tmp_dir(), filename) with open(filepath, "wb") as fh: base64_data = request.json['image'].replace('data:image/png;base64,', '') fh.write(base64.b64decode(base64_data)) return jsonify({}) ``` -------------------------------- ### Current history state object structure Source: https://github.com/devforth/painterro/blob/master/README.md Structure of the current history state object passed to onUndo and onRedo events. Contains prev and next state references, counts, and size information. ```javascript { prev: {} or undefined next: {} or undefined prevCount: int sizeh: int sizew: int } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.