UNPKG

canvasimo

Version:

An HTML5 canvas drawing library, with 150+ useful methods, jQuery-like fluent interface, and cross-browser compatibility enhancements.

1,243 lines (1,242 loc) 82.1 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.canvasimo = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PROPERTY_MAP = { globalAlpha: 'opacity', globalCompositeOperation: 'compositeOperation', fillStyle: 'fill', strokeStyle: 'stroke', lineWidth: 'strokeWidth', lineCap: 'strokeCap', lineJoin: 'strokeJoin', lineDashOffset: 'strokeDashOffset', miterLimit: 'miterLimit', shadowColor: 'shadowColor', shadowBlur: 'shadowBlur', shadowOffsetX: 'shadowOffsetX', shadowOffsetY: 'shadowOffsetY', textAlign: 'textAlign', textBaseline: 'textBaseline', }; exports.IMAGE_SMOOTHING_KEYS = [ 'imageSmoothingEnabled', 'msImageSmoothingEnabled', 'mozImageSmoothingEnabled', 'webkitImageSmoothingEnabled', ]; exports.IMAGE_SMOOTHING_QUALITY_KEYS = [ 'imageSmoothingQuality', 'msImageSmoothingQuality', 'mozImageSmoothingQuality', 'webkitImageSmoothingQuality', ]; exports.CONTEXT_TYPE = '2d'; exports.INCORRECT_POINT_FORMAT = "Path points must be an array of:\n\n numbers [x, y, x, y], pairs [[x, y], [x, y]], or objects [{x, y}, {x, y}]."; exports.INCORRECT_GET_ANGLE_ARGUMENTS = 'Incorrect number of arguments supplied for getAngle. ' + 'Arguments must be [x1, y1, x2, y2] or [x1, y1, x2, y2, x3, y3].'; exports.DEFAULT_FONT_PARTS = ['normal', 'normal', 'normal', '10px', 'sans-serif']; exports.DEFAULT_FONT = exports.DEFAULT_FONT_PARTS.join(' '); exports.DEFAULT_DENSITY = 1; exports.MATCHES_SPECIAL_FILL = /^(nonzero|evenodd)$/i; exports.MATCHES_NORMAL = /^(normal)$/i; exports.MATCHES_FONT_STYLE = /^(italic|oblique)$/i; exports.MATCHES_FONT_VARIANT = /^(small-caps)$/i; exports.MATCHES_FONT_WEIGHT = /^(bold|bolder|lighter|\d00)$/i; exports.MATCHES_SPECIAL_FONT = /^(caption|icon|menu|message-box|small-caption|status-bar)$/i; exports.MATCHES_WHITESPACE = /\s+/g; exports.MATCHES_ALL_WHITESPACE = /^\s*$/; exports.MATCHES_FONT_SIZE = /(^|\s+)(\d*\.?\d+)([a-z]+|%)(\/\d*\.?\d+(?:[a-z]+|%)?)?\s/i; exports.MATCHES_WORD_BREAKS = /(?![^\w\s])\b/g; exports.DEFAULT_CONTEXT_VALUES = { globalAlpha: 1, globalCompositeOperation: 'source-over', strokeStyle: '#000000', fillStyle: '#000000', shadowOffsetX: 0, shadowOffsetY: 0, shadowBlur: 0, shadowColor: 'rgba(0, 0, 0, 0)', lineWidth: 1, lineCap: 'butt', lineJoin: 'miter', miterLimit: 10, lineDashOffset: 0, font: exports.DEFAULT_FONT, textAlign: 'start', textBaseline: 'alphabetic', }; exports.DEFAULT_IMAGE_SMOOTHING_VALUES = { imageSmoothingEnabled: true, imageSmoothingQuality: 'low', }; exports.DEFAULT_LINE_DASH = []; },{}],2:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // tslint:disable-next-line:no-var-requires var VERSION = _dereq_('../package.json').version; var constants_1 = _dereq_("./constants"); var logger_1 = _dereq_("./logger"); var utils_1 = _dereq_("./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