angular-image-annotator
Version:
Angular component for annotating images.
1,260 lines (1,244 loc) • 45.6 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms')) :
typeof define === 'function' && define.amd ? define('angular-image-annotator', ['exports', '@angular/core', '@angular/forms'], factory) :
(factory((global['angular-image-annotator'] = {}),global.ng.core,global.ng.forms));
}(this, (function (exports,core,forms) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (b.hasOwnProperty(p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __values(o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m)
return m.call(o);
return {
next: function () {
if (o && i >= o.length)
o = void 0;
return { value: o && o[i++], done: !o };
}
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @abstract
*/
var /**
* @abstract
*/ DrawState = /** @class */ (function () {
function DrawState() {
}
return DrawState;
}());
var PencilState = /** @class */ (function (_super) {
__extends(PencilState, _super);
function PencilState() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.currentCommand = new PencilCommand();
return _this;
}
/**
* Draws the next point in the path
* @param ctx Canvas to be drawn on
* @param point Next point to draw
*/
/**
* Draws the next point in the path
* @private
* @param {?} ctx Canvas to be drawn on
* @param {?} point Next point to draw
* @return {?}
*/
PencilState.prototype.drawNextPoint = /**
* Draws the next point in the path
* @private
* @param {?} ctx Canvas to be drawn on
* @param {?} point Next point to draw
* @return {?}
*/
function (ctx, point) {
ctx.beginPath();
ctx.moveTo(this.lastCoord.x, this.lastCoord.y);
ctx.lineTo(point.x, point.y);
ctx.closePath();
ctx.stroke();
};
/**
* @return {?}
*/
PencilState.prototype.getName = /**
* @return {?}
*/
function () {
return 'pencil';
};
/**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
PencilState.prototype.contactStart = /**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
function (imageAnnotator, ev) {
this.lastCoord = ev.point;
this.currentCommand.setColor(( /** @type {?} */(imageAnnotator.drawingCtx.fillStyle)));
};
/**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
PencilState.prototype.contactMove = /**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
function (imageAnnotator, ev) {
this.currentCommand.addPoint(ev.point);
this.drawNextPoint(imageAnnotator.drawingCtx, ev.point);
this.lastCoord = ev.point;
};
/**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
PencilState.prototype.contactEnd = /**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
function (imageAnnotator, ev) {
this.currentCommand.addPoint(ev.point);
this.drawNextPoint(imageAnnotator.drawingCtx, ev.point);
imageAnnotator.addCommand(this.currentCommand);
this.currentCommand = new PencilCommand();
};
/**
* @param {?} imageAnnotator
* @return {?}
*/
PencilState.prototype.cleanUp = /**
* @param {?} imageAnnotator
* @return {?}
*/
function (imageAnnotator) { };
return PencilState;
}(DrawState));
var TextState = /** @class */ (function (_super) {
__extends(TextState, _super);
function TextState() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* @return {?}
*/
TextState.prototype.getName = /**
* @return {?}
*/
function () {
return 'text';
};
/**
* @private
* @param {?} textEntry
* @param {?} projectionFactor
* @return {?}
*/
TextState.prototype.generatePositionTextPairs = /**
* @private
* @param {?} textEntry
* @param {?} projectionFactor
* @return {?}
*/
function (textEntry, projectionFactor) {
/** @type {?} */
var fullText = textEntry.getText();
/** @type {?} */
var lines = fullText.split('\n');
/** @type {?} */
var lineHeight = textEntry.getLineHeight() * projectionFactor;
/** @type {?} */
var positionTextPairs = [];
for (var i = 0; i < lines.length; i++) {
if (lines[i].trim() === '') {
continue;
}
/** @type {?} */
var position = { x: this.currentPosition.x, y: this.currentPosition.y + (i * lineHeight) };
positionTextPairs.push({
text: lines[i],
position: position
});
}
return positionTextPairs;
};
/**
* @private
* @param {?} imageAnnotator
* @return {?}
*/
TextState.prototype.recordCommandAndReset = /**
* @private
* @param {?} imageAnnotator
* @return {?}
*/
function (imageAnnotator) {
/** @type {?} */
var positionTextPairs = this.generatePositionTextPairs(imageAnnotator.textEntry, imageAnnotator.projectionFactor);
this.currentCommand.addPositionTextPairs(positionTextPairs);
this.currentCommand.setColor(( /** @type {?} */(imageAnnotator.drawingCtx.fillStyle)));
this.currentCommand.setFont(imageAnnotator.drawingCtx.font);
this.currentCommand.draw(imageAnnotator.drawingCtx);
imageAnnotator.addCommand(this.currentCommand);
imageAnnotator.textEntry.clear();
this.currentCommand = null;
};
/**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
TextState.prototype.contactStart = /**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
function (imageAnnotator, ev) {
var _this = this;
if (this.currentCommand && !imageAnnotator.textEntry.isEmpty()) {
this.recordCommandAndReset(imageAnnotator);
imageAnnotator.textEntry.hide();
}
else {
this.currentCommand = new TextCommand();
this.currentPosition = ev.point;
imageAnnotator.textEntry.setPosition(ev.point.x / imageAnnotator.projectionFactor, ev.point.y / imageAnnotator.projectionFactor);
imageAnnotator.textEntry.show();
imageAnnotator.textEntry.focus();
imageAnnotator.textEntry.onBlur()
.then(( /**
* @param {?} _
* @return {?}
*/function (_) {
if (_this.currentCommand && !imageAnnotator.textEntry.isEmpty()) {
_this.recordCommandAndReset(imageAnnotator);
}
}));
}
};
/**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
TextState.prototype.contactMove = /**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
function (imageAnnotator, ev) {
this.currentPosition = ev.point;
imageAnnotator.textEntry.setPosition(ev.point.x / imageAnnotator.projectionFactor, ev.point.y / imageAnnotator.projectionFactor);
};
/**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
TextState.prototype.contactEnd = /**
* @param {?} imageAnnotator
* @param {?} ev
* @return {?}
*/
function (imageAnnotator, ev) {
if (!this.currentCommand) {
return;
}
imageAnnotator.textEntry.focus();
};
/**
* @param {?} imageAnnotator
* @return {?}
*/
TextState.prototype.cleanUp = /**
* @param {?} imageAnnotator
* @return {?}
*/
function (imageAnnotator) {
if (this.currentCommand && !imageAnnotator.textEntry.isEmpty()) {
this.recordCommandAndReset(imageAnnotator);
}
imageAnnotator.textEntry.hide();
};
return TextState;
}(DrawState));
var PencilCommand = /** @class */ (function () {
function PencilCommand() {
this.pathArray = [];
}
/**
* @param {?} point
* @return {?}
*/
PencilCommand.prototype.addPoint = /**
* @param {?} point
* @return {?}
*/
function (point) {
this.pathArray.push(point);
};
/**
* @param {?} color
* @return {?}
*/
PencilCommand.prototype.setColor = /**
* @param {?} color
* @return {?}
*/
function (color) {
this.color = color;
};
/**
* @param {?} ctx
* @return {?}
*/
PencilCommand.prototype.draw = /**
* @param {?} ctx
* @return {?}
*/
function (ctx) {
/** @type {?} */
var currentStrokeStyle = ctx.strokeStyle;
ctx.strokeStyle = this.color;
ctx.beginPath();
for (var i = 1; i < this.pathArray.length; i++) {
/** @type {?} */
var coord = this.pathArray[i];
/** @type {?} */
var lastCoord = this.pathArray[i - 1];
ctx.moveTo(lastCoord.x, lastCoord.y);
ctx.lineTo(coord.x, coord.y);
ctx.closePath();
}
ctx.stroke();
ctx.strokeStyle = currentStrokeStyle;
};
return PencilCommand;
}());
var TextCommand = /** @class */ (function () {
function TextCommand() {
this.positionTextPairs = [];
}
/**
* @param {?} pairs
* @return {?}
*/
TextCommand.prototype.addPositionTextPairs = /**
* @param {?} pairs
* @return {?}
*/
function (pairs) {
this.positionTextPairs = this.positionTextPairs.concat(pairs);
};
/**
* @param {?} color
* @return {?}
*/
TextCommand.prototype.setColor = /**
* @param {?} color
* @return {?}
*/
function (color) {
this.color = color;
};
/**
* @param {?} font
* @return {?}
*/
TextCommand.prototype.setFont = /**
* @param {?} font
* @return {?}
*/
function (font) {
this.font = font;
};
/**
* @param {?} ctx
* @return {?}
*/
TextCommand.prototype.draw = /**
* @param {?} ctx
* @return {?}
*/
function (ctx) {
var e_1, _a;
/** @type {?} */
var currentFillStyle = ctx.fillStyle;
/** @type {?} */
var currentFont = ctx.font;
ctx.fillStyle = this.color;
ctx.font = this.font;
try {
for (var _b = __values(this.positionTextPairs), _c = _b.next(); !_c.done; _c = _b.next()) {
var pair = _c.value;
ctx.fillText(pair.text, pair.position.x, pair.position.y);
}
}
catch (e_1_1) {
e_1 = { error: e_1_1 };
}
finally {
try {
if (_c && !_c.done && (_a = _b.return))
_a.call(_b);
}
finally {
if (e_1)
throw e_1.error;
}
}
ctx.fillStyle = currentFillStyle;
ctx.font = currentFont;
};
return TextCommand;
}());
var ClearCommand = /** @class */ (function () {
function ClearCommand(canvasWidth, canvasHeight) {
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
}
/**
* @param {?} ctx
* @return {?}
*/
ClearCommand.prototype.draw = /**
* @param {?} ctx
* @return {?}
*/
function (ctx) {
ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
};
return ClearCommand;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var ContactEvent = /** @class */ (function () {
function ContactEvent(type, point) {
this.type = type;
this.point = point;
}
return ContactEvent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var EventTranslator = /** @class */ (function () {
function EventTranslator() {
}
/**
* @param {?} event
* @param {?} canvasRect
* @param {?} projectionFactor
* @return {?}
*/
EventTranslator.prototype.translate = /**
* @param {?} event
* @param {?} canvasRect
* @param {?} projectionFactor
* @return {?}
*/
function (event, canvasRect, projectionFactor) {
/** @type {?} */
var singleEvent;
// @ts-ignore
if (window.TouchEvent && event instanceof TouchEvent) {
singleEvent = event.changedTouches.item(0);
}
else {
singleEvent = event;
}
/** @type {?} */
var point = this.getCanvasPointFromEvent(singleEvent, canvasRect.left, canvasRect.top, projectionFactor);
return new ContactEvent(this.getTypeFromEvent(event), point);
};
/**
* @private
* @param {?} ev
* @param {?} offsetLeft
* @param {?} offsetTop
* @param {?} projectionFactor
* @return {?}
*/
EventTranslator.prototype.getCanvasPointFromEvent = /**
* @private
* @param {?} ev
* @param {?} offsetLeft
* @param {?} offsetTop
* @param {?} projectionFactor
* @return {?}
*/
function (ev, offsetLeft, offsetTop, projectionFactor) {
/** @type {?} */
var point = {
x: (ev.clientX - offsetLeft) * projectionFactor,
y: (ev.clientY - offsetTop) * projectionFactor
};
return point;
};
/**
* @private
* @param {?} ev
* @return {?}
*/
EventTranslator.prototype.getTypeFromEvent = /**
* @private
* @param {?} ev
* @return {?}
*/
function (ev) {
/** @type {?} */
var type;
switch (ev.type) {
case 'touchstart':
type = 'start';
break;
case 'mousedown':
type = 'start';
break;
case 'touchmove':
type = 'move';
break;
case 'mousemove':
type = 'move';
break;
case 'touchend':
type = 'end';
break;
case 'mouseup':
type = 'end';
break;
default:
console.error("aia-image-annotator: unrecognized contact event: " + ev.type);
}
return type;
};
return EventTranslator;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
var DEFAULTS = {
fontSize: '15px',
fontFamily: 'Georgia',
color: '#1218CE'
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var FloatingTextEntryComponent = /** @class */ (function () {
function FloatingTextEntryComponent() {
this.currentText = '';
}
/**
* @return {?}
*/
FloatingTextEntryComponent.prototype.getText = /**
* @return {?}
*/
function () {
return this.currentText;
};
/**
* @return {?}
*/
FloatingTextEntryComponent.prototype.hide = /**
* @return {?}
*/
function () {
this.textBoxRef.nativeElement.style.display = 'none';
};
/**
* @return {?}
*/
FloatingTextEntryComponent.prototype.show = /**
* @return {?}
*/
function () {
this.textBoxRef.nativeElement.style.display = 'block';
};
/**
* @param {?} fontStr
* @return {?}
*/
FloatingTextEntryComponent.prototype.setFont = /**
* @param {?} fontStr
* @return {?}
*/
function (fontStr) {
this.textBoxRef.nativeElement.style.font = fontStr;
};
/**
* @param {?} color
* @return {?}
*/
FloatingTextEntryComponent.prototype.setColor = /**
* @param {?} color
* @return {?}
*/
function (color) {
this.textBoxRef.nativeElement.style.color = color;
};
/**
* @param {?} x
* @param {?} y
* @return {?}
*/
FloatingTextEntryComponent.prototype.setPosition = /**
* @param {?} x
* @param {?} y
* @return {?}
*/
function (x, y) {
this.textBoxRef.nativeElement.style.top = y + 'px';
this.textBoxRef.nativeElement.style.left = x + 'px';
};
/**
* @return {?}
*/
FloatingTextEntryComponent.prototype.isEmpty = /**
* @return {?}
*/
function () {
return this.currentText.trim() === '';
};
/**
* @return {?}
*/
FloatingTextEntryComponent.prototype.focus = /**
* @return {?}
*/
function () {
var _this = this;
setTimeout(( /**
* @param {?} _
* @return {?}
*/function (_) {
_this.inputRef.nativeElement.focus();
}), 0);
};
/**
* @return {?}
*/
FloatingTextEntryComponent.prototype.clear = /**
* @return {?}
*/
function () {
this.currentText = '';
};
/**
* @return {?}
*/
FloatingTextEntryComponent.prototype.onBlur = /**
* @return {?}
*/
function () {
var _this = this;
return new Promise(( /**
* @param {?} resolve
* @return {?}
*/function (resolve) {
_this.inputRef.nativeElement.addEventListener('blur', resolve);
}));
};
/**
* @return {?}
*/
FloatingTextEntryComponent.prototype.getLineHeight = /**
* @return {?}
*/
function () {
return this.getLineHeightHelper(this.textBoxRef.nativeElement);
};
/**
* @private
* @param {?} el
* @return {?}
*/
FloatingTextEntryComponent.prototype.getLineHeightHelper = /**
* @private
* @param {?} el
* @return {?}
*/
function (el) {
/** @type {?} */
var temp = document.createElement(el.nodeName);
temp.setAttribute('style', "margin:0px;padding:0px;font-family:" + el.style.fontFamily + ";font-size:" + el.style.fontSize);
temp.innerHTML = 'test';
temp = el.parentNode.appendChild(temp);
/** @type {?} */
var ret = temp.clientHeight;
temp.parentNode.removeChild(temp);
return ret;
};
FloatingTextEntryComponent.decorators = [
{ type: core.Component, args: [{
selector: 'aia-floating-text-entry',
template: "<div #textBox class=\"floating-text-entry\">\n <textarea #input [(ngModel)]=\"currentText\"></textarea>\n <p>{{currentText}} </p>\n</div>\n",
styles: [".floating-text-entry{display:none;position:absolute;padding:0;margin:0;background-color:rgba(0,0,0,0);border:1px solid #5aa5be;text-align:left;white-space:pre}.floating-text-entry p{padding:0;margin:0}.floating-text-entry textarea{position:absolute;bottom:0;right:0;height:0;width:0;border:0;padding:0;background:rgba(0,0,0,0);resize:none}"]
}] }
];
FloatingTextEntryComponent.propDecorators = {
textBoxRef: [{ type: core.ViewChild, args: ['textBox',] }],
inputRef: [{ type: core.ViewChild, args: ['input',] }]
};
return FloatingTextEntryComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var AiaImageAnnotatorComponent = /** @class */ (function () {
function AiaImageAnnotatorComponent() {
this.displayWidth = null;
this.imageWidth = 0;
this.imageHeight = 0;
this.displayHeight = 0;
/**
* Multiply this to project from the DOM space to the canvas space
*/
this.projectionFactor = 0;
this._state = new PencilState();
this._drawCommands = [];
this._redoCommands = [];
this.eventTranslator = new EventTranslator();
this.mouseCurrentlyDown = false;
}
Object.defineProperty(AiaImageAnnotatorComponent.prototype, "canvasRect", {
get: /**
* @return {?}
*/ function () {
return this.drawingCanvasRef.nativeElement.getBoundingClientRect();
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.loadImageAndInitializeCanvas(this.image);
};
/**
* @param {?} changes
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
if (changes.image) {
// Full reset
this._drawCommands = [];
this._redoCommands = [];
this.loadImageAndInitializeCanvas(this.image);
}
else {
// Just colors and fonts
this.setColorAndFont(this.color, this.fontSize, this.fontFamily);
}
};
/**
* BEGIN PUBLIC INTERFACE
*/
/**
* Sets current tool
* @param toolName Name of the tool
*/
/**
* BEGIN PUBLIC INTERFACE
*/
/**
* Sets current tool
* @param {?} toolName Name of the tool
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.setTool = /**
* BEGIN PUBLIC INTERFACE
*/
/**
* Sets current tool
* @param {?} toolName Name of the tool
* @return {?}
*/
function (toolName) {
if (toolName === this._state.getName()) {
return;
}
this._state.cleanUp(this);
switch (toolName) {
case 'pencil':
this._state = new PencilState();
break;
case 'text':
this._state = new TextState();
break;
default:
console.error("Angular Image Annotator: Unrecognized tool name " + toolName);
break;
}
};
/**
* Undo last action
*/
/**
* Undo last action
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.undo = /**
* Undo last action
* @return {?}
*/
function () {
if (!this._drawCommands.length) {
return;
}
this._redoCommands.push(this._drawCommands.pop());
this.clearCanvas();
this.drawCommandsOnCanvas(this._drawCommands, this.drawingCtx);
};
/**
* Redo last undone action if available
*/
/**
* Redo last undone action if available
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.redo = /**
* Redo last undone action if available
* @return {?}
*/
function () {
if (!this._redoCommands.length) {
return;
}
this._drawCommands.push(this._redoCommands.pop());
this.clearCanvas();
this.drawCommandsOnCanvas(this._drawCommands, this.drawingCtx);
};
/**
* Clears canvas undo-ably
*/
/**
* Clears canvas undo-ably
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.clear = /**
* Clears canvas undo-ably
* @return {?}
*/
function () {
/** @type {?} */
var clearCommand = new ClearCommand(this.drawingCanvasRef.nativeElement.width, this.drawingCanvasRef.nativeElement.height);
this.addCommand(clearCommand);
this.drawCommandsOnCanvas([clearCommand], this.drawingCtx);
};
/**
* Returns annotated image as data URI
*/
/**
* Returns annotated image as data URI
* @param {?=} type
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.getAnnotatedImage = /**
* Returns annotated image as data URI
* @param {?=} type
* @return {?}
*/
function (type) {
if (type === void 0) {
type = 'image/png';
}
/** @type {?} */
var mergeCanvas = this.mergeCanvasRef.nativeElement;
mergeCanvas.style.width = this.drawingCanvasRef.nativeElement.width;
mergeCanvas.style.height = this.drawingCanvasRef.nativeElement.height;
/** @type {?} */
var mergeCtx = mergeCanvas.getContext('2d');
mergeCtx.drawImage(this.imageCanvasRef.nativeElement, 0, 0);
mergeCtx.drawImage(this.drawingCanvasRef.nativeElement, 0, 0);
return mergeCanvas.toDataURL(type);
};
/**
* END PUBLIC INTERFACE
*/
/**
* Loads an image from an src and initializes the canvases. CLEARS ALL EXISTING ANNOTATIONS
* @param image The src for the image to be annotated
*/
/**
* END PUBLIC INTERFACE
*/
/**
* Loads an image from an src and initializes the canvases. CLEARS ALL EXISTING ANNOTATIONS
* @private
* @param {?} image The src for the image to be annotated
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.loadImageAndInitializeCanvas = /**
* END PUBLIC INTERFACE
*/
/**
* Loads an image from an src and initializes the canvases. CLEARS ALL EXISTING ANNOTATIONS
* @private
* @param {?} image The src for the image to be annotated
* @return {?}
*/
function (image) {
var _this = this;
if (!image) {
console.log('aia-image-annotator: No image bound... skipping render');
return;
}
/** @type {?} */
var tempImage = new Image();
tempImage.onload = ( /**
* @param {?} _
* @return {?}
*/function (_) {
_this.imageWidth = tempImage.width;
_this.imageHeight = tempImage.height;
_this.initializeDisplayDimensions();
setTimeout(( /**
* @param {?} _
* @return {?}
*/function (_) {
_this.initializeCanvas(tempImage);
}), 0);
});
tempImage.src = image;
};
/**
* Sets projection factor, display width, and display height.
* If display width hasn't been provided, it defaults to the image dimensions
*/
/**
* Sets projection factor, display width, and display height.
* If display width hasn't been provided, it defaults to the image dimensions
* @private
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.initializeDisplayDimensions = /**
* Sets projection factor, display width, and display height.
* If display width hasn't been provided, it defaults to the image dimensions
* @private
* @return {?}
*/
function () {
if (this.displayWidth) {
this.displayHeight = this.displayWidth * this.imageHeight / this.imageWidth;
this.projectionFactor = this.imageHeight / this.displayHeight;
}
else {
this.displayHeight = this.imageHeight;
this.displayWidth = this.imageWidth;
this.projectionFactor = 1;
}
};
/**
* Initializes the canvases (both drawing and image)
* Sets canvas dimensions, loads contexts, etc.
* @param img The image to load on the image canvas
*/
/**
* Initializes the canvases (both drawing and image)
* Sets canvas dimensions, loads contexts, etc.
* @private
* @param {?} img The image to load on the image canvas
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.initializeCanvas = /**
* Initializes the canvases (both drawing and image)
* Sets canvas dimensions, loads contexts, etc.
* @private
* @param {?} img The image to load on the image canvas
* @return {?}
*/
function (img) {
this.imageCtx = this.imageCanvasRef.nativeElement.getContext('2d');
this.imageCtx.drawImage(img, 0, 0);
this.drawingCtx = this.drawingCanvasRef.nativeElement.getContext('2d');
this.drawingCtx.lineJoin = 'round';
this.drawingCtx.lineCap = 'round';
this.drawingCtx.lineWidth = 2;
this.drawingCtx.textBaseline = 'hanging';
this.setColorAndFont(this.color, this.fontSize, this.fontFamily);
};
/**
* Sets the color and the font
*/
/**
* Sets the color and the font
* @private
* @param {?} color
* @param {?} fontSize
* @param {?} fontFamily
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.setColorAndFont = /**
* Sets the color and the font
* @private
* @param {?} color
* @param {?} fontSize
* @param {?} fontFamily
* @return {?}
*/
function (color, fontSize, fontFamily) {
if (!this.drawingCtx) {
return;
}
this.drawingCtx.strokeStyle = color || DEFAULTS.color;
this.drawingCtx.fillStyle = color || DEFAULTS.color;
this.textEntry.setColor(color || DEFAULTS.color);
/** @type {?} */
var fontString = (fontSize || DEFAULTS.fontSize) + " " + (fontFamily || DEFAULTS.fontFamily);
this.drawingCtx.font = fontString;
/** @type {?} */
var fontParts = fontSize.match(/(.*)(px|pt)/);
/** @type {?} */
var adjustedFontSize = Math.floor(parseInt(fontParts[1], 10) / this.projectionFactor) + fontParts[2];
this.textEntry.setFont((adjustedFontSize || DEFAULTS.fontSize) + " " + (fontFamily || DEFAULTS.fontFamily));
};
/**
* Clears drawing canvas - no questions asked
*/
/**
* Clears drawing canvas - no questions asked
* @private
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.clearCanvas = /**
* Clears drawing canvas - no questions asked
* @private
* @return {?}
*/
function () {
this.drawingCtx.clearRect(0, 0, this.drawingCanvasRef.nativeElement.width, this.drawingCanvasRef.nativeElement.height);
};
/**
* Draws commands on canvas
* @param commands The draw commands to be drawn
* @param ctx The canvas 2d context
*/
/**
* Draws commands on canvas
* @private
* @param {?} commands The draw commands to be drawn
* @param {?} ctx The canvas 2d context
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.drawCommandsOnCanvas = /**
* Draws commands on canvas
* @private
* @param {?} commands The draw commands to be drawn
* @param {?} ctx The canvas 2d context
* @return {?}
*/
function (commands, ctx) {
commands.forEach(( /**
* @param {?} command
* @return {?}
*/function (command) {
command.draw(ctx);
}));
};
/**
* @param {?} command
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.addCommand = /**
* @param {?} command
* @return {?}
*/
function (command) {
this._drawCommands.push(command);
this._redoCommands = [];
};
/**
* @param {?} ev
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.touchStart = /**
* @param {?} ev
* @return {?}
*/
function (ev) {
/** @type {?} */
var contactEvent = this.eventTranslator.translate(ev, this.canvasRect, this.projectionFactor);
this._state.contactStart(this, contactEvent);
};
/**
* @param {?} ev
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.touchMove = /**
* @param {?} ev
* @return {?}
*/
function (ev) {
ev.preventDefault(); // Disable scrolling
// Disable scrolling
/** @type {?} */
var contactEvent = this.eventTranslator.translate(ev, this.canvasRect, this.projectionFactor);
this._state.contactMove(this, contactEvent);
};
/**
* @param {?} ev
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.touchEnd = /**
* @param {?} ev
* @return {?}
*/
function (ev) {
/** @type {?} */
var contactEvent = this.eventTranslator.translate(ev, this.canvasRect, this.projectionFactor);
this._state.contactEnd(this, contactEvent);
};
/**
* @param {?} ev
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.mouseDown = /**
* @param {?} ev
* @return {?}
*/
function (ev) {
this.mouseCurrentlyDown = true;
/** @type {?} */
var contactEvent = this.eventTranslator.translate(ev, this.canvasRect, this.projectionFactor);
this._state.contactStart(this, contactEvent);
};
/**
* @param {?} ev
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.mouseMove = /**
* @param {?} ev
* @return {?}
*/
function (ev) {
if (!this.mouseCurrentlyDown) {
return;
}
/** @type {?} */
var contactEvent = this.eventTranslator.translate(ev, this.canvasRect, this.projectionFactor);
this._state.contactMove(this, contactEvent);
};
/**
* @param {?} ev
* @return {?}
*/
AiaImageAnnotatorComponent.prototype.mouseUp = /**
* @param {?} ev
* @return {?}
*/
function (ev) {
this.mouseCurrentlyDown = false;
/** @type {?} */
var contactEvent = this.eventTranslator.translate(ev, this.canvasRect, this.projectionFactor);
this._state.contactEnd(this, contactEvent);
};
AiaImageAnnotatorComponent.decorators = [
{ type: core.Component, args: [{
selector: 'aia-image-annotator',
template: "<div class=\"outer-container\">\n <div [style.width.px]=\"displayWidth\" [style.height.px]=\"displayHeight\" class=\"canvas-container\">\n <canvas class=\"image-canvas\" #imageCanvas [width]=\"imageWidth\" [height]=\"imageHeight\" [style.width.px]=\"displayWidth\" [style.height.px]=\"displayHeight\"></canvas>\n <canvas #drawingCanvas (touchstart)=\"touchStart($event)\" (touchmove)=\"touchMove($event)\" (touchend)=\"touchEnd($event)\" (mousedown)=\"mouseDown($event)\" (mousemove)=\"mouseMove($event)\" (mouseup)=\"mouseUp($event)\" [width]=\"imageWidth\" [height]=\"imageHeight\" [style.width.px]=\"displayWidth\" [style.height.px]=\"displayHeight\"></canvas>\n <canvas #mergeCanvas class=\"merge-canvas\" [width]=\"imageWidth\" [height]=\"imageHeight\"></canvas>\n <aia-floating-text-entry (mouseup)=\"mouseUp($event)\" (touchend)=\"touchEnd($event)\"></aia-floating-text-entry>\n </div>\n</div>\n",
styles: [".outer-container{display:flex;justify-content:space-around}.outer-container .canvas-container{position:relative}.outer-container .canvas-container canvas{position:absolute;top:0;left:0}.outer-container .canvas-container canvas.image-canvas{z-index:-1}.outer-container .canvas-container canvas.merge-canvas{display:none}"]
}] }
];
/** @nocollapse */
AiaImageAnnotatorComponent.ctorParameters = function () { return []; };
AiaImageAnnotatorComponent.propDecorators = {
image: [{ type: core.Input }],
fontFamily: [{ type: core.Input }],
fontSize: [{ type: core.Input }],
color: [{ type: core.Input }],
displayWidth: [{ type: core.Input }],
imageCanvasRef: [{ type: core.ViewChild, args: ['imageCanvas',] }],
drawingCanvasRef: [{ type: core.ViewChild, args: ['drawingCanvas',] }],
mergeCanvasRef: [{ type: core.ViewChild, args: ['mergeCanvas',] }],
textEntry: [{ type: core.ViewChild, args: [FloatingTextEntryComponent,] }]
};
return AiaImageAnnotatorComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var AngularImageAnnotatorModule = /** @class */ (function () {
function AngularImageAnnotatorModule() {
}
AngularImageAnnotatorModule.decorators = [
{ type: core.NgModule, args: [{
declarations: [AiaImageAnnotatorComponent, FloatingTextEntryComponent],
imports: [
forms.FormsModule
],
exports: [AiaImageAnnotatorComponent]
},] }
];
return AngularImageAnnotatorModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
exports.AiaImageAnnotatorComponent = AiaImageAnnotatorComponent;
exports.AngularImageAnnotatorModule = AngularImageAnnotatorModule;
exports.ɵa = FloatingTextEntryComponent;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=angular-image-annotator.umd.js.map