Code Monkey home page Code Monkey logo

painterro's Introduction

live demo | npm | GitHub           npmvers npmDown totalNpm ghdownloads

JavaScript painting plugin which allows editing images in a browser. Can be easily integrated into any website or webapp by calling simple initialization code.

🙏🙏🙏 Scream for help to Ukraine 🇺🇦

24 February 2022, Russia started bombing cities with peacefully civilized population in whole Ukraine. And has been doing it up to this day. Breaking all laws of war. Their bombs has been killing children and adults. This deserves Hague court.

  • 🏠 If you are from Russia, please stop your government by any means including protests, don't trust local media, they are bribed by the government. They always was. I am sure you already feel lie by unexplainable crazy things in your country caused by world sanctions.
  • 💣 Please spread the information about bombing of Ukraine in all social way you could. Russia treacherously broke into the territory of a sovereign state. Do not trust to anything from Russian media, most likely it will be bullshit
  • 💼 If you have any kind of business cooperation with Russia, please block it now and keep most of money on your side, this is the only possible ethical decision
  • ☢️ Ask your government to stop Russia from spreading invasion in any way. Russia is nuclear threat to the whole world. You think it is not possible? We thought that bombing of independent country with population of 44.13 million is also not possible.

Features

  • Paste image from clipboard with Ctrl+V (e.g. PtnScr screenshot), drag and drop it into widget, or load with file select dialog
  • Crop image by defined area
  • Paint primitives: line, rectangle, ellipse (alpha color can be used)
  • Brush – free drawing tool e.g. to implement finger-based signatures on tablet screens
  • Add text (you can use Ctrl+B - bold, Ctrl+I - italic, Ctrl+U - underlined, or just pase formatted HTML)
  • Rotate / resize, scale image
  • Pixelize some area to hide sensitive data
  • Draw arrows
  • Trash can tool to clear the canvas
  • Paint bucket tool for color fills
  • Add filters to images

Painterro gif preview

Used by



NASA Open MCT



Cisco DevNet



Tracklify



FastDivs


Advantages 💪

  • It is lightweight and minimalistic - written with vanilla JS, you don't need dependencies to use it
  • Designed to process images with minimal clicks, most actions support hot-keys
  • Could be easily integrated into SPA application (React, Vue, Angular)
  • Could be used in Electron and Cordova apps
  • Flexibale image saving - you provide your save handler, and get base64 data with any jpeg/png compression
  • Could be translated to any language

Originally Painterro was designed for quick screenshots processing: You make screenshot by pressing PrtSc button, then open Painterro on your website, paste an image with Ctrl+V, crop it to interested area, highlight something with line/rectangle tool and/or add some text to the image and save on server with custom save handler (e.g. simple XHR request to your backend). In addition, you can use Painterro as image editor for any kind of raster images. Please try a demo. Also painterro has Wordpress Plugin.

If you want to see some feature in Painterro, please leave (or vote for) an issue here. There is no promise that it will be implemented soon or ever, but it is interesting to know what features users want to have.

Usefull hints and tweaks 😋:

Table of contents

Installation

With npm

If you have npm-based project (e.g. SPA like React/Vue) you can run:

npm install painterro --save

Then in your code

import Painterro from 'painterro'
...
Painterro().show()

By including script

You can download latest painterro-*.min.js here https://github.com/devforth/painterro/releases/ or build it by yourself.

Then insert <script> e.g to <head> section of your HTML file:

<script src="/xxx/painterro-x.x.x.min.js"></script>

Then in your code (body section, onclick handler, etc):

<script>
  Painterro().show()
</script>

See jsfiddle.net example

Read after installation

To be able to save edited images on server or client see Saving image. For configurations see Configuration

Supported hotkeys ⌨

Ctrl + Z Cancel last operation
Ctrl + V Paste image from clipboard
Ctrl + C Copy selected aria to clipboard
Shift when drawing rect/ellipse Draw square/circle
Shift when drawing line draw at angles of 0, 45, 90, 135 etc degrees
Alt when using pipette Hide zoom helper (colored grid)
Ctrl + Wheel mouse up/down Zoom image
Ctrl + S Save image

Also some tools have own one-button hotkeys e.g. C - crop, you could see this shortcuts if you will hold mouse on toolbutton.

Configuration ⚙

You can pass parameters map to Painterro constructor:

Painterro({
  activeColor: '#00ff00', // default brush color is green
  // ... other params here
})
Param Description Default
id If provided, then Painterro will be placed to some holder on page with this id, in other case holder-element will be created (fullscreen with margins). Important note: If you are using your block and id option, please add position:relative or absolute or fixed on your container, default (static) will lead to positioning issues undefined
activeColor Line/Text color that selected by default '#ff0000'
activeColorAlpha Transparancy of activeColor from 0.0 to 1.0, 0.0 = transparent 1
activeFillColor Fill color that selected by default '#000000'
activeFillColorAlpha Transparancy of activeColor from 0.0 to 1.0 0
defaultLineWidth Line width in px that selected by default 5
defaultPrimitiveShadowOn Enable Shadow for primitive tools (easier recognize them on a screenshots) true
defaultEraserWidth Eraser width in px that selected by default 5
backgroundFillColor Default background color when image created/erased '#ffffff'
backgroundFillColorAlpha Transparancy of backgroundFillColor from 0.0 to 1.0 1.0
textStrokeColor Stroke color of text tool '#ffffff'
textStrokeColorAlpha Stroke color of text tool 1.0
shadowScale Change text shadow blur for text and arrow 1.0
defaultFontSize Default font size in pixels 24
backplateImgUrl background for drawing, doesn't include in final image undefined
defaultTextStrokeAndShadow Enables Stroke and Shadow for text tool by default (easier recognize text on screenshots) true
defaultSize default image size, should be string in format <width>x<height> in pixel, e.g. '200x100'. If value is 'fill'(default) than all container size will be used 'fill'
defaultTool Tool selected by default 'select'
hiddenTools List of tools that you wish to exclude from toolbar. Subset from this list ['crop', 'line', 'arrow', 'rect', 'ellipse', 'brush', 'text', 'rotate', 'resize', 'save', 'open', 'close', 'undo', 'redo', 'zoomin', 'zoomout', 'bucket'], You can't hide default tool ['redo']
initText Display some centered text before painting (supports HTML). If null, no text will be shown null
initTextColor Color of init text '#808080'
initTextStyle Style of init text "26px 'Open Sans', sans-serif"
pixelizePixelSize Default pixel size of pixelize tool. Can accept values - x - x pixels, x% - means percents of minimal area rectangle side 20%
pixelizeHideUserInput Don't allow users to enter pixel size In settings tools (and save in localstorage), this would allow developer to freeze pixel size by using params pixelizePixelSize to make sure users will not set low pixel sizes false
availableLineWidths A list of the line width values that are available for selection in a drop down list e.g. [1,2,4,8,16,64]. Otherwise an input field is used. undefined
availableArrowLengths A list of the arrow sizes values that are available for selection in a drop down list e.g. [10,20,30,40,50,60]. Otherwise an input field is used. undefined
defaultArrowLength default arrow length 15
availableEraserWidths A list of the eraser width values that are available for selection in a drop down list e.g. [1,2,4,8,16,64]. Otherwise an input field is used. undefined
availableFontSizes A list of the font size values that are available for selection in a drop down list e.g. [1,2,4,8,16,64]. Otherwise an input field is used. undefined
toolbarPosition Whether to position the toolbar at the top or bottom. 'bottom'
fixMobilePageReloader By default painterro adds overflow-y: hidden to page body on mobile devices to prevent "super smart" feature lice Chrom's reload page. Unfortunately we can't prevent it by preventDefault. If your want to scroll page when painterro is open, set this to false true
language Language of the widget. 'en'
how_to_paste_actions List of paste options that will be suggested on paste using some paste dialog e.g. ['extend_right', 'extend_down'] . If there is only one option in list, then it will chosen automatically without dialog ['replace_all', 'paste_over', 'extend_right', 'extend_down']
replaceAllOnEmptyBackground Whether to select replace_all without dialog on first paste after painterro was just opened. So it will replaces background with image (will change dimensions to pasted image when background is empty) true
hideByEsc If true then ESC press will hide widget false
saveByEnter If true then ENTER press will do same as Ctrl+S false
extraFonts By default Text tool supports only several predefined fonts due to compatibility considirations , but yousing this option you can add any fonts you want if you are sure they are available on your page/app ['Roboto']
toolbarHeightPx Height of toolbar in pixels 40
buttonSizePx Button for toolbar in pixels 32
bucketSensivity Bucket tool sensivity 100
customTools List of the custom tools which will appear at the left menu after default options. Custom tool includes three options : {name:string, callBack:function, iconUrl:dataURL string or URL}

Events

Param Description Accepted Arguments
onBeforeClose Function that will be called when user closes painterro it, call doClose to confirm close hasUnsavedChaged: bool, doCloseCallback: function
onClose If passed will be triggered when painterro closed by X button (use onHide for all close reasons) undefined
onHide If passed will be triggered when painterro hides (by X button or save or any other way) undefined
onChange Function that will be called if something will be changed (painted, erased, resized, etc) <exportable image>
onUndo Function that will be called if user will undo (Ctrl+Z) {<current history state>}
onRedo Function that will be called if user will redo (Ctrl+Z) {<current history state>}
onImageFailedOpen Function that will be called if image can`t open undefined
onImageLoaded Function that will be called if you passed image to show and when it was loaded undefined
saveHandler Function that will be called when user presses Save (or Ctrl+S), Call doneCallback to reflect in painterro that image was saved {<exportable image>}, doneCallback : function

Events accepted arguments:

  • {<exportable image>} is object:
{ 
  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
} 
  • {<current history state>} is object:
{
  prev: {<current history state>} or undefined
  next: {<current history state>} or undefined
  prevCount: int
  sizeh: int
  sizew: int
}

UI color scheme

Next group of params used to configure painterro user interface in simple "JS way". They should be placed under colorScheme group, for example:

Painterro({
  colorScheme: {
    main: '#fdf6b8', // make panels light-yellow
    control: '#FECF67' // change controls color
  }
}).show()
Param Description Default
main Color of panels, take most of UI space '#fff'
control Color of controls background (e.g. button background) '#fff'
controlShadow Color controls box shadow '0px 0px 3px 1px #bbb'
controlContent Content of controls (e.g. button text) '#000000'
activeControl Color for control when it active (e.g. button pressed) '#7485B1'
activeControlContent Color for activated control content main
inputBorderColor You can add border to inputs, by default color is same as main so borders will not be seen main
inputBackground Background of inputs '#ffffff'
inputShadow shadow of input 'inset 0 0 4px 1px #ccc'
inputText Color of text in input activeControl
backgroundColor Background color of component area which left outside of image due to it size/ratio '#999999'
dragOverBarColor Color of bar when dropping file to painterro '#899dff'
hoverControl Controls color when mouse hovered control
hoverControlContent Controls background color when mouse hovered '#1a3d67'
toolControlNameColor Color of toolbar labels that prepend controls rgba(255,255,255,0.7)

NOTE: all these params are defined only for simplicity, you are free to redefine them in your cascade style files (we don't use importants and so on, so all props should be easily editable). This mettod is recommended for experts - because you can use your CSS preprocessor variables and adopt Painterro for your design. Example usecase is different color of shadows for a buttons with ::after/::before

API

.show([optional]openImage, [optional]initialMimeType) - Shows painterro instance. openImage can have next values:

  • false - will open image that already was drawn before last close
  • some string value, e.g. 'http://placehold.it/120x120&text=image1' - will try to load image from url
  • all another values - will clear content before open

initialMimeType could be used to help painterro understand which file do you try to load there. Could be useful if you want to save the original mime and file opened explicitly (painterro open tool or dnd/ctrl+v handlers get it automatically)

.hide() - hide instance

.setColor(options) - sets the color of the chosen tool , or changes initial value of color. options should be array with two values, [target,colorWidgetState]

available values for target:

|line|, |bg|

colorWidgetState - object with requred properties :

  • palleteColor - color string . Just indicates which color will be shown on the collor pallete.
  • alpha - number in range from 0 to 1. The same but for alpha channel.
  • alphaColor - color string. Color with alpha, which will be using for drawing element.

NOTE: paleteColor and alpha is using only for displaing right values in color picker widget, this two options don't effect on color which will be used for drawing elements.

.setLineWidth() - set line width for chosen tool.

.setArrowLength() - set width for chosen arrow.

.setEraserWidth() - set width of eraser

.setShadowOn() - set shadowfor line elements or arrow element. It takes boolean value.

.save() - call save (same save as on buttons bar). Can be used if save button is hidden (hiddenTools: ['save'])

.doScale({ width, height, scale }) - scale the image and resize area.

Scale to match the width and scale height proportinally (e.g. 50x32 will become 100->64):

.doScale({width: 100})

Scale to fill width and height (e.g. 50x32 will become 11->15):

.doScale({width: 11, height: 15})

Scale x2 (e.g. 11x12 will become 22->24):

.doScale({ scale: 2 })

Example:

var p = Painterro()
p.show()

Translation 📙

Want to translate Painterro into your language?

If you need one of languages in table below, just pass pass language parameter, for example:

Painterro({
  language: 'es'  // Spanish
}).show()

Translated languages:

language param Name
ca Catalan
de German
en English
es Spanish
fa Iran-Farsi (Persian (Ir-Fa)
fr French
ja Japanese
pl Polish
pt-PT European Portuguese
pt-BR Brazilian Portuguese
ru Russian
nl Dutch

If you want to add another language, then:

  1. fork to your GitHub with button on top.
  2. Create empty file in folder langs [<LANG_ISO_CODE>.lang.js] for your translation. LANG_ISO_CODE should follow ISO 639-1
  3. Copy content from [langs/en.lang.js] to a new file
  4. Then translate all 'Strings'
  5. Add reference in [js/translation.js] inside of your repo.
  6. After that create pull-request, or just open issue if you don't know how to create a PR.

🤔 Found a bug in some word for your language? Feel free to edit on GitHub directly and suggest a fix.

If you want to translate or change strings without contributing you can do this by passing translation parameter, for example:

Painterro({
  translation: {
    name: 'ua',
    strings: {
      apply: 'Застосувати'    
      // other strings
    }
  }
}).show()

For all strings that should be translated, see [langs/en.lang.js]

Saving image 💾

You should provide your own save handler, that will post/update image on server or will pass image to other frontend components. In this section we will provide several backend examples on python Flask (easiest web server for python). Anyway if you will face any python exception you can use super-helpfull fixexception.com service to fix any issue you will face 💪.

Binary saving

You can post data with binary multipart/form-data request which is the most efficient way to pass data to backend. Example uses raw XMLHttpRequest. Of course, you can use fetch, jQuery, etc insead.

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();

Here is python flask backend example (of course same can be implemented using any technology):

@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({})

See full example in example directory. You can run it used python3 with installed Flask (pip install flask).

Base64 saving

You can also same image by posting base64 string via plain POST json call. Please note that base64 encoding is less efficient then binary data, for example some 1920 x 1080 image took 402398 bytes for base64 upload. The same image took 301949 bytes with multipart/form-data.

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();

Backend should convert base64 to binary and save file:

@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({})

Saving to WYSIWYG

You can just insert image as data url to any WYSIWYG editor, e.g. TinyMCE:

    tinymce.init({ selector:'textarea', });
    var ptro = Painterro({
      saveHandler: function (image, done) {
        tinymce.activeEditor.execCommand('mceInsertContent', false, '<img src="' + image.asDataURL() + '" />');
        // after saving is done, call done callback
        done(true); //done(true) will hide painterro, done(false) will leave opened
      }
    })

Format and quality

When you call image.asDataURL() or image.asBlob(), you can also specify image mime type (format), e.g. image.asDataURL('image/jpeg').

Default type is mimetype used by image which was loaded into Painterro, or "image/png" if image was created from scratch.

If type is image/jpeg or image/webp, you can also define image quality from 0.0 to 1.0, default is 0.92, example: image.asDataURL('image/jpeg', 0.5)

Save to jpeg or png depending on whether there is an alpha channel

An efficient way to save an image might be implmented by checking whether image has some alpha pixels:

  • If yes - we need to serve image in less efficient png format
  • Otherwise lets just use JPEG This is very simple with next:
var ptro = Painterro({
  saveHandler: function (image, done) {

    image.asBlob(image.hasAlphaChannel() ? 'image/png' : 'image/jpeg');
    // upload blob
  }
})

Example: Open Painterro by Ctrl+V

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

If you face any painterro errors (exceptions), please reffer to Painterro page on FixJSError

Development 🔨

Latest supported NodeJS version is 16, use nvm to switch to it:

nvm install 16
nvm use 16

Code written on ES6 which transplited by Babel and packed (minified) to a single file using webpack. All configs are inside so all you have to do after pulling repo is installing node modules:

cd painterro
npm ci

Building painterro

npm run build

Result file for <script> import is build/painterro.min.js.

Actually, above command produces 4 versions of library:

  • build/painterro-x.y.z.min.js, build/painterro.min.js the same files but with different filenames (with and without versiontag) - this is var version which will be loaded as global variable (var painterro = <Library class>) when you will import it as <script src='painterro.min.js' /> tag. So this is for script tag only.
  • build/painterro.commonjs2.js - this version sutable for js require/import. That's why it is used as entry point in package.json file - if you are using webpack or other tool that can handle require/import of commonjs2 libraries then you can do npm install painterro, and do import painterro and it will use commonjs2 version.
  • build/painterro.amd.js and build/painterro.umd.js - these both are same as above but for AMD and UMD importers respectivly.

Dev-server

To start hot-reload dev server (for reloading code "on the fly"):

npm run dev

Then open http://localhost:3000 with demo page

Editing source on the fly for painterro imported from side webpack app (e.g. your project SPA)

  1. If your side app uses 'eslint' it, most likely side app will need eslint-plugin-import:
npm i eslint-plugin-import
  1. Since compiled painterro commonjs2 file already linted and minimized you need to exclude it from linting:

Add to package.json of your side app:

  "eslintIgnore": [
    "/home/ivan/devforth/painterro/build/painterro2.commonjs.js"
  ],

where /home/ivan/devforth/painterro is a folder with Painterro sources

  1. Replace
import Painterro from 'painterro';

with

import Painterro from '/home/ivan/devforth/painterro/build/painterro.commonjs2.js';
  1. Go to painterro source folder and run:
watch npm run build

Regenerating icons font

If you need add/edit icons in res folder, please after editing run:

npm run buildfont

For font generation we use method described here: How to generate a webfont (automated setup)

Contributing

Pull-requests are welcome.

If you want to say thank us Patreon is here

Supported by DevForth - Best quality, rapid, modern tech development services

painterro's People

Contributors

4rno avatar alexnavratil avatar alonaradchenko avatar azbesciak avatar crmtestresco avatar dalgarins avatar darktimeoff avatar davesmith9088 avatar dependabot[bot] avatar frifrafry avatar ihorstorozhok avatar ivictbor avatar jesfery avatar kingofnull avatar krofinzki avatar kyusung4698 avatar michaelklem avatar nebosuker avatar pjbakker avatar reni-min avatar svd-sea avatar vadimpyshenko avatar viliusle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

painterro's Issues

setAttribute error

Hi,

This is the best js library for image manipulation.

For version 0.2.21 when put the 'crop' in hiddenTools there a console error:
"Uncaught TypeError: Cannot read property 'setAttribute' of null"
Thanks.

[BUG] If defaultTool is set, Crop & Pixelize buttons are not disabled

Minor issue with toolbar buttons. If defaultTool is set to for example arrow, the Crop & Pixelize buttons are enabled. Clicking them produce browser's console error :

painterro.commonjs2.js:234 Uncaught TypeError: Cannot read property '0' of undefined
    at A.value (painterro.commonjs2.js:234)
    at Object.activate (painterro.commonjs2.js:245)
    at A.value (painterro.commonjs2.js:245)
    at HTMLButtonElement.n.getBtnEl.onclick [as ontouch] (painterro.commonjs2.js:245)
value @ painterro.commonjs2.js:234
activate @ painterro.commonjs2.js:245
value @ painterro.commonjs2.js:245
n.getBtnEl.onclick @ painterro.commonjs2.js:245

handling how_to_paste event

how to handle how_to_paste event to default as replace all..

and also open image is very slow when i done it in angular-ionic app, it keep on showing loading......

Is possible blur setting for small area

Hi,

Is there a possibility to hide sensitive data to controlling pixel intensity effect(pixels on the selected area), without repeating pixel tool?

Problem is when a text in picture and it very small area for blur. Then pixelize is imperfect.

Maybe a good idea is setting for this.

pixel_text

Thanks.

[Bug] Insert text on IE

Hi !

The text insertion doesn't work under IE. Do you plan a fix or is there a way to workaround ?

Thanks by advance

Text not working in IOS app in 0.2.48

Hi Ivictbor,

First of all, thank you for this amazing widget. I am currently trying to implement paintero on my cordova app. I am able to use all the functionality but for some reason the text does not work. When I click the text button the text box does appear but I am not able to append the text to the editable span. Could you please look into this issue. Thank you.

[Feature Request] New positions

Would be great to have the options at Right or Left side. Right now we can only choose between Top and Bottom for what I saw.

Best Regards

Translation texts to spanish and catalan and a proposal

Hello, I send here the strings to translate to spanish and catalan, hope it helps.
And one proposition for this magnific control: a button to add simbols like stars, text ballons, arrows, etc.
Thank you !

Spanish:

translation: {
    name: 'es',
    strings: {
      	lineColor: 'L',
        lineColorFull: 'Color de linea',
        fillColor: 'O',
        fillColorFull: 'Color de relleno',
        alpha: 'T',
        alphaFull: 'Transparencia',
        lineWidth: 'A',
        lineWidthFull: 'Ancho de linea',
        eraserWidth: 'B',
        eraserWidthFull: 'Ancho de borrador',
        textColor: 'C',
        textColorFull: 'Color de texto',
        fontSize: 'L',
        fontSizeFull: 'Tamaño de letra',
        fontStrokeSize: 'TLl',
        fontStrokeSizeFull: 'Tamaño de linea de letra',
		fontStyle: 'EL',
        fontStyleFull: 'Estilo de letra',
        fontName: 'NL',
        fontNameFull: 'Nombre del tipo de letra',
        textStrokeColor: 'CL',
        textStrokeColorFull: 'Color de letra',
        apply: 'Aplicar',
        cancel: 'Cancelar',
        close: 'Cerrar',
        clear: 'Limpiar',
        width: 'Ancho',
        height: 'Alto',
        keepRatio: 'Mantener ratio Ancho/Alto',
        fillPageWith: 'Rellenar la página con el color de fondo actual',
        pixelSize: 'P',
        pixelSizeFull: 'Tamaño de pixel',
        resizeScale: 'Escala',
        resizeResize: 'Redimensionar',
        backgroundColor: 'Color de fondo de la página',
        pixelizePixelSize: 'Tamaño de pixel al pixelar',
        wrongPixelSizeValue: 'Tamaño de pixel incorrecto. Puedes entrar por ejemplo \"20%\" que significa que el tamaño de pixel es 1/5 del area seleccionada, o \"4\" significa 4 px',
		tools: {
          crop: 'Recortar imagen a la area seleccionada',
          pixelize: 'Pixelar la area seleccionada',
          rect: 'Dibujar rectángulo',
          ellipse: 'Dibujar eclipse',
          line: 'Dibujar linea',
          rotate: 'Rotar imagen',
          save: 'Guardar imagen',
          load: 'Cargar imagen',
          text: 'Escribir texto',
          brush: 'Pincel',
          resize: 'Cambiar tamaño o escalar',
          open: 'Abrir imagen',
          select: 'Selección de area',
          close: 'Cerrar editor',
          eraser: 'Borrador',
          settings: 'Parámetros',
        },
        pasteOptions: {
          fit: 'Reemplazar todo',
          extend_down: 'Extender hacia abajo',
          extend_right: 'Extender a la derecha',
          over: 'Pegar encima',
          how_to_paste: 'Cómo se ha de pegar?'
        }
    }
  }

Catalan:

  translation: {
    name: 'ca',
    strings: {
      	lineColor: 'L',
        lineColorFull: 'Color de línia',
        fillColor: 'O',
        fillColorFull: 'Color per omplir',
        alpha: 'T',
        alphaFull: 'Transparència',
        lineWidth: 'A',
        lineWidthFull: 'Ample de línia',
        eraserWidth: 'B',
        eraserWidthFull: 'Ample de borrador',
        textColor: 'C',
        textColorFull: 'Color de texte',
        fontSize: 'L',
        fontSizeFull: 'Tamany de la lletra',
        fontStrokeSize: 'TLl',
        fontStrokeSizeFull: 'Tamany linea de la lletra',
		fontStyle: 'EL',
        fontStyleFull: 'Estil de lletra',
        fontName: 'NL',
        fontNameFull: 'Nom del tipus de lletra',
        textStrokeColor: 'CL',
        textStrokeColorFull: 'Color de lletra',
        apply: 'Aplicar',
        cancel: 'Cancel·lar',
        close: 'Tancar',
        clear: 'Netejar',
        width: 'Ample',
        height: 'Alt',
        keepRatio: 'Mantenir ratio Ample/Alt',
        fillPageWith: 'Omplir la pàgina amb el color de fons actual',
        pixelSize: 'P',
        pixelSizeFull: 'Tamany de pixel',
        resizeScale: 'Escala',
        resizeResize: 'Redimensionar',
        backgroundColor: 'Color de fons de la pàgina',
        pixelizePixelSize: 'Tamany de píxel al pixelar',
        wrongPixelSizeValue: 'Tamany de píxel incorrecte. Pots entrar per exemple \"20%\" que significa que el tamany de píxel és 1/5 de l\'àrea seleccionada, o \"4\" significa 4 px',
		tools: {
          crop: 'Retallar imatge a l\'àrea seleccionada',
          pixelize: 'Pixelar l\'àrea seleccionada',
          rect: 'Dibuixar rectangle',
          ellipse: 'Dibuixar eclipse',
          line: 'Dibuixar línia',
          rotate: 'Rotar imatge',
          save: 'Guardar image',
          load: 'Carregar image',
          text: 'Escriure texte',
          brush: 'Pinzell',
          resize: 'Cambiar tamany o escalar',
          open: 'Obrir imatge',
          select: 'Seleció d\'àrea',
          close: 'Tancar editor',
          eraser: 'Borrador',
          settings: 'Paràmetres',
        },
        pasteOptions: {
          fit: 'Reemplaçar tot',
          extend_down: 'Extendre cap avall',
          extend_right: 'Extendre a la dreta',
          over: 'Empegar al damunt',
          how_to_paste: 'Com s\'ha d\'empegar?'
        }
    }
  }

Any way to save the state of drawing pattern?

Hi, is there any way to preserve the changes done on page load. To maintain a state or something like that.
Also if I can pass the saved state to different route as parameters, to load another instance of painterro in that route, it would be great.

Thanks.

[Doubt] Language Files

Hi there, I am interested on providing PRs for Portuguese (Portugal and Brasil) and French languages but I want to know which filenames I should give. Portuguese-Portugal normally is just pt or pt-PT and Portuguese-Brasil is pt-BR and french just fr or fr-FR.

So it would be:

pt-PT.lang.js
pt-BR.lang.js
fr.lang.js

?

[Feature Request] Smudge Tool

At First i should thank you for sharing this with us, it's very nice and has been very useful to me.
I know this is too much, but can you add smudge tool (like Photoshop) to it?
Many of us using this as image editor and there are many situation that smudge tool comes very handy, in fact if there was smudge tool, for editing pictures, most of us won't need any other image editor application for web.
Thanks again and sorry for my poor English.

[Bug] Out of memory

Resize tool allows to enter any width and height that leads to : Out of memory:

build.bf4afac32cb9.js:341 Uncaught RangeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': Out of memory at ImageData creation
    at e.value (build.bf4afac32cb9.js:341)
    at e.value (build.bf4afac32cb9.js:352)
    at HTMLDocument.mousedown (build.bf4afac32cb9.js:352)

How can I add image loader

I want to add a loader while a big image getting loaded. Is there any property in painterro to set image loader?
Thanks
Paritosh

Feature request: Close event

Thank you for this very useful plug in.
I feel like this is missing (or maybe i haven't noticed) a very simple an onCloseHandler, just like the onChangeHandler, for when the close button is clicked or the painter is set to hidden.

Image Size Issue

When I upload image size 100 kb, after saving it becomes 700kb. I am not able to understand logic behind it. how can it fix? Please suggest me.

Save in Angular

HI Guys,

How can i save this image into blob in angular , can you guys please guide me on this...

React with webpack: e.defaultSize.split is not a function

After transitioning our web app to react, we've encountered such an issue:
image
Seems like it is line 108 in params.js in your source code.

We get in randomly, 50% of time, when calling Painterro(painterroConfiguration).
Here is our painterroConfiguration json.
{ "translation": { "name": "en", "strings": { "lineColor": "Line color: ", "lineColorFull": "Line color", "fillColor": "Fill color: ", "fillColorFull": "Fill color", "alpha": "Alpha value", "alphaFull": "Alpha value", "lineWidth": "Line width: ", "lineWidthFull": "Line width", "eraserWidth": "Eraser width: ", "eraserWidthFull": "Eraser width", "textColor": "Text color: ", "textColorFull": "Text color", "fontSize": "Font size: ", "fontSizeFull": "Font size", "fontStrokeSize": "Stroke width: ", "fontStrokeSizeFull": "Stroke width", "fontStyle": "Font style: ", "fontStyleFull": "Font style", "fontName": "Font name: ", "fontNameFull": "Font name", "textStrokeColor": "Stroke color: ", "textStrokeColorFull": "Stroke color", "apply": "Apply", "cancel": "Cancel", "close": "Close", "clear": "Clear", "width": "Width", "height": "Height", "keepRatio": "Keep width/height ratio", "fillPageWith": "Fill page with current background color", "pixelSize": "P", "pixelSizeFull": "Pixel size", "resizeScale": "Scale", "resizeResize": "Resize", "backgroundColor": "Page background color", "pixelizePixelSize": "Pixelize pixel size", "wrongPixelSizeValue": "Wrong pixel size. You can enter e.g. \"20%\" which mean pixel size will be 1/5 of the selected area side, or \"4\" means 4 px", "tools": { "crop": "Crop image to selected area", "pixelize": "Pixelize selected area", "rect": "Draw rectangle", "ellipse": "Draw ellipse", "line": "Draw line", "rotate": "Rotate image", "save": "Save image", "load": "Load image", "text": "Put text", "brush": "Brush", "resize": "Resize or scale", "open": "Open image", "select": "Select area", "close": "Close Painterro", "eraser": "Eraser", "settings": "Settings" }, "pasteOptions": { "fit": "Replace all", "extend_down": "Extend down", "extend_right": "Extend right", "over": "Paste over", "how_to_paste": "How to paste?" } } }, "id": "scratch-pad-containter", "defaultTool": "brush", "hiddenTools": ["crop", "pixelize", "rotate", "resize", "settings", "close", "save", "text"], "defaultSize": "fill", "defaultLineWidth": 4, "defaultEraserWidth": 16, "availableLineWidths": [1,2,4,8,16], "availableEraserWidths": [1,2,4,8,16,64], "availableFontSizes": [1,2,4,8,16], "colorScheme": { "main": "rgba(0,98,217,0.6)", "control": "white", "activeControl": "rgba(230,230,230,1)", "inputText": "black" } }
Switching default size to e.g. 100x100 or even removing it completely doesn't help too.

Browse PDF

HI Team,

can we browse and open PDF in this painterro?

Painterro prevents page scrolling on mobile browser

Page with Painterro does not scroll on mobile browsers. When user clicks "close" button in Paiterro, the page can scroll again.

Reproduced on Chrome for Android, Safari on iOS and in Device Mode on Desktop Chrome (Windows 10)

Autosave written on ChangeHandler event

I am trying to handle autosave feature on ChangeHandler but couldn't access the updated image.
Please suggest ,as i want to save image after each change

saveHandler: function (image, done ) {
        this.imageData = sketch.page1.imageData;
        formData.push('page1', image.asDataURL());
        sketch.page1.name = formData[0];
        sketch.page1.imageData = formData[1];
        db.put(sketch.pole, (err, result) => {
          if (!err) {
                     console.log("save Sucess");
          }
        });
               done(true);
      },
      changeHandler: function () {
        alert('test '+ this.imageData);
      },

[Feature Request] Adding Redo Button

Since we've now the Undo button would be great to have the Redo one too. It could be hidden by default if thats a button that most wouldnt like to have by default.

best regards

Issue with toolbar and dialogs not showing in Microsoft Edge

Hi,

I've been using the Painterro widget to implement an image annotator feature and it's excellent. However I've encountered a couple of problems trying to support Microsoft Edge. For some reason, the toolbar and colour picker dialogs don't immediately render, until the window is resized. You can see the issue here: https://jsfiddle.net/DaveSmith/d26738t6/ - it works fine in all other browsers but if you use Edge you can see the problem.

I also noticed that your demo page: maketips.net/paste works fine in all browser including Edge, so I was trying to see what it does differently, but so far I haven't been able to make it work and I was just wondering if this was an issue you had seen before?

Any help appreciated!
Many thanks
Dave Smith

Touch Interface

Hi,
I tried Painterro on an iPad and an Android tablet and it doesn't work. Can't draw, crop or do anything useful. Any plans for adding touch capability?
Thanks, S

initText

HI,

Can i make this initText to remain on the top even after painting???

How i can add callback to Undo and Redo events?

Hi, i want use this project for made collaborating painting on web page,
I want for this understand how i can add callback to Undo and Redo events, and how i can drawing to the canvas from js code.

Save to local or send by email

Thx for this lovely script !
Would be great to have the possibility to save the canvas local or to send it by email ?
thx for your great work !

[Bug] Issue when uploading image in IE/Edge

There is a bug on IE and Edge when trying upload an image. After selecting the image from the explorer it won't display into the canvas. The upload only works if you try it several times.
I have seen this issue on both v.0.2.67 and v.0.2.68.
This also happens when using the paste command, though it works ok when you drag and drop an image into the canvas.
Thank you.

translation parameter

Hi Ivan,

I was trying to use the translation parameter to alter a couple of the tool's tooltips, but I get the following runtime error when I attempt to use it.

Uncaught TypeError: Cannot read property 'get' of undefined

I'm not sure, but I think it might be the way Translation is imported at the top of params.js. Changing it to import { Translation } from './translation'; seemed to fix it for me, but I'm not familiar with how the import stuff works.

Thanks

Sean

Getting CORS policy error

Is there is any way to set Access-Control-Allow-Origin for my domain because I am getting error "has been blocked by CORS policy: No 'Access-Control-Allow-Origin'". Thanks Paritosh

Open painterro with existing image

Hi,

Sorry if this question is obvious, I cannot see how to do this from the document.

Can painterro .show() with existing image e.g. image data from API?

build/painterro.js not found

I have done npm build as per the documentation but painterro.js is not getting generated, also tried in different development environments.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.