UNPKG

@drizm/ng-whiteboard

Version:

A Canvas component for Angular which supports free drawing.

407 lines (406 loc) 19.2 kB
import { EventEmitter, ElementRef, OnInit, OnChanges, OnDestroy, AfterViewInit, NgZone, ChangeDetectorRef, TemplateRef } from '@angular/core'; import { CanvasWhiteboardUpdate } from './_classes/canvas-whiteboard-update.model'; import { CanvasWhiteboardService } from './_services/canvas-whiteboard.service'; import { CanvasWhiteboardOptions } from './_types/canvas-whiteboard-options'; import { CanvasWhiteboardShape } from './_classes/shape/canvas-whiteboard-shape'; import { CanvasWhiteboardShapeService, INewCanvasWhiteboardShape } from './_services/canvas-whiteboard-shape.service'; import { CanvasWhiteboardShapeOptions } from './_classes/shape/canvas-whiteboard-shape-options'; export declare class CanvasWhiteboardComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy { private ngZone; private changeDetectorRef; private canvasWhiteboardService; private canvasWhiteboardShapeService; options?: CanvasWhiteboardOptions; batchUpdateTimeoutDuration: number; private _imageUrl?; set imageUrl(imageUrl: string | undefined); get imageUrl(): string | undefined; customWhiteboardUi?: TemplateRef<any>; aspectRatio?: number; drawButtonClass?: string; clearButtonClass?: string; eraseButtonClass?: string; undoButtonClass?: string; redoButtonClass?: string; saveDataButtonClass?: string; drawButtonText: string; clearButtonText: string; eraseButtonText: string; undoButtonText: string; redoButtonText: string; saveDataButtonText: string; strokeColorPickerText: string; fillColorPickerText: string; drawButtonEnabled: boolean; clearButtonEnabled: boolean; eraseButtonEnabled: boolean; undoButtonEnabled: boolean; redoButtonEnabled: boolean; saveDataButtonEnabled: boolean; shouldDownloadDrawing: boolean; strokeColorPickerEnabled: boolean; fillColorPickerEnabled: boolean; lineWidth: number; eraserLineWidth: number; strokeColor: string; startingColor: string; scaleFactor: number; drawingEnabled: boolean; set erasingEnabled(value: boolean); showStrokeColorPicker: boolean; showFillColorPicker: boolean; downloadedFileName?: string; lineJoin: string; lineCap: string; shapeSelectorEnabled: boolean; showShapeSelector: boolean; fillColor: string; clear: EventEmitter<any>; undo: EventEmitter<any>; redo: EventEmitter<any>; batchUpdate: EventEmitter<CanvasWhiteboardUpdate[]>; imageLoaded: EventEmitter<any>; save: EventEmitter<string | Blob>; canvas: ElementRef; context: CanvasRenderingContext2D; private _incompleteShapesCanvas; cachedStrokeColor: string; private _incompleteShapesCanvasContext; private _incompleteShapesMap; private _imageElement; private _canDraw; private _erasingEnabled; private _clientDragging; private _updateHistory; private _lastUUID?; private _shapesMap; private _undoStack; private _redoStack; private _batchUpdates; private _updatesNotDrawn; private _updateTimeout; private _canvasWhiteboardServiceSubscriptions; private _resizeSubscription; private _registeredShapesSubscription; selectedShapeConstructor?: INewCanvasWhiteboardShape<CanvasWhiteboardShape>; canvasWhiteboardShapePreviewOptions: CanvasWhiteboardShapeOptions; constructor(ngZone: NgZone, changeDetectorRef: ChangeDetectorRef, canvasWhiteboardService: CanvasWhiteboardService, canvasWhiteboardShapeService: CanvasWhiteboardShapeService); /** * Initialize the canvas drawing context. If we have an aspect ratio set up, the canvas will resize * according to the aspect ratio. */ ngOnInit(): void; /** * If an image exists and it's url changes, we need to redraw the new image on the canvas. */ ngOnChanges(changes: any): void; /** * Recalculate the width and height of the canvas after the view has been fully initialized */ ngAfterViewInit(): void; /** * Unsubscribe from the service observables */ ngOnDestroy(): void; /** * This method reads the options which are helpful since they can be really long when specified in HTML * This method is also called everytime the options object changes * For security reasons we must check each item on its own since if we iterate the keys * we may be injected with malicious values */ private _initInputsFromOptions; private _isNullOrUndefined; /** * Init global window listeners like resize and keydown */ private _initCanvasEventListeners; /** * Subscribes to new signals in the canvas whiteboard service and executes methods accordingly * Because of circular publishing and subscribing, the canvas methods do not use the service when * local actions are completed (Ex. clicking undo from the button inside this component) */ private _initCanvasServiceObservables; /** * Calculate the canvas width and height from it's parent container width and height (use aspect ratio if needed) */ private _calculateCanvasWidthAndHeight; /** * Load an image and draw it on the canvas (if an image exists) * @param callbackFn A function that is called after the image loading is finished * @return Emits a value when the image has been loaded. */ private _loadImage; /** * Sends a notification after clearing the canvas * This method should only be called from the clear button in this component since it will emit an clear event * If the client calls this method he may create a circular clear action which may cause danger. */ clearCanvasLocal(): void; /** * Clears all content on the canvas. */ clearCanvas(): void; /** * This method resets the state of the canvas and redraws it. * It calls a callback function after redrawing */ private _removeCanvasData; /** * Clears the canvas and redraws the image if the url exists. * @param callbackFn A function that is called after the background is redrawn * @return Emits a value when the clearing is finished */ private _redrawBackground; private _drawStartingColor; /** * Returns a value of whether the user clicked the draw button on the canvas. */ getDrawingEnabled(): boolean; /** * Toggles drawing on the canvas. It is called via the draw button on the canvas. */ toggleDrawingEnabled(): void; /** * Set if drawing is enabled from the client using the canvas */ setDrawingEnabled(drawingEnabled: boolean): void; /** * Toggles erasing on the canvas. It is called via the erase button on the canvas. */ toggleErasingEnabled(): void; /** * Replaces the drawing color with a new color * The format should be ("#ffffff" or "rgb(r,g,b,a?)") * This method is public so that anyone can access the canvas and change the stroke color * * @param newStrokeColor The new stroke color */ changeStrokeColor(newStrokeColor: string): void; /** * Replaces the fill color with a new color * The format should be ("#ffffff" or "rgb(r,g,b,a?)") * This method is public so that anyone can access the canvas and change the fill color * * @param newFillColor The new fill color */ changeFillColor(newFillColor: string): void; /** * This method is invoked by the undo button on the canvas screen * It calls the global undo method and emits a notification after undoing. * This method should only be called from the undo button in this component since it will emit an undo event * If the client calls this method he may create a circular undo action which may cause danger. */ undoLocal(): void; /** * This methods selects the last uuid prepares it for undoing (making the whole update sequence invisible) * This method can be called if the canvas component is a ViewChild of some other component. * This method will work even if the undo button has been disabled */ doUndo(callbackFn?: (updateUUID: string) => void): void; /** * This method takes an UUID for an update, and redraws the canvas by making all updates with that uuid invisible */ private _undoCanvas; /** * This method is invoked by the redo button on the canvas screen * It calls the global redo method and emits a notification after redoing * This method should only be called from the redo button in this component since it will emit an redo event * If the client calls this method he may create a circular redo action which may cause danger. */ redoLocal(): void; /** * This methods selects the last uuid prepares it for redoing (making the whole update sequence visible) * This method can be called if the canvas component is a ViewChild of some other component. * This method will work even if the redo button has been disabled */ doRedo(callbackFn?: (arg: string) => any): void; /** * This method takes an UUID for an update, and redraws the canvas by making all updates with that uuid visible */ private _redoCanvas; /** * Catches the Mouse and Touch events made on the canvas. * If drawing is disabled (If an image exists but it's not loaded, or the user did not click Draw), * this function does nothing. * * If a "mousedown | touchstart" event is triggered, dragging will be set to true and an CanvasWhiteboardUpdate object * of type "start" will be drawn and then sent as an update to all receiving ends. * * If a "mousemove | touchmove" event is triggered and the client is dragging, an CanvasWhiteboardUpdate object * of type "drag" will be drawn and then sent as an update to all receiving ends. * * If a "mouseup, mouseout | touchend, touchcancel" event is triggered, dragging will be set to false and * an CanvasWhiteboardUpdate object of type "stop" will be drawn and then sent as an update to all receiving ends. * */ canvasUserEvents(event: any): void; /** * Get the coordinates (x,y) from a given event * If it is a touch event, get the touch positions * If we released the touch, the position will be placed in the changedTouches object * If it is not a touch event, use the original mouse event received */ private _getCanvasEventPosition; /** * The update coordinates on the canvas are mapped so that all receiving ends * can reverse the mapping and get the same position as the one that * was drawn on this update. * * @param update The CanvasWhiteboardUpdate object. */ private _prepareToSendUpdate; /** * Catches the Key Up events made on the canvas. * If the ctrlKey or commandKey(macOS) was held and the keyCode is 90 (z), an undo action will be performed * If the ctrlKey or commandKey(macOS) was held and the keyCode is 89 (y), a redo action will be performed * If the ctrlKey or commandKey(macOS) was held and the keyCode is 83 (s) or 115(S), a save action will be performed * * @param event The event that occurred. */ private _canvasKeyDown; /** * On window resize, recalculate the canvas dimensions and redraw the history */ private _redrawCanvasOnResize; /** * Redraw the saved history after resetting the canvas state */ private _redrawHistory; /** * Draws a CanvasWhiteboardUpdate object on the canvas. * The coordinates are first reverse mapped so that they can be drawn in the proper place. The update * is afterwards added to the undoStack so that it can be * * If the CanvasWhiteboardUpdate Type is "start", a new "selectedShape" is created. * If the CanvasWhiteboardUpdate Type is "drag", the shape is taken from the shapesMap and then it's updated. * Afterwards the context is used to draw the shape on the canvas. * This function saves the last X and Y coordinates that were drawn. * * @param update The update object. */ private _draw; private _drawIncompleteShapes; private _swapCompletedShapeToActualCanvas; private _resetIncompleteShapeCanvas; /** * Delete everything from the screen, redraw the background, and then redraw all the shapes from the shapesMap */ drawAllShapes(): void; private _addCurrentShapeDataToAnUpdate; generateShapePreviewOptions(): CanvasWhiteboardShapeOptions; /** * Sends the update to all receiving ends as an Event emit. This is done as a batch operation (meaning * multiple updates are sent at the same time). If this method is called, after 100 ms all updates * that were made at that time will be packed up together and sent to the receiver. * * @param update The update object. * @return Emits an Array of Updates when the batch. */ private _prepareUpdateForBatchDispatch; /** * Draws an Array of Updates on the canvas. * * @param updates The array with Updates. */ drawUpdates(updates: CanvasWhiteboardUpdate[]): void; /** * Draw any missing updates that were received before the image was loaded */ private _drawMissingUpdates; /** * Draws an image on the canvas * * @param context The context used to draw the image on the canvas. * @param image The image to draw. * @param x The X coordinate for the starting draw position. * @param y The Y coordinate for the starting draw position. * @param width The width of the image that will be drawn. * @param height The height of the image that will be drawn. * @param offsetX The offsetX if the image size is larger than the canvas (aspect Ratio) * @param offsetY The offsetY if the image size is larger than the canvas (aspect Ratio) */ private _drawImage; /** * The HTMLCanvasElement.toDataURL() method returns a data URI containing a representation * of the image in the format specified by the type parameter (defaults to PNG). * The returned image is in a resolution of 96 dpi. * If the height or width of the canvas is 0, the string "data:," is returned. * If the requested type is not image/png, but the returned value starts with data:image/png, then the requested type is not supported. * Chrome also supports the image/webp type. * * @param returnedDataType A DOMString indicating the image format. The default format type is image/png. * @param returnedDataQuality A Number between 0 and 1 indicating image quality if the requested type * is image/jpeg or image/webp. * If this argument is anything else, the default value for image quality is used. The default value is 0.92. * Other arguments are ignored. */ generateCanvasDataUrl(returnedDataType?: string, returnedDataQuality?: number): string; /** * Generate a Blob object representing the content drawn on the canvas. * This file may be cached on the disk or stored in memory at the discretion of the user agent. * If type is not specified, the image type is image/png. The created image is in a resolution of 96dpi. * The third argument is used with image/jpeg images to specify the quality of the output. * * @param callbackFn The function that should be executed when the blob is created. Should accept a parameter Blob (for the result). * @param returnedDataType A DOMString indicating the image format. The default type is image/png. * @param returnedDataQuality A Number between 0 and 1 indicating image quality if the requested type is image/jpeg or image/webp. * If this argument is anything else, the default value for image quality is used. Other arguments are ignored. */ generateCanvasBlob(callbackFn: (blob: Blob, returnedDataType?: string) => void, returnedDataType?: string, returnedDataQuality?: number): void; /** * Generate a canvas image representation and download it locally * The name of the image is canvas_drawing_ + the current local Date and Time the image was created * Methods for standalone creation of the images in this method are left here for backwards compatibility * * @param returnedDataType A DOMString indicating the image format. The default type is image/png. * @param downloadData? The created string or Blob (IE). * @param customFileName? The name of the file that should be downloaded */ downloadCanvasImage(returnedDataType?: string, downloadData?: string | Blob, customFileName?: string): void; /** * Save the canvas blob (IE) locally */ private _saveCanvasBlob; /** * This method generates a canvas url string or a canvas blob with the presented data type * A callback function is then invoked since the blob creation must be done via a callback * */ generateCanvasData(callback: any, returnedDataType?: string, returnedDataQuality?: number): void; /** * Local method to invoke saving of the canvas data when clicked on the canvas Save button * This method will emit the generated data with the specified Event Emitter * */ saveLocal(returnedDataType?: string): void; private _generateDataTypeString; /** * Toggles the color picker window, delegating the showColorPicker Input to the ColorPickerComponent. * If no value is supplied (null/undefined) the current value will be negated and used. */ toggleStrokeColorPicker(value: boolean): void; /** * Toggles the color picker window, delegating the showColorPicker Input to the ColorPickerComponent. * If no value is supplied (null/undefined) the current value will be negated and used. */ toggleFillColorPicker(value: boolean): void; /** * Toggles the shape selector window, delegating the showShapeSelector Input to the CanvasWhiteboardShapeSelectorComponent. * If no value is supplied (null/undefined) the current value will be negated and used. */ toggleShapeSelector(value: boolean): void; selectShape(newShapeBlueprint: INewCanvasWhiteboardShape<CanvasWhiteboardShape>): void; /** * Returns a deep copy of the current drawing history for the canvas. * The deep copy is returned because we don't want anyone to mutate the current history */ getDrawingHistory(): CanvasWhiteboardUpdate[]; private _setErasing; /** * Unsubscribe from a given subscription if it is active */ private _unsubscribe; private _generateUUID; private _random4; get erasingEnabled(): boolean; }