canvasimo
Version:
An HTML5 canvas drawing library, with 150+ useful methods, jQuery-like fluent interface, and cross-browser compatibility enhancements.
1,271 lines (1,270 loc) • 70.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// tslint:disable-next-line:no-var-requires
var VERSION = require('../package.json').version;
var constants_1 = require("./constants");
var logger_1 = require("./logger");
var utils_1 = require("./utils");
var unsupportedMethodErrors = [];
var logUnsupportedMethodError = function (method) {
if (unsupportedMethodErrors.indexOf(method) < 0) {
unsupportedMethodErrors.push(method);
logger_1.default.warn(method + " is not supported by this browser");
}
};
var Canvasimo = /** @class */ (function () {
function Canvasimo(element) {
var _this = this;
this.ctxType = constants_1.CONTEXT_TYPE;
this.density = constants_1.DEFAULT_DENSITY;
/**
* @group Canvas element
* @description A collection of methods for getting and setting various properties of the canvas element.
*/
/**
* Get the canvas element.
* @alias getElement
*/
this.getCanvas = function () { return _this.element; };
this.getElement = function () { return _this.getCanvas(); };
/**
* Set the canvas pixel density.
*/
this.setDensity = function (density) {
if (_this.density !== density) {
var _a = _this.getSize(), prevWidth = _a.width, prevHeight = _a.height;
_this.saveContextValues();
_this.density = density;
_this.element.width = prevWidth * density;
_this.element.height = prevHeight * density;
_this.restoreContextValues();
}
return _this;
};
/**
* Get the canvas pixel density.
*/
this.getDensity = function () { return _this.density; };
/**
* Set the canvas dimensions.
*/
this.setSize = function (width, height) {
_this.saveContextValues();
if (typeof width === 'object') {
_this.element.width = width.width * _this.density;
_this.element.height = width.height * _this.density;
}
else if (typeof height === 'number') {
_this.element.width = width * _this.density;
_this.element.height = height * _this.density;
}
_this.restoreContextValues();
return _this;
};
/**
* Get the canvas dimensions.
*/
this.getSize = function () { return ({
width: _this.element.width / _this.density,
height: _this.element.height / _this.density,
}); };
/**
* Set the canvas width.
*/
this.setWidth = function (width) {
_this.saveContextValues();
_this.element.width = width * _this.density;
_this.restoreContextValues();
return _this;
};
/**
* Get the canvas width.
*/
this.getWidth = function () { return _this.element.width / _this.density; };
/**
* Set the canvas height.
*/
this.setHeight = function (height) {
_this.saveContextValues();
_this.element.height = height * _this.density;
_this.restoreContextValues();
return _this;
};
/**
* Get the canvas height.
*/
this.getHeight = function () { return _this.element.height / _this.density; };
/**
* Get the canvas size & position on screen.
*/
this.getBoundingClientRect = function () { return _this.element.getBoundingClientRect(); };
/**
* @group Context
* @description 'A collection of methods for retrieving a canvas context or information about the context.
*/
/**
* Get the standard canvas context (used for drawing).
*/
this.getContext = function (type, contextAttributes) {
return _this.element.getContext(type, contextAttributes);
};
/**
* Get canvas context used by Canvasimo (2d).
*/
this.getCurrentContext = function () { return _this.ctx; };
/**
* Get the context type used by Canvasimo ('2d', 'webgl', etc).
*/
this.getCurrentContextType = function () { return _this.ctxType; };
/**
* Get the context attributes used.
*/
this.getContextAttributes = function () {
if (typeof _this.ctx.getContextAttributes !== 'function') {
logUnsupportedMethodError('getContextAttributes');
return null;
}
return _this.ctx.getContextAttributes();
};
/**
* @group Solid Shapes
* @description A collection of methods for plotting or drawing solid shapes -
* those that create a new shape when invoked, and are self closing.
*/
// plotRect',
/**
* Plot a rectangle that can then have a fill or stroke applied to it.
* @alias rect
*/
this.plotRect = function (x, y, width, height) { return _this.rect(x, y, width, height); };
this.rect = function (x, y, width, height) {
_this.ctx.rect(x * _this.density, y * _this.density, width * _this.density, height * _this.density);
return _this;
};
/**
* Plot a rectangle and apply a stroke to it.
*/
this.strokeRect = function (x, y, width, height, color) {
if (typeof color !== 'undefined') {
_this.setStroke(color);
}
_this.ctx.strokeRect(x * _this.density, y * _this.density, width * _this.density, height * _this.density);
return _this;
};
/**
* Plot a rectangle and apply a fill to it.
*/
this.fillRect = function (x, y, width, height, color) {
if (typeof color !== 'undefined') {
_this.setFill(color);
}
_this.ctx.fillRect(x * _this.density, y * _this.density, width * _this.density, height * _this.density);
return _this;
};
/**
* Plot a rounded rectangle that can then have a fill or stroke applied to it.
*/
this.plotRoundedRect = function (x, y, width, height, radius) {
var minRadius = Math.min(width / 2, height / 2, radius);
return _this
.beginPath()
.moveTo(x + minRadius, y)
.lineTo(x + width - minRadius, y)
.arcTo(x + width, y, x + width, y + minRadius, minRadius)
.lineTo(x + width, y + height - minRadius)
.arcTo(x + width, y + height, x + width - minRadius, y + height, minRadius)
.lineTo(x + minRadius, y + height)
.arcTo(x, y + height, x, y + height - minRadius, minRadius)
.lineTo(x, y + minRadius)
.arcTo(x, y, x + minRadius, y, minRadius)
.closePath();
};
/**
* Plot a rounded rectangle and apply a stroke to it.
*/
this.strokeRoundedRect = function (x, y, width, height, radius, color) {
return _this
.plotRoundedRect(x, y, width, height, radius)
.stroke(color);
};
/**
* Plot a rounded rectangle and apply a fill to it.
*/
this.fillRoundedRect = function (x, y, width, height, radius, color) {
return _this
.plotRoundedRect(x, y, width, height, radius)
.fill(color);
};
/**
* Plot a circle that can then have a stroke or fill applied to it.
*/
this.plotCircle = function (x, y, radius, anticlockwise) {
return _this
.beginPath()
.plotArc(x, y, radius, 0, Math.PI * 2, anticlockwise)
.closePath();
};
/**
* Plot a circle and apply a stroke to it.
*/
this.strokeCircle = function (x, y, radius, anticlockwise, color) {
return _this
.plotCircle(x, y, radius, anticlockwise)
.stroke(color);
};
/**
* Plot a circle and apply a fill to it.
*/
this.fillCircle = function (x, y, radius, anticlockwise, color) {
return _this
.plotCircle(x, y, radius, anticlockwise)
.fill(color);
};
/**
* Plot a polygon that can then have a stroke or fill applied to it.
*/
this.plotPoly = function (x, y, radius, sides, anticlockwise) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
var direction = anticlockwise ? -1 : 1;
var beforeEnd = function (i) { return anticlockwise ? i > -sides : i < sides; };
_this
.beginPath()
.moveTo(x + radius, y);
for (var i = 0; beforeEnd(i); i += direction) {
var angle = Math.PI * 2 / sides * i;
_this.lineTo(x + radius * Math.cos(angle), y + radius * Math.sin(angle));
}
return _this.closePath();
};
/**
* Plot a polygon and apply a stoke to it.
*/
this.strokePoly = function (x, y, radius, sides, anticlockwise, color) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
return _this
.plotPoly(x, y, radius, sides, anticlockwise)
.stroke(color);
};
/**
* Plot a polygon and apply a fill to it.
*/
this.fillPoly = function (x, y, radius, sides, anticlockwise, color) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
return _this
.plotPoly(x, y, radius, sides, anticlockwise)
.fill(color);
};
/**
* Plot a star that can then have a stroke or fill applied to it.
*/
this.plotStar = function (x, y, radius1, sides, anticlockwise) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
else if (sides === 3 || sides === 4) {
return _this.plotPoly(x, y, radius1, sides);
}
sides = sides * 2;
var direction = anticlockwise ? -1 : 1;
var offset = Math.PI * 2 / sides;
var cross = Math.cos(offset * 2) * radius1;
var radius2 = cross / Math.cos(offset);
var beforeEnd = function (i) { return anticlockwise ? i > -sides : i < sides; };
_this
.beginPath()
.moveTo(x + radius1, y);
for (var i = 0; beforeEnd(i); i += direction) {
var angle = offset * i;
var radius = i % 2 ? radius2 : radius1;
_this.lineTo(x + radius * Math.cos(angle), y + radius * Math.sin(angle));
}
return _this.closePath();
};
/**
* Plot a star and apply a stoke to it.
*/
this.strokeStar = function (x, y, radius1, sides, anticlockwise, color) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
return _this
.plotStar(x, y, radius1, sides, anticlockwise)
.stroke(color);
};
/**
* Plot a star and apply a fill to it.
*/
this.fillStar = function (x, y, radius1, sides, anticlockwise, color) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
return _this
.plotStar(x, y, radius1, sides, anticlockwise)
.fill(color);
};
/**
* Plot a burst that can then have a stroke or fill applied to it.
*/
this.plotBurst = function (x, y, radius1, radius2, sides, anticlockwise) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
sides = sides * 2;
var direction = anticlockwise ? -1 : 1;
var offset = Math.PI * 2 / sides;
var beforeEnd = function (i) { return anticlockwise ? i > -sides : i < sides; };
_this
.beginPath()
.moveTo(x + radius1, y);
for (var i = 0; beforeEnd(i); i += direction) {
var angle = offset * i;
var radius = i % 2 ? radius2 : radius1;
_this.lineTo(x + radius * Math.cos(angle), y + radius * Math.sin(angle));
}
return _this
.closePath();
};
/**
* Plot a burst and apply a stoke to it.
*/
this.strokeBurst = function (x, y, radius1, radius2, sides, anticlockwise, color) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
return _this
.plotBurst(x, y, radius1, radius2, sides, anticlockwise)
.stroke(color);
};
/**
* Plot a burst and apply a fill to it.
*/
this.fillBurst = function (x, y, radius1, radius2, sides, anticlockwise, color) {
sides = Math.round(sides);
if (!sides || sides < 3) {
return _this;
}
return _this
.plotBurst(x, y, radius1, radius2, sides, anticlockwise)
.fill(color);
};
/**
* Plot a single pixel that can then have a stroke or fill applied to it.
*/
this.plotPixel = function (x, y) {
return _this
.plotRect(x, y, 1, 1);
};
/**
* Plot a single pixel and apply a stroke to it.
*/
this.strokePixel = function (x, y, color) {
return _this
.strokeRect(x, y, 1, 1, color);
};
/**
* Plot a single pixel and apply a fill to it.
*/
this.fillPixel = function (x, y, color) {
return _this
.fillRect(x, y, 1, 1, color);
};
/**
* Plot a closed path that can then have a stroke or fill applied to it.
*/
this.plotClosedPath = function (points) {
return _this
.beginPath()
.plotPath(points)
.closePath();
};
/**
* Plot a closed path and apply a stroke to it.
*/
this.strokeClosedPath = function (points, color) {
return _this
.plotClosedPath(points)
.stroke(color);
};
/**
* Plot a closed path and apply a fill to it.
*/
this.fillClosedPath = function (points, color) {
return _this
.plotClosedPath(points)
.fill(color);
};
/**
* @group Open Shapes
* @description A collection of methods for plotting or drawing open shapes -
* those that create a new shape when invoked, but are not self closing.
*/
/**
* Plot a line that can then have a stroke or fill applied to it.
*/
this.plotLine = function (x1, y1, x2, y2) {
return _this
.moveTo(x1, y1)
.lineTo(x2, y2);
};
/**
* Plot a line and apply a stroke to it.
*/
this.strokeLine = function (x1, y1, x2, y2, color) {
return _this
.plotLine(x1, y1, x2, y2)
.stroke(color);
};
/**
* Plot a line, by length & angle, that can then have a stroke or fill applied to it.
*/
this.plotLength = function (x1, y1, length, angle) {
var x2 = x1 + length * Math.cos(angle);
var y2 = y1 + length * Math.sin(angle);
return _this
.moveTo(x1, y1)
.lineTo(x2, y2);
};
/**
* Plot a line, by length & angle, and apply a stroke to it.
*/
this.strokeLength = function (x1, y1, length, angle, color) {
return _this
.plotLength(x1, y1, length, angle)
.stroke(color);
};
/**
* Plot a path, that is not self closing, that can have a stroke or fill applied to it.
*/
this.plotPath = function (points) {
utils_1.forPoints(points, function (x, y, i) {
if (i === 0) {
_this.moveTo(x, y);
}
else {
_this.lineTo(x, y);
}
});
return _this;
};
/**
* Plot a path, that is not self closing, and apply a stroke to it.
*/
this.strokePath = function (points, color) {
return _this
.plotPath(points)
.stroke(color);
};
/**
* Plot a path, that is not self closing, and apply a fill to it.
*/
this.fillPath = function (points, color) {
return _this
.plotPath(points)
.fill(color);
};
/**
* @group Paths
* @description A collection of methods for plotting or drawing paths -
* shapes that can be connected to create more complex shapes.
*/
/**
* Plot an arc that can have a stroke or fill applied to it.
* @alias arc
*/
this.plotArc = function (x, y, radius, startAngle, endAngle, anticlockwise) {
return _this.arc(x, y, radius, startAngle, endAngle, anticlockwise);
};
this.arc = function (x, y, radius, startAngle, endAngle, anticlockwise) {
_this.ctx.arc(x * _this.density, y * _this.density, radius * _this.density, startAngle, endAngle, anticlockwise || false);
return _this;
};
/**
* Plot an arc and apply a stroke to it.
*/
this.strokeArc = function (x, y, radius, startAngle, endAngle, anticlockwise, color) {
return _this
.plotArc(x, y, radius, startAngle, endAngle, anticlockwise)
.stroke(color);
};
/**
* Plot an arc and apply a fill to it.
*/
this.fillArc = function (x, y, radius, startAngle, endAngle, anticlockwise, color) {
return _this
.plotArc(x, y, radius, startAngle, endAngle, anticlockwise)
.fill(color);
};
/**
* Plot an ellipse that can then have a stroke or fill applied to it.
* @alias ellipse
*/
this.plotEllipse = function (x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise) {
return _this.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);
};
this.ellipse = function (x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise) {
// tslint:disable-next-line:strict-type-predicates
if (typeof _this.ctx.ellipse === 'function') {
_this.ctx.ellipse(x * _this.density, y * _this.density, radiusX * _this.density, radiusY * _this.density, rotation, startAngle, endAngle, anticlockwise || false);
return _this;
}
return _this
.save()
.translate(x, y)
.rotate(rotation)
.scale(1, radiusY / radiusX)
.plotArc(0, 0, radiusX, startAngle, endAngle, anticlockwise)
.restore();
};
/**
* Plot an ellipse and apply a stroke to it.
*/
this.strokeEllipse = function (x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise, color) {
return _this
.plotEllipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
.stroke(color);
};
/**
* Plot an ellipse and apply a fill to it.
*/
this.fillEllipse = function (x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise, color) {
return _this
.plotEllipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
.fill(color);
};
/**
* @group Text
* @description A collection of methods for drawing text,
* and getting and setting properties related to text rendering.
*/
/**
* Draw a text with a stroke.
*/
this.strokeText = function (text, x, y, maxWidth, color) {
if (typeof color !== 'undefined') {
_this.setStroke(color);
}
if (typeof maxWidth !== 'number') {
_this.ctx.strokeText(text, x * _this.density, y * _this.density);
}
else {
_this.ctx.strokeText(text, x * _this.density, y * _this.density, maxWidth * _this.density);
}
return _this;
};
/**
* Draw a text with a fill.
*/
this.fillText = function (text, x, y, maxWidth, color) {
if (typeof color !== 'undefined') {
_this.setFill(color);
}
// If max width is not a number (e.g. undefined) then iOS does not draw anything
if (typeof maxWidth !== 'number') {
_this.ctx.fillText(text, x * _this.density, y * _this.density);
}
else {
_this.ctx.fillText(text, x * _this.density, y * _this.density, maxWidth * _this.density);
}
return _this;
};
/**
* Draw text with a stroke, wrapped at newlines and automatically wrapped if the text exceeds the maxWidth.
* If no maxWidth is specified text will only wrap at newlines (wordBreak is ignore).
* Words will not break by default (normal) and therefore may overflow.
* break-all will break words wherever possible, and break-word will only break words if there is not enough room.
* The lineHeight parameter is a multiplier for the font size, and defaults to 1.
*/
this.strokeTextMultiline = function (text, x, y, maxWidth, wordBreak, lineHeight, color) {
return _this.textMultiline(_this.strokeText, text, x, y, maxWidth, wordBreak, lineHeight, color);
};
/**
* Draw text with a fill, wrapped at newlines and automatically wrapped if the text exceeds the maxWidth.
* If no maxWidth is specified text will only wrap at newlines (wordBreak is ignore).
* Words will not break by default (normal) and therefore may overflow.
* break-all will break words wherever possible, and break-word will only break words if there is not enough room.
* The lineHeight parameter is a multiplier for the font size, and defaults to 1.
*/
this.fillTextMultiline = function (text, x, y, maxWidth, wordBreak, lineHeight, color) {
return _this.textMultiline(_this.fillText, text, x, y, maxWidth, wordBreak, lineHeight, color);
};
/**
* Get information about the size text will be drawn.
* @alias measureText
*/
this.getTextSize = function (text) { return _this.measureText(text); };
this.measureText = function (text) {
var metrics = _this.ctx.measureText(text);
return {
width: (metrics.width || 0) / _this.density,
};
};
/**
* Set the horizontal text alignment.
*/
this.setTextAlign = function (value) { return _this.setCanvasProperty('textAlign', value); };
/**
* Get the horizontal text alignment.
*/
this.getTextAlign = function () { return _this.getCanvasProperty('textAlign'); };
/**
* Set the vertical text alignment.
*/
this.setTextBaseline = function (value) { return _this.setCanvasProperty('textBaseline', value); };
/**
* Get the vertical text alignment.
*/
this.getTextBaseline = function () { return _this.getCanvasProperty('textBaseline'); };
/**
* @group Fonts
* @description A collection of methods for getting and setting font styles and variations.
*/
/**
* Set the font to use.
*/
this.setFont = function (font) {
_this.ctx.font = utils_1.formatFont(font, _this.density, false);
return _this;
};
/**
* Get the font that is being used.
* This returns the exact CanvasRenderingContext2D.font string.
*/
this.getFont = function () {
return utils_1.formatFont(_this.ctx.font, _this.density, true);
};
/**
* Set the font family to use.
*/
this.setFontFamily = function (family) {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return _this.setFont('');
}
parts[4] = family || constants_1.DEFAULT_FONT_PARTS[4];
_this.ctx.font = utils_1.formatFont(parts.join(' '), _this.density, false);
return _this;
};
/**
* Get the font that is being used.
*/
this.getFontFamily = function () {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return null;
}
return parts[4];
};
/**
* Set the font size to use.
*/
this.setFontSize = function (size) {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return _this.setFont('');
}
parts[3] = (typeof size === 'number' ? size + 'px' : size) || constants_1.DEFAULT_FONT_PARTS[3];
_this.ctx.font = utils_1.formatFont(parts.join(' '), _this.density, false);
return _this;
};
/**
* Get the font size that is being used.
* Returns null if using a special font e.g. caption, icon, menu.
*/
this.getFontSize = function () {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return null;
}
return parseFloat(parts[3]);
};
/**
* Set the font style to use.
*/
this.setFontStyle = function (style) {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return _this.setFont('');
}
parts[0] = style || constants_1.DEFAULT_FONT_PARTS[0];
_this.ctx.font = utils_1.formatFont(parts.join(' '), _this.density, false);
return _this;
};
/**
* Get the font style that is being used.
* Returns null if using a special font e.g. caption, icon, menu.
*/
this.getFontStyle = function () {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return null;
}
return parts[0];
};
/**
* Set the font variant to use.
*/
this.setFontVariant = function (variant) {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return _this.setFont('');
}
parts[1] = variant || constants_1.DEFAULT_FONT_PARTS[1];
_this.ctx.font = utils_1.formatFont(parts.join(' '), _this.density, false);
return _this;
};
/**
* Get the font variant that is being used.
* Returns null if using a special font e.g. caption, icon, menu.
*/
this.getFontVariant = function () {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return null;
}
return parts[1];
};
/**
* Set the font weight to use.
*/
this.setFontWeight = function (weight) {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return _this.setFont('');
}
parts[2] = weight.toString() || constants_1.DEFAULT_FONT_PARTS[2];
_this.ctx.font = utils_1.formatFont(parts.join(' '), _this.density, false);
return _this;
};
/**
* Get the font weight that is being used.
* Returns null if using a special font e.g. caption, icon, menu.
*/
this.getFontWeight = function () {
var parts = utils_1.getFontParts(_this.ctx.font, _this.density, true);
if (parts.length < 5) {
return null;
}
return parts[2];
};
/**
* @group Stroke Styles
* @description A collection of methods for getting and setting stroke styles,
* and applying strokes to existing shapes.
*/
/**
* Apply a stroke to the current shape.
*/
this.stroke = function (color, path) {
if (typeof color === 'string') {
_this.setStroke(color);
// tslint:disable-next-line:strict-type-predicates
if (path && typeof path === 'object') {
_this.ctx.stroke(path);
}
else {
_this.ctx.stroke();
}
// tslint:disable-next-line:strict-type-predicates
}
else if (color && typeof color === 'object') {
_this.ctx.stroke(color);
// tslint:disable-next-line:strict-type-predicates
}
else if (path && typeof path === 'object') {
_this.ctx.stroke(path);
}
else {
_this.ctx.stroke();
}
return _this;
};
/**
* Set the stroke style to use.
* @alias setStrokeStyle
*/
this.setStroke = function (value) { return _this.setStrokeStyle(value); };
this.setStrokeStyle = function (value) { return _this.setCanvasProperty('strokeStyle', value); };
/**
* Get the stroke style that is being used.
* @alias getStrokeStyle
*/
this.getStroke = function () { return _this.getStrokeStyle(); };
this.getStrokeStyle = function () { return _this.getCanvasProperty('strokeStyle'); };
/**
* Set the stroke cap to use.
* @alias setLineCap
*/
this.setStrokeCap = function (value) { return _this.setLineCap(value); };
this.setLineCap = function (value) { return _this.setCanvasProperty('lineCap', value); };
/**
* Get the stroke cap that is being used.
* @alias getLineCap
*/
this.getStrokeCap = function () { return _this.getLineCap(); };
this.getLineCap = function () { return _this.getCanvasProperty('lineCap'); };
/**
* Set the stroke dash to use.
* @alias setLineDash
*/
this.setStrokeDash = function (segments) { return _this.setLineDash(segments); };
this.setLineDash = function (segments) {
// tslint:disable-next-line:strict-type-predicates
if (typeof _this.ctx.setLineDash !== 'function') {
logUnsupportedMethodError('setLineDash');
return _this;
}
_this.ctx.setLineDash(segments.map(function (segment) { return segment * _this.density; }));
return _this;
};
/**
* Get the stroke dash that is being used.
* @alias getLineDash
*/
this.getStrokeDash = function () { return _this.getLineDash(); };
this.getLineDash = function () {
// tslint:disable-next-line:strict-type-predicates
if (typeof _this.ctx.getLineDash !== 'function') {
logUnsupportedMethodError('getLineDash');
return [];
}
return (_this.ctx.getLineDash() || []).map(function (value) { return value / _this.density; });
};
/**
* Set the stroke dash offset to use.
* @alias setLineDashOffset
*/
this.setStrokeDashOffset = function (value) { return _this.setLineDashOffset(value); };
this.setLineDashOffset = function (value) {
return _this.setCanvasProperty('lineDashOffset', value * _this.density);
};
/**
* Get the stroke dash offset that is being used.
* @alias getLineDashOffset
*/
this.getStrokeDashOffset = function () { return _this.getLineDashOffset(); };
this.getLineDashOffset = function () { return _this.getCanvasProperty('lineDashOffset') / _this.density; };
/**
* Set the stroke join to use.
* @alias setLineJoin
*/
this.setStrokeJoin = function (value) { return _this.setLineJoin(value); };
this.setLineJoin = function (value) { return _this.setCanvasProperty('lineJoin', value); };
/**
* Get the stroke join that is being used.
* @alias getLineJoin
*/
this.getStrokeJoin = function () { return _this.getLineJoin(); };
this.getLineJoin = function () { return _this.getCanvasProperty('lineJoin'); };
/**
* Set the stroke width to use.
* @alias setLineWidth
*/
this.setStrokeWidth = function (value) { return _this.setLineWidth(value); };
this.setLineWidth = function (value) { return _this.setCanvasProperty('lineWidth', value * _this.density); };
/**
* Get the stroke width that is being used.
* @alias getLineWidth
*/
this.getStrokeWidth = function () { return _this.getLineWidth(); };
this.getLineWidth = function () { return _this.getCanvasProperty('lineWidth') / _this.density; };
/**
* Set the miter limit to use.
*/
this.setMiterLimit = function (value) { return _this.setCanvasProperty('miterLimit', value * _this.density); };
/**
* Get the miter limit that is being used.
*/
this.getMiterLimit = function () { return _this.getCanvasProperty('miterLimit') / _this.density; };
/**
* @group Fill styles
* @description A collection of methods for getting and setting fill styles,
* and applying fills to existing shapes.
*/
/**
* Apply a fill to the current shape.
*/
this.fill = function (color, fillRule) {
if (utils_1.isFillRule(color)) {
_this.ctx.fill(color);
}
else if (typeof color === 'string') {
_this.setFill(color);
if (fillRule) {
_this.ctx.fill(fillRule);
}
else {
_this.ctx.fill();
}
}
else {
_this.ctx.fill(fillRule);
}
return _this;
};
/**
* Apply a fill to the entire canvas area.
*/
this.fillCanvas = function (color) {
return _this
.resetTransform()
.fillRect(0, 0, _this.getWidth(), _this.getHeight(), color);
};
/**
* Clear the entire canvas area
*/
this.clearCanvas = function () {
return _this.setWidth(_this.getWidth());
};
/**
* Clear a rectangular area of the canvas.
*/
this.clearRect = function (x, y, width, height) {
_this.ctx.clearRect(x * _this.density, y * _this.density, width * _this.density, height * _this.density);
return _this;
};
/**
* Set the fill to use.
* @alias setFillStyle
*/
this.setFill = function (value) { return _this.setFillStyle(value); };
this.setFillStyle = function (value) { return _this.setCanvasProperty('fillStyle', value); };
/**
* Get the fill that is being used.
* @alias getFillStyle
*/
this.getFill = function () { return _this.getFillStyle(); };
this.getFillStyle = function () { return _this.getCanvasProperty('fillStyle'); };
/**
* Create a linear gradient to use as a fill.
*/
this.createLinearGradient = function (x0, y0, x1, y1) {
return _this.ctx.createLinearGradient(x0 * _this.density, y0 * _this.density, x1 * _this.density, y1 * _this.density);
};
/**
* Create a radial gradient to use as a fill.
*/
this.createRadialGradient = function (x0, y0, r0, x1, y1, r1) {
return _this.ctx.createRadialGradient(x0 * _this.density, y0 * _this.density, r0 * _this.density, x1 * _this.density, y1 * _this.density, r1 * _this.density);
};
/**
* Create a pattern to be used as a fill.
*/
this.createPattern = function (image, repetition) {
return _this.ctx.createPattern(image, repetition);
};
/**
* Draw an image to the canvas.
* If the second position / size arguments are supplied, the first will be used for cropping the image,
* and the second for the position and size it will be drawn.
*/
this.drawImage = function (image, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH) {
if (typeof srcW !== 'undefined' &&
typeof srcH !== 'undefined') {
if (typeof dstX !== 'undefined' &&
typeof dstY !== 'undefined' &&
typeof dstW !== 'undefined' &&
typeof dstH !== 'undefined') {
_this.ctx.drawImage(image, srcX * _this.density, srcY * _this.density, srcW * _this.density, srcH * _this.density, dstX * _this.density, dstY * _this.density, dstW * _this.density, dstH * _this.density);
}
else {
_this.ctx.drawImage(image, srcX * _this.density, srcY * _this.density, srcW * _this.density, srcH * _this.density);
}
}
else {
_this.ctx.drawImage(image, srcX * _this.density, srcY * _this.density);
}
return _this;
};
/**
* @group Image Data
* @description A collection of methods for creating, putting, or getting image data about the canvas.
*/
/**
* Get a data URL of the current canvas state.
*/
this.getDataURL = function (type) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var _a;
return (_a = _this.element).toDataURL.apply(_a, [type].concat(args));
};
/**
* Create image data with either the width and height specified,
* or with the width and height of a the image data supplied.
*/
this.createImageData = function (width, height) {
if (typeof width !== 'number') {
return _this.ctx.createImageData(width);
}
return _this.ctx.createImageData(width * _this.density, height || 0 * _this.density);
};
/**
* Get the image data from an area of the canvas.
*/
this.getImageData = function (sx, sy, sw, sh) {
return _this.ctx.getImageData(sx * _this.density, sy * _this.density, sw * _this.density, sh * _this.density);
};
/**
* Draw image data onto the canvas.
*/
this.putImageData = function (imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight) {
if (typeof dirtyX === 'undefined' ||
typeof dirtyY === 'undefined' ||
typeof dirtyWidth === 'undefined' ||
typeof dirtyHeight === 'undefined') {
_this.ctx.putImageData(imagedata, dx * _this.density, dy * _this.density);
}
else {
_this.ctx.putImageData(imagedata, dx * _this.density, dy * _this.density, dirtyX * _this.density, dirtyY * _this.density, dirtyWidth * _this.density, dirtyHeight * _this.density);
}
return _this;
};
/**
* Get image data about a specific pixel.
*/
this.getPixelData = function (x, y) {
return _this.getImageData(x, y, 1, 1).data;
};
/**
* Get the color of a specific pixel.
*/
this.getPixelColor = function (x, y) {
var data = _this.getImageData(x, y, 1, 1).data;
return _this.createRGBA(data[0], data[1], data[2], data[3]);
};
/**
* @group Color Helpers
* @description A collection of methods to help with creating color strings.
*/
/**
* Create an HSL color string from the given values.
*/
this.createHSL = function (h, s, l) {
return 'hsl(' + h + ',' + s + '%,' + l + '%)';
};
/**
* Create an HSLA color string from the given values.
*/
this.createHSLA = function (h, s, l, a) {
return 'hsla(' + h + ',' + s + '%,' + l + '%,' + a + ')';
};
/**
* Create an RGB color string from the given values.
*/
this.createRGB = function (r, g, b) {
return 'rgb(' + r + ',' + g + ',' + b + ')';
};
/**
* Create an RGBA color string from the given values.
*/
this.createRGBA = function (r, g, b, a) {
return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
};
/**
* Return an HSL color string from the given HSLA color string.
*/
this.getHSLFromHSLA = function (color) { return _this.getRGBFromRGBA(color); };
/**
* Return an RGB color string from the given RGBA color string.
*/
this.getRGBFromRGBA = function (color) {
var lastCommaIndex = color.lastIndexOf(',');
return color.replace(/^(\w{3})a/, '$1').substring(0, lastCommaIndex - 1) + ')';
};
/**
* @group Converting Sizes
* @description A collection of methods to help with calculating and converting sizes, and distances.
*/
/**
* Get a fraction from the provided percent value e.g. 80 returns 0.8.
*/
this.getFractionFromPercent = function (percent) {
return (percent / 100);
};
/**
* Get a percent from the provided fraction value e.g. 0.7 returns 70.
*/
this.getPercentFromFraction = function (fraction) {
return (fraction * 100);
};
/**
* Returns the actual value of a fraction of the canvas width e.g.
* a canvas with a width of 200 returns 100 if the provided value is 0.5.
*/
this.getFractionOfWidth = function (fraction) {
return _this.getWidth() * fraction;
};
/**
* Returns the actual value of a fraction of the canvas height e.g.
* a canvas with a height of 100 returns 20 if the provided value is 0.2.
*/
this.getFractionOfHeight = function (fraction) {
return _this.getHeight() * fraction;
};
/**
* Returns the actual value of a percentage of the canvas width e.g.
* a canvas with a width of 200 returns 100 if the provided value is 50.
*/
this.getPercentOfWidth = function (percent) {
return _this.getWidth() / 100 * percent;
};
/**
* Returns the actual value of a percentage of the canvas height e.g.
* a canvas with a height of 100 returns 20 if the provided value is 20.
*/
this.getPercentOfHeight = function (percent) {
return _this.getHeight() / 100 * percent;
};
/**
* Returns the distance between 2 points.
*/
this.getDistance = function (x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
};
/**
* @group Converting Angles
* @description A collection of methods to help with calculating and converting angles.
*/
/**
* Get a radian value from the provided degrees e.g. 90 returns 1.5708.
*/
this.getRadiansFromDegrees = function (degrees) {
return degrees * Math.PI / 180;
};
/**
* Get a degree value from the provided radians e.g. 3.14159 returns 180.
*/
this.getDegreesFromRadians = function (radians) {
return radians * 180 / Math.PI;
};
/**
* Get the angle (in radians) between 2 or 3 points.
*/
this.getAngle = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (!args.length || !(args.length === 4 || args.length === 6)) {
throw new Error(constants_1.INCORRECT_GET_ANGLE_ARGUMENTS);
}
var x1 = args[0];
var y1 = args[1];
var x2 = args[2];
var y2 = args[3];
if (args.length === 4) {
return Math.atan2(y2 - y1, x2 - x1);
}
var x3 = args[4];
var y3 = args[5];
var a = _this.getAngle(x1, y1, x2, y2);
var b = _this.getAngle(x2, y2, x3, y3);
var c = b - a;
if (c >= 0) {
return Math.PI - c;
}
return -Math.PI - c;
};
/**
* @group Path Plotting
* @description A collection of methods for path drawing.
*/
/**
* Begin a new path (shape).
*/
this.beginPath = function () {
_this.ctx.beginPath();
return _this;
};
/**
* Close the current path (shape).
*/
this.closePath = function () {
_this.ctx.closePath();
return _this;
};
/**
* Move the starting point of a the next sub-path.
*/
this.moveTo = function (x, y) {
_this.ctx.moveTo(x * _this.density, y * _this.density);
return _this;
};
/**
* Connect the last point to the provided coordinates.
*/
this.lineTo = function (x, y) {
_this.ctx.lineTo(x * _this.density, y * _this.density);
return _this;
};
/**
* Arc from one point to another.
*/
this.arcTo = function (x1, y1, x2, y2, radius) {
_this.ctx.arcTo(x1 * _this.density, y1 * _this.density, x2 * _this.density, y2 * _this.density, radius * _this.density);
return _this;
};
/**
* Connect the last point to the provided coordinates with a bezier curve (2 control points).
*/
this.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
_this.ctx.bezierCurveTo(cp1x * _this.density, cp1y * _this.density, cp2x * _this.density, cp2y * _this.density, x * _this.density, y * _this.density);
return _this;
};
/**
* Connect the last point to the provided coordinates with a quadratic curve (1 control point).
*/
this.quadraticCurveTo = function (cpx, cpy, x, y) {
_this.ctx.quadraticCurveTo(cpx * _this.density, cpy * _this.density, x * _this.density, y * _this.density);
return _this;
};
/**
* @group Canvas State
* @description A collection of methods to save, restore, or transform the canvas state.
*/
/**
* Push the current state of the canvas into a stack that can later be restored.
*/
this.save = function () {
_this.ctx.save();
return _this;
};
/**
* Restore the most recent state of the canvas that was saved.
*/
this.restore = function () {
_this.ctx.restore();
return _this;
};
/**
* Add rotation (in radians) to the transform matrix so that shapes can be drawn at an angle.
*/
this.rotate = function (angle) {
_this.ctx.rotate(angle);
return _this;
};
/**
* Scale the transform matrix so that shapes can be drawn at the provided scale.
*/
this.scale = function (x, y) {
_this.ctx.scale(x, y);
return _this;
};
/**
* Move the canvas origin.