Code Monkey home page Code Monkey logo

ng2-canvas-whiteboard's Introduction

ng2-canvas-whiteboard

Canvas version changes

v5.0.0 merges PR to add Angular15 support

#110

v4.0.2 merges PR to add variables for fillColorPickerText and strokeColorPickerText

#68

v3.1.3, v4.0.1

Exports all existing canvas shapes, so that they can be easily unregistered from the canvas. (see README for unregistering the shapes).

Also, this version introduces two new Inputs, strokeColorPickerEnabled: boolean and fillColorPickerEnabled: boolean, also deprecates the colorPickerEnabled Input.

For the sake of reverse-compat, the colorPickerEnabled input is still there and it will be used in combination with the two new variables. (ex: colorPickerEnabled || fillColorPickerEnabled).

v3.1.1 Audits the npm packages and upgrades the lodash version from 4.17.11 to 4.17.13

v3.1.0 Merges the pull request from #55 to allow the component to be used in Angular 8 and 9 applications. Also fixes the imports for rxjs items from 'rxjs/index' to 'rxjs'

v3.0.4 Fixes a bug with production build and recognition of shape names by adding an abstract method in the base Shape class.

v3.0.0 Removes the rxjs-compat library and adds rxjs^6. This means that older versions will not be supported if they upgrade to ng2-canvas-whiteboard^3.0.0.

This version also changes the way of how this library is built and made ready for publish.

For applications before Angular 6 please use versions below v3.0.0.

Features:

  • Premade Shapes
  • The ability to create custom premade shapes
  • Supports touch.
  • Supports UNDO/REDO.
  • Implements a color picker for stroke and fill colors.
  • Sends outputs on every action.
  • Contains inputs for multiple modifications.
  • Save drawn images

Install

  1. Install npm module:

    npm install ng2-canvas-whiteboard --save
  2. If you are using system.js you may want to add this into map and package config:

    {
        "map": {
            "ng2-canvas-whiteboard": "node_modules/ng2-canvas-whiteboard"
        },
        "packages": {
            "ng2-canvas-whiteboard": { "main": "index.js", "defaultExtension": "js" }
        }
    }

Add the module to your project

@NgModule({
    imports: [
        CanvasWhiteboardModule
    ]
    ...
)}

In your component, you should add the CanvasWhiteboardComponent as a view provider

@Component({
    selector: '...',
    viewProviders: [CanvasWhiteboardComponent],
    templateUrl: '...'
})

In the html file, you can insert the Canvas Whiteboard

<canvas-whiteboard #canvasWhiteboard
                     [drawButtonClass]="'drawButtonClass'"
                     [drawButtonText]="'Draw'"
                     [clearButtonClass]="'clearButtonClass'"
                     [clearButtonText]="'Clear'"
                     [undoButtonText]="'Undo'"
                     [undoButtonEnabled]="true"
                     [redoButtonText]="'Redo'"
                     [redoButtonEnabled]="true"
                     [colorPickerEnabled]="true"
                     [fillColorPickerText]="'Fill'"
                     [strokeColorPickerText]="'Stroke'"
                     [saveDataButtonEnabled]="true"
                     [saveDataButtonText]="'Save'"
                     [lineWidth]="5"
                     [strokeColor]="'rgb(0,0,0)'"
                     [shouldDownloadDrawing]="true"
                     (onBatchUpdate)="sendBatchUpdate($event)"
                     (onClear)="onCanvasClear()"
                     (onUndo)="onCanvasUndo($event)"
                     (onRedo)="onCanvasRedo($event)">
</canvas-whiteboard>

If there is too much overhead with inputs, you can just specify the [options] input, and specify the options from the typescript code

Example:

<canvas-whiteboard #canvasWhiteboard
                   [options]="canvasOptions"
                   (onBatchUpdate)="onCanvasDraw($event)"
                   (onClear)="onCanvasClear()"
                   (onUndo)="onCanvasUndo($event)"
                   (onRedo)="onCanvasRedo($event)">
</canvas-whiteboard>

Code:

  canvasOptions: CanvasWhiteboardOptions = {
    drawButtonEnabled: true,
    drawButtonClass: "drawButtonClass",
    drawButtonText: "Draw",
    clearButtonEnabled: true,
    clearButtonClass: "clearButtonClass",
    clearButtonText: "Clear",
    undoButtonText: "Undo",
    undoButtonEnabled: true,
    redoButtonText: "Redo",
    redoButtonEnabled: true,
    colorPickerEnabled: true,
    fillColorPickerText: "Fill",
    strokeColorPickerText: "Stroke",
    saveDataButtonEnabled: true,
    saveDataButtonText: "Save",
    lineWidth: 5,
    strokeColor: "rgb(0,0,0)",
    shouldDownloadDrawing: true
  };

Drawing on the canvas

The canvas drawing is triggered when the user touches the canvas, draws (moves the mouse or finger) and then stops drawing. When the drawing is started, after 100 ms all the signals in between are added to a list and are sent as a batch signal which is emitted by the onBatchUpdate emitter. If received, the user can then manipulate with the sent signals.

Inputs

batchUpdateTimeoutDuration: number (default: 100)

The time in milliseconds that a batch update should be sent after drawing.

imageUrl: string (optional)

The path to the image. If not specified, the drawings will be placed on the background color of the canvas. This path can either be a base64 string or an actual path to a resource

aspectRatio: number (optional)

If specified, the canvas will be resized according to this ratio

drawButtonClass: string
clearButtonClass: string
undoButtonClass: string
redoButtonClass: string
saveDataButtonClass: string

The classes of the draw, clear, undo and redo buttons. These classes are used in "<i>" tags.
Example:

[drawButtonClass]="'fa fa-pencil fa-2x'"
[clearButtonClass]="'fa fa-eraser fa-2x canvas_whiteboard_button-clear'"
drawButtonEnabled: boolean (default: true)
clearButtonEnabled: boolean (default: true)
undoButtonEnabled: boolean (default: false)
redoButtonEnabled: boolean (default: false)
saveDataButtonEnabled: boolean (default: false)

Specifies whether or not the button for drawing or clearing the canvas should be shown.

drawButtonText, clearButtonText, undoButtonText, redoButtonText, saveDataButtonText

Specify the text to add to the buttons, default is no text

[drawButtonText]="'Draw'"
[clearButtonText]="'Clear'"

##Use the options: CanvasWhiteboardOptions to send the inputs Changes to this object will be detected by the canvas in the OnChange listener and will be changed accordingly

  //Component
  canvasOptions: CanvasWhiteboardOptions = {
      drawButtonEnabled: true,
      drawButtonClass: 'drawButtonClass',
      drawButtonText: 'Draw',
      clearButtonEnabled: true,
      clearButtonClass: 'clearButtonClass',
      clearButtonText: 'Clear',
      undoButtonText: 'Undo',
      undoButtonEnabled: true,
      redoButtonText: 'Redo',
      redoButtonEnabled: true,
      colorPickerEnabled: true,
      saveDataButtonEnabled: true,
      saveDataButtonText: 'Save',
      lineWidth: 4,
      scaleFactor: 1
  };

   //View
  <canvas-whiteboard #canvasWhiteboard
                       [options]="canvasOptions"
                       (onBatchUpdate)="onCanvasDraw($event)"
                       (onClear)="onCanvasClear()"
                       (onUndo)="onCanvasUndo($event)"
                       (onRedo)="onCanvasRedo($event)"
                       (onSave)="onCanvasSave($event)">
  </canvas-whiteboard>

NOTE: In order for the changeDetection to pick up the options changes, you must change the options reference whenever you want to change a value. Example:

  public changeOptions(): void {
    this.canvasOptions = {
      ...this.canvasOptions,
      fillColorPickerEnabled: true,
      colorPickerEnabled: false
    };
  }

To add text to the buttons via css

Each button has its on class (example: Draw button -> .canvas_whiteboard_button-draw)
This button can be customized by overriding its css

.canvas_whiteboard_button-draw:before {
  content: "Draw";
}

will add the "Draw" text to the button.

If using component-only styles, for this to work the viewEncapsulation must be set to None.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  encapsulation: ViewEncapsulation.None
})

You can also use the ::ng-deep selector if you do not want to change the ViewEncapsulation property on the component.

Deprecated: colorPickerEnabled: boolean (default: false)

This allows the adding of a colorPickers that the user can choose to draw with (stroke and fill color), and the original colors will be used when redrawing

fillColorPickerEnabled: boolean (default: false)

This shows/hides the fill color picker. Note: if this field has been to false, but the colorPickerEnabled field has been to true, the color picker will be shown, as per reverse-compat needs.

fillColorPickerText: string (default: 'Fill')

Specify the text to add to the fill color picker button. Default is 'Fill' for reverse-compat needs.

strokeColorPickerEnabled: boolean (default: false)

This shows/hides the stroke color picker. Note: if this field has been to false, but the colorPickerEnabled field has been set to true, the color picker will be shown, as per reverse-compat needs.

strokeColorPickerText: string (default: 'Stroke')

Specify the text to add to the stroke color picker button. Default is 'Stroke' for reverse-compat needs.

lineWidth: number (default: 2)

This input controls the drawing pencil size

strokeColor: string (default: "rgba(0, 0, 0, 1)")

This input control the color of the brush

fillColor: string (default: "rgba(0, 0, 0, 0) -> transparent")

This input control the background color of the shapes

shouldDownloadDrawing: boolean (default: true)

This input control if the image created when clicking the save button should be downloaded right away.

startingColor: string (default: "#fff")

This input control is used to fill the canvas with the specified color at initialization and on resize events.

scaleFactor: number (default: 0)

This input controls the generation of the X and Y coordinates with a given scaleOffset. If not provided, the current with and height of the bounding rect and the canvas object will be used so that it works when transforming the canvas with css.

drawingEnabled: boolean (default: false)

This input controls if the drawing should be enabled from the start, instead of waiting for the user to click draw

showStrokeColorPicker: boolean (default: false)

This input controls if the CanvasWhiteboardColorPickerComponent for the strokeColor should be shown programmatically

showFillColorPicker: boolean (default: false)

This input controls if the CanvasWhiteboardColorPickerComponent for the fillColor should be shown programmatically

downloadedFileName: string (no default value)

This input controls the name of the file that will be downloaded when an image is saved. If the downloadCanvasImage method is called with a fileName as a third parameter, then it will have priority over everything If the fileName is not provided, then this Input will have priority. If this input is not provided as well, the image will be saved as canvas_drawing_" + new Date().valueOf(); At the end the file extension will be added so that it can be opened by a particular app.

lineJoin: string (default: "round")

The lineJoin property sets or returns the type of corner created, when two lines meet.

lineCap: string (default: "round")

The lineCap property sets or returns the style of the end caps for a line.

shapeSelectorEnabled: boolean (default: true)

This input controls if the CanvasWhiteboardShapeSelectorComponent will be enabled so that the user can pick other shapes via the View

showShapeSelector: boolean (default: false)

This input controls if the CanvasWhiteboardShapeSelectorComponent should be shown programmatically

Event emitters

 @Output() onClear = new EventEmitter<any>();
 @Output() onBatchUpdate = new EventEmitter<CanvasWhiteboardUpdate[]>();
 @Output() onImageLoaded = new EventEmitter<any>();
 @Output() onUndo = new EventEmitter<any>();
 @Output() onRedo = new EventEmitter<any>();
 @Output() onSave = new EventEmitter<string | Blob>();

onClear is emitted when the canvas has been cleared.
onImageLoaded is emitted if the user specified an image and it has successfully been drawn on the canvas. onUndo is emitted when the canvas has done an UNDO function, emits an UUID (string) for the continuous last drawn shape undone.
onClear is emitted when the canvas has done a REDO function, emits an UUID (string) for the continuous shape redrawn.
onSave is emitted when the canvas has done a SAVE function, emits a Data URL or a Blob (IE).

Canvas Whiteboard Shapes

Every shape in the application extends the abstract class CanvasWhiteboardShape. This class adds predefined methods so that the creator of the shape can follow them and decide how his shape should be drawn.

Each shape is made of a starting position point of type CanvasWhiteboardPoint, and an options object which may be different for each shape, and it's of type CanvasWhiteboardShapeOptions.

Each predefined shape must know how to:

  • Return the name of the shape (should be the same as the name of the class)
  • Draw itself given a canvas context
  • Draw it's preview given a canvas context
  • Update itself given a CanvasWhiteboardUpdate

All of the predefined shapes are registered and available in the CanvasWhiteboardShapeService which the user can have to register/unregister additional shapes.

To create a new shape, you must create a class which extends the abstract class CanvasWhiteboardShape .

From there you need to implement the required methods.

After all of this is complete, you need to register this shape in the canvas whiteboard shape service (for the sake of convention).

class AppComponent {
     constructor(private _canvasWhiteboardService: CanvasWhiteboardService, private _canvasWhiteboardShapeService: CanvasWhiteboardShapeService) {
            _canvasWhiteboardShapeService.registerShape(RandomShape);
     }
}

export class RandomShape extends CanvasWhiteboardShape {
    linePositions: Array<number>;

    constructor(positionPoint?: CanvasWhiteboardPoint, options?: CanvasWhiteboardShapeOptions) {
        // Optional constructor if you need some additional setup
        super(positionPoint, options);
        this.linePositions = [];
    }

    getShapeName(): string {
        // Abstract method which should return a string with the shape name
        // Should be the same as the class name
        return 'RandomShape';
    }

    draw(context: CanvasRenderingContext2D): any {
        // Tell the canvas how to draw your shape here

        // Use the selected options from the canvas whiteboard
        // Object.assign(context, this.options);

        // Start drawing
        // context.save();
        // context.beginPath();
        // context.stroke();
        // context.fill();
        // context.closePath();
        // context.restore();
    }

    drawPreview(context: CanvasRenderingContext2D): any {
        // Provide info or update this object when it's needed for preview drawing.
        // Example: The CIRCLE selects the center point and updates the radius.
        // Example: The RECT selects 0,0 and updates width and height to 100%.

        // Then call the draw method with the updated object if you want your shape
        // to have a proper preview.

        // this.draw(context);
    }

    onUpdateReceived(update: CanvasWhiteboardUpdate): any {
        // Choose what your shape does when an update is registered for it
        // For example the CircleShape updates it's radius
    }

    onStopReceived(update: CanvasWhiteboardUpdate): void {
        // This method is optional but CAN be overriden
    }
}

Unregistering Shapes

The default shapes can also be unregistered. Example:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private canvasWhiteboardShapeService: CanvasWhiteboardShapeService) {
    this.canvasWhiteboardShapeService.unregisterShapes([CircleShape, SmileyShape, StarShape]);
  }
}

NOTE: There must be at least one shape registered for the canvas to work, but for the sake of convenience, all of the default shapes have been exported (maybe someone would want to unregister all of them and register his own shapes), but it is recommended not to unregister the FreeHandShape.

Canvas Whiteboard Shape Selector

The CanvasWhiteboardComponent is now equipped with a shape selector (since the free hand drawing is now a shape because of consistency), The shape selector can be managed or hidden with inputs, and it basically calls the CanvasWhiteboardShapeService and draws all the registered shapes so that they can be selected. They are drawn with the selected fill/stroke color for preview.

CanvasWhiteboard shape preview

Canvas Whiteboard Service

The CanvasWhiteboardService will be used by the canvas to listen to outside events. The event emitters and ViewChild functionality will remain the same but with this service we can notify the canvas when it should invoke a specific action

Example:

export class AppComponent {
  constructor(private _canvasWhiteboardService: CanvasWhiteboardService) {}
 
  public receiveNewMessage(newMessage: any): void {
     switch (newMessage.type) {
       case VCDataMessageType.canvas_draw:
         let updates = newMessage.data.map(updateJSON => CanvasWhiteboardUpdate.deserializeJson(JSON.parse(updateJSON)));
         this._canvasWhiteboardService.drawCanvas(updates);
         break;
       case VCDataMessageType.canvas_clear:
         this._canvasWhiteboardService.clearCanvas();
         break;
       case VCDataMessageType.canvas_undo:
         this._canvasWhiteboardService.undoCanvas(newMessage.UUID);
         break;
       case VCDataMessageType.canvas_redo:
         this._canvasWhiteboardService.redoCanvas(newMessage.UUID);
         break;
     }
  }
}   

Requesting the full update history so far

Can be called via the method getDrawingHistory(): CanvasWhiteboardUpdate[]. The items will be deep cloned for consistency using lodash.

Saving drawn canvas as an image

In order to save drawn images you can either click the Save button in the canvas, use the short Ctrl/Command + s key or get a reference of the canvas and save programmatically.

Example, save an image whenever an undo action was made:

HTML: Create a canvas view reference with some name (ex: #canvasWhiteboard)

<canvas-whiteboard #canvasWhiteboard>
</canvas-whiteboard>
import {CanvasWhiteboardComponent} from 'ng2-canvas-whiteboard';

export class AppComponent {

  @ViewChild('canvasWhiteboard') canvasWhiteboard: CanvasWhiteboardComponent;

  onCanvasUndo(updateUUID: string) {
    console.log(`UNDO with uuid: ${updateUUID}`);
    
    //Returns base64 string representation of the canvas
    let generatedString = this.canvasWhiteboard.generateCanvasDataUrl("image/jpeg", 0.3);
     
    //Generates a IE canvas blob using a callbak method
    this.canvasWhiteboard.generateCanvasBlob((blob: any) => {
       console.log(blob);
    }, "image/png");
    
    //This method uses both of the above method and returns either string or blob
    //using a callback method
    this.canvasWhiteboard.generateCanvasData((generatedData: string | Blob) => {
        console.log(generatedData);
    }, "image/png", 1);
    
    //This method downloads the image using either existing data if it exists
    //or creates it locally
    this.canvasWhiteboard.downloadCanvasImage("image/png", existingData?, "customFileName");
    
    //If you need the context of the canvas
    let context = this.canvasWhiteboard.context;
  }
}

Image of canvas

CanvasWhiteboard

Canvas whiteboard color picker (CanvasWhiteboardColorPickerComponent)

A canvas component that is used to identify and emit selected colors.

@Input() selectedColor: string (default: "rgb(0,0,0)");
@Output() onColorSelected = new EventEmitter<string>();

CanvasWhiteboardColorpicker

Example of a drawn image

An example of a drawn image and shape on the canvas with additional css for the buttons and a date:

Image in CanvasWhiteboard

Example of a full fledged WebRTC app which shares drawing signals

Image in FulFledged WebRTC App

Current limitations

  • If there are problems with the sizing of the parent container, the canvas size will not be the wanted size. It may sometimes be width: 0, height: 0. If this is the case you may want to call a resize event for the window for the size to be recalculated.
    if (this.isCanvasOpened) {
      setTimeout(() => {
        window.dispatchEvent(new Event('resize'));
      }, 1);
    }

ng2-canvas-whiteboard's People

Contributors

goran234 avatar leonardortlima avatar matejkramny avatar peshou avatar tpanev 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

Watchers

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

ng2-canvas-whiteboard's Issues

No onSave event emitter

Awesome code - Reading through the documentation - there doesn't seem to be an output event for when the save button is pressed - should one be added?

In the example they attach the saving technique to the undo event but this probably isnt the best place to do this.

Able to Draw at Chrome but not able to draw at IE

Hi,
I have created a bootstrap modal window and used ng2-canvas whiteboard. Here I am able to draw at chrome, but I could not able to draw at IE. Could you please help me out how to resolve my issue..

make color transparent

Hi, I am using ng2-canvas-whiteboard for painting on an image however If I paint it then I can not see the image. Actually what I want to do is to make the color transparent.

I tried to add opacity in your createColorPalette function.. however it is not working as intended.
I tried to edit this function

CanvasWhiteboardColorPickerComponent.prototype.createColorPalette = function() { var gradient = this._context.createLinearGradient(0, 0, this._context.canvas.width, 0); gradient.addColorStop(0.6, "rgb(255,0,0 , 0.3)"); gradient.addColorStop(0.15, "rgb(255,0,255, 0.3)"); gradient.addColorStop(0.33, "rgb(0, 0, 255, 0.3)"); gradient.addColorStop(0.49, "rgb(0, 255, 255, 0.3)"); gradient.addColorStop(0.67, "rgb(0, 255, 0, 0.3)"); gradient.addColorStop(0.84, "rgb(255, 255, 0, 0.3)"); gradient.addColorStop(1, "rgb(255, 0, 0, 0.3)"); this._context.fillStyle = gradient; this._context.fillRect(0, 0, this._context.canvas.width, this._context.canvas.height); gradient = this._context.createLinearGradient(0, 0, 0, this._context.canvas.height); gradient.addColorStop(0, "rgba(255, 255, 255, 1, 0.3)"); gradient.addColorStop(0.5, "rgba(255, 255, 255, 0, 0.3)"); gradient.addColorStop(0.5, "rgba(0, 0, 0, 0, 0.3)"); gradient.addColorStop(1, "rgba(0, 0, 0, 1, 0.3)"); this._context.fillStyle = gradient; this._context.fillRect(0, 0, this._context.canvas.width, this._context.canvas.height); };

can you please tell me how can I achieve that?

Not working in Angular 9

Hello,

I have updated my project to Angular 9 and this package to the latest version (3.0.4 at this time).
After including the module in my AppModule imports, adding the CanvasWhiteboardComponent to the viewProviders and including the code below I got an error.

<canvas-whiteboard
    #canvasWhiteboard
    [drawButtonClass]="'drawButtonClass'"
    [drawButtonText]="'Draw'"
    [clearButtonClass]="'clearButtonClass'"
    [clearButtonText]="'Clear'"
    [undoButtonText]="'Undo'"
    [undoButtonEnabled]="true"
    [redoButtonText]="'Redo'"
    [redoButtonEnabled]="true"
    [colorPickerEnabled]="true"
    [saveDataButtonEnabled]="true"
    [saveDataButtonText]="'Save'"
    [lineWidth]="5"
    [strokeColor]="'rgb(0,0,0)'"
    [shouldDownloadDrawing]="true"
    (onBatchUpdate)="sendBatchUpdate($event)"
    (onClear)="onCanvasClear()">
</canvas-whiteboard>

The error I get when this initializes:
Schermafbeelding 2020-02-13 om 11 28 18

ERROR using Angular 7

Hi, I use Angular CLI: 7.0.1 and Angular: 7.0.0.

When executing: ng serve -o

ERROR in src / .... module.ts (9,40): error TS2307: Cannot find module 'ng2-canvas-whiteboard/index'.

Please help.

Shapes not work after Production Compile

Works all fine in Dev Mode
But in Production Mode, Shapes are Selectable but still draw in strokes mode.

-> ng build --base-href=/ --prod --aot --build-optimizer --vendor-chunk=false --optimization

Error while using with Angular 6

Module not found: Error: Can't resolve 'rxjs/Subject' in '\node_modules\ng2-canvas-whiteboard\dist'.

Please help.

@angular/cli": "~6.0.5"

How to save draw pattern and How to retain to same image

Hi,

I am using this canvas for my uploaded image. I can draw different pattern using ng2-canvas-whiteboard. But my doubt is how can i save the draw pattern. And how can i retain the drawn pattern to image using mysql or mongodb. What value i need to save for drawn pattern

Please help!!

ImageUrl not working with base64

I want to be able to set the imageUrl to a base64 String, but I am only getting

compiler.js:7275 Uncaught Error: Quotes are not supported for evaluation!

Custom font not applied before clearing the canvas

Hi,
I'm facing a weird issue, not sure if it concerns the package or not, but i'm stating it anyway, i'm using the canvas context to fill the canvas with some text after it loads, with a custom font, on Firefox it works perfectly as i want it, but on Chrome / Opera it load with default fault (Arial i guess) and after i click on the Clear button (I made it rewrite the text on the Onclear event) it loads with the correct font, here are my codes :
` ngAfterViewInit() {
setTimeout(() => {
this.canvas.changeColor("#000000");
this.context = this.canvas.context;
this.onCanvasClear();
}, 250);

} onCanvasClear() {
this.drawPaperFormat();
} drawPaperFormat() {
this.context.lineWidth = 1;
this.context.strokeStyle = "gray";
for (var i = 0; i <= 1000; i += 10) {
this.context.moveTo(i, 0);
this.context.lineTo(i, 1000);
this.context.moveTo(0, i);
this.context.lineTo(1000, i);
}
this.context.stroke();
this.context.font = "100px Arabic-Dots";
this.context.fillText(this.canvasRef.nativeElement.getAttribute("content"), 100, 100);
}`

Any ideas ?
I have another issue, not sure if i should create another ticket or not, but when i resize the browser the grids i draw using the DrawPaperFormat() are cleared and so is the contents, i added an angular listener to the resize event and have the drawPaperFormat() executed when the window resize, but it doesn't, any idea ? Thank you in advance

Uploading img results in cropping much of it out.

I'm trying to use this lib for changing imgs.

Yet when i update the imageUrl
this.canvasOptions.imageUrl = base64imgUrl;

it "zooms in" and crop out most of the image inside the canvas.
even with aspectRatio: 1 in options.

am i doing something wrong here?

Code.

init
ngOnInit() { setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 1); this.imageUrl(this.incImageUrl); }

Options
canvasOptions: CanvasWhiteboardOptions = { drawButtonEnabled: false, drawButtonClass: 'drawButtonClass', drawButtonText: 'Drawing', drawingEnabled: true, clearButtonEnabled: true, clearButtonClass: 'clearButtonClass', clearButtonText: 'Clear', undoButtonText: 'Undo', undoButtonEnabled: true, redoButtonText: 'Redo', redoButtonEnabled: true, colorPickerEnabled: true, saveDataButtonEnabled: true, saveDataButtonText: 'Save', lineWidth: 5, strokeColor: 'rgb(0,0,0)', shouldDownloadDrawing: true, imageUrl: '', aspectRatio: 1 };

ImageUrl func.
imageUrl(base64imgUrl) { this.canvasOptions.imageUrl = base64imgUrl; }

ERROR in Unexpected value 'CanvasWhiteboardModule. Please add a @NgModule annotation.

Hi,
I added 'CanvasWhiteboardModule' in app.module.ts. And canvas is used in one of my component. But when use

ng serve --aot

I am getting following error.

ERROR in Unexpected value 'CanvasWhiteboardModule in C:/projectfFolder/node_modules/ng2-canvas-whiteboard/dist/ng2-canvas-whiteboard.d.ts' imported by the module 'AppModule in C:/projectfFolder/src/app/app.module.ts'. Please add a @NgModule annotation.

i domt why i am getting this error. Please suggest

Question: Exposing _updateHistory?

Hi,

First of all great works.

Secondly I have a question: my use case requires me to save the drawings as a list of history as oppose to an image or a blob. Do you think its an acceptable idea to expost _updateHistory in canvas-whiteboard.component?

Thanks!

Support for scaled whiteboard

Hi @Peshou and community,

first of all, I would like to thank you for this package. I am considering using this package in my project. Great work so far.

However, when using the package, I stumbled upon an issue, as I am using whiteboard with css transform: scale(...):

The problem is as follows: If you scale the whiteboard (or an HTML element that surrounds it) by applying transform: scale(...) the line is not drawn at the correct position. This is, because the mouse position is absolute. But the lines are drawn on the image with the original size first and then the whole canvas is scaled (e.g., if you want to draw on 50/50 but you scale it down by 0.5, you should draw at 100/100).

Maybe you could add a scaleFactor that allows for this feature?

The solution that worked for me is as follows:

let xPos;
let yPos;
if (event) {
    // FireFox
    xPos = event.pageX;
    yPos = event.pageY;
} else {
    // IE
    const windowEvent = window.event as any;
    xPos = windowEvent.x + document.body.scrollLeft - 2;
    yPos = windowEvent.y + document.body.scrollTop - 2;
}

// Set position relative to canvas' top and left offset
const boundingRect = this._canvas.getBoundingClientRect();
xPos -= boundingRect.left;
yPos -= boundingRect.top;

// Reset scale made from css transform-scale, to get mouse position relative to actual canvas size
const scaleWidth = boundingRect.width / this._canvas.width;
const scaleHeight = boundingRect.height / this._canvas.height;
xPos /= scaleWidth;
yPos /= scaleHeight;

return {
    x: xPos,
    y: yPos
}

The important part would be:

// Reset scale made from css transform-scale, to get mouse position relative to actual canvas size
const scaleWidth = boundingRect.width / this._canvas.width;
const scaleHeight = boundingRect.height / this._canvas.height;
xPos /= scaleWidth;
yPos /= scaleHeight;

Whereas, this._canvas is the actual CanvasHTMLElement.

If you use the mentioned solution with the Input() scaleFactor, you can probably replace scaleWidth and scaleHeight with this scaleFactor. I guess the factors for width and height should be equal anyway, otherwise the content may be streched.

If Iโ€™m understanding your code correctly the changes would be in the method _getCanvasEventPosition in the file canvas-whiteboard.component.ts.

Thank you in advance for your time and effort,
Cheers

Transparent canvas

It would be nice if we have input param for leaving the canvas background transparent instead of setting default color.

I can't unregister the shape from the service.

Hi!
I am trying to unregister FreeHandShape, LineShape, SmileyShape, StarShape in the service:

draw.component.ts

import { Component, OnInit } from '@angular/core';
import { 
  CanvasWhiteboardComponent, CanvasWhiteboardOptions, 
  CanvasWhiteboardService, CanvasWhiteboardShapeService, 
  CircleShape, FreeHandShape, LineShape, RectangleShape, SmileyShape, StarShape
} from 'ng2-canvas-whiteboard';

@Component({ ... })
export class DrawComponent implements OnInit {

  private canvasOptions: CanvasWhiteboardOptions;

  constructor(private _canvasWhiteboardService: CanvasWhiteboardService, private _canvasWhiteboardShapeService: CanvasWhiteboardShapeService) { 
    _canvasWhiteboardShapeService.unregisterShapes([CircleShape, FreeHandShape, LineShape, RectangleShape, SmileyShape, StarShape]);
  }

  ngOnInit() {
    this.canvasOptions = { ... };
  }

CircleShape and RectangleShape unregistered successfully.
For the rest I get an error:

"export 'FreeHandShape' was not found in 'ng2-canvas-whiteboard'
"export 'LineShape' was not found in 'ng2-canvas-whiteboard'
"export 'SmileyShape' was not found in 'ng2-canvas-whiteboard'
"export 'StarShape' was not found in 'ng2-canvas-whiteboard'

There is no export of these shapes in the ng2-canvas-whiteboard.ts. Maybe this is the reason?

Here is my repository: https://github.com/oduvanka/test-draw/tree/unregister-error

Draw button disabled but drawing enabled

Hi,
there is a way to go in canvas without draw button enabled but drawing enabled. So the user doesn't must click the draw button to start the draw.

Thanks in advance.

Load Saved "CanvasDataUrl"

Hi

I am using version 2.0.2.

Is it possible to "re-load" a saved CanvasDataUrl (received using generateCanvasDataUrl()) at a later point?

Or more specific: when the user presses the save-button, we store the CanvasDataUrl. At a later point it should be possible to come back to this drawing and edit it further (it is not needed to undo steps done before the saving).
Is this currently possible to achieve?

Thanks,
Stefan

Use RxJS6 as main RxJS lib instead of needing to download rxjs-compat library

Dear @Peshou ,

is it possible to use rxjs 6 instead of rxjs 5 for this package? Currently, if you want to use rxjs 6 you will need to add the compat lib.. Wouldn't it be better to use rxjs 6 as default and use a compat in case someone needs to use it with rxjs 5 instead? because sooner or later one will need to switch to rxjs 6.

what do you think on this?

All the best and cheers,

Possibility to style color pickers

Good morning,

Thanks a lot for for your great project. We implemented your ng2-canvas-whiteboard into our application and everythings works fine, but we would appreciate to have some additional styling options.

Unfortunately, we cannot control the color pickers. We would like to change their text or use icons for them. The options object does not have attributes for that.

Moreover, we would like to have the possibility that the color-pickers are not shown. For example, when we set the "shapeSelectorEnabled" attribute to false in order to achieve that the consumer can only use lines then the "Fill" color-picker should not be displayed.

Do you intent to include such features?

Support text

Are you planning to add text drawing support?

_loadImage() to public

Would be nice to have a possibility to load image after the canvas is initialized. One of these options would be good to have:

  1. canvasWhiteboardComp.imageUrl = image;
    canvasWhiteboardComp.loadImage();
    
  2. or simply
    canvasWhiteboardComp.loadImage(image);

Feature request: key-in content.

In many simple image editors, there is a feature of typing content/letterd.

Is this in the scope of this component in near future?

Clear and undo do not work after loading a saved "CanvasDataUrl"

This is a follow-up to issue 29. It appears that any time an image is loaded into the canvas from the base64 encoding, the Clear, Undo, (and presumably Redo) buttons no longer work. Obviously it should not clear any old work, but when the canvas with the image is loaded, then a new line or shape is drawn onto the canvas, pressing Clear or Undo should remove that new line or shape. Currently, nothing happens (I don't see any errors, but the last action is not removed).

Insecure operation when imageUrl is from another server

Saving the canvas image works fine when there is no imageUrl, but I need to use an image from another server on our network. When trying to save the canvas, I get a DOMException: "The operation is insecure."

The error is to be expected because the image taints the canvas, and it isn't secure to just save it.

It looks like the solution involves something along these lines (taken from here)

function startDownload() {
  let imageURL = "https://cdn.glitch.com/4c9ebeb9-8b9a-4adc-ad0a-238d9ae00bb5%2Fmdn_logo-only_color.svg?1535749917189";
 
  downloadedImg = new Image;
  downloadedImg.crossOrigin = "Anonymous";
  downloadedImg.addEventListener("load", imageReceived, false);
  downloadedImg.src = imageURL;
}

Is there something like this already that I am missing, or is this a feature request to provide an option to do this?

Image Object-Fit

Hi,
it seems that the canvas use the object-fit: cover to show the image. There is a way to use the object-fit: contain?

Thanks in advance.

Need to load the image inside canvas without chopping off

Hi team,

The library was very nice. But I see that the original image was chopped off on top and bottom.

I mean that the image width was completely fine but it was not covering the all content when it comes to height. Some of the contents on top and bottom of the image was deleted when it was on edit mode.

Please fix it OR let me know if there's any option to load it completely.

Optimize stroke speed

Good morning.

The implementation has been a success. Thank you for your contribution.
But we were presented with an inconvenience when we loaded the application by means of table.
We experience undefined strokes when taking a signature.
This also happens in PC but when we write fast with the mouse.

How can I optimize the writing stroke?

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.