UNPKG

micro-editor

Version:

1. npm install

142 lines (131 loc) 1.02 MB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["editor"] = factory(); else root["editor"] = factory(); })(window, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./src/components/photo-editor.tsx"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./node_modules/@emotion/is-prop-valid/dist/is-prop-valid.browser.esm.js": /*!*******************************************************************************!*\ !*** ./node_modules/@emotion/is-prop-valid/dist/is-prop-valid.browser.esm.js ***! \*******************************************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _emotion_memoize__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @emotion/memoize */ \"./node_modules/@emotion/memoize/dist/memoize.browser.esm.js\");\n\n\nvar reactPropsRegex = /^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|suppressHydrationWarning|valueLink|accept|acceptCharset|accessKey|action|allow|allowUserMedia|allowPaymentRequest|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|default|defer|dir|disabled|download|draggable|encType|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|itemProp|itemScope|itemType|itemID|itemRef|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class|autofocus)|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/; // https://esbench.com/bench/5bfee68a4cd7e6009ef61d23\n\nvar index = Object(_emotion_memoize__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(function (prop) {\n return reactPropsRegex.test(prop) || prop.charCodeAt(0) === 111\n /* o */\n && prop.charCodeAt(1) === 110\n /* n */\n && prop.charCodeAt(2) < 91;\n}\n/* Z+1 */\n);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (index);\n\n\n//# sourceURL=webpack://editor/./node_modules/@emotion/is-prop-valid/dist/is-prop-valid.browser.esm.js?"); /***/ }), /***/ "./node_modules/@emotion/memoize/dist/memoize.browser.esm.js": /*!*******************************************************************!*\ !*** ./node_modules/@emotion/memoize/dist/memoize.browser.esm.js ***! \*******************************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\nfunction memoize(fn) {\n var cache = {};\n return function (arg) {\n if (cache[arg] === undefined) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (memoize);\n\n\n//# sourceURL=webpack://editor/./node_modules/@emotion/memoize/dist/memoize.browser.esm.js?"); /***/ }), /***/ "./node_modules/@emotion/unitless/dist/unitless.browser.esm.js": /*!*********************************************************************!*\ !*** ./node_modules/@emotion/unitless/dist/unitless.browser.esm.js ***! \*********************************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\nvar unitlessKeys = {\n animationIterationCount: 1,\n borderImageOutset: 1,\n borderImageSlice: 1,\n borderImageWidth: 1,\n boxFlex: 1,\n boxFlexGroup: 1,\n boxOrdinalGroup: 1,\n columnCount: 1,\n columns: 1,\n flex: 1,\n flexGrow: 1,\n flexPositive: 1,\n flexShrink: 1,\n flexNegative: 1,\n flexOrder: 1,\n gridRow: 1,\n gridRowEnd: 1,\n gridRowSpan: 1,\n gridRowStart: 1,\n gridColumn: 1,\n gridColumnEnd: 1,\n gridColumnSpan: 1,\n gridColumnStart: 1,\n msGridRow: 1,\n msGridRowSpan: 1,\n msGridColumn: 1,\n msGridColumnSpan: 1,\n fontWeight: 1,\n lineHeight: 1,\n opacity: 1,\n order: 1,\n orphans: 1,\n tabSize: 1,\n widows: 1,\n zIndex: 1,\n zoom: 1,\n WebkitLineClamp: 1,\n // SVG-related properties\n fillOpacity: 1,\n floodOpacity: 1,\n stopOpacity: 1,\n strokeDasharray: 1,\n strokeDashoffset: 1,\n strokeMiterlimit: 1,\n strokeOpacity: 1,\n strokeWidth: 1\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (unitlessKeys);\n\n\n//# sourceURL=webpack://editor/./node_modules/@emotion/unitless/dist/unitless.browser.esm.js?"); /***/ }), /***/ "./node_modules/konva/konva.js": /*!*************************************!*\ !*** ./node_modules/konva/konva.js ***! \*************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { eval("/* WEBPACK VAR INJECTION */(function(global) {/*\n * Konva JavaScript Framework v2.6.0\n * http://konvajs.github.io/\n * Licensed under the MIT\n * Date: Fri Dec 14 2018\n *\n * Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)\n * Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva)\n *\n * @license\n */\n\n// runtime check for already included Konva\n(function() {\n 'use strict';\n /**\n * @namespace Konva\n */\n\n var PI_OVER_180 = Math.PI / 180;\n\n var Konva = {\n // public\n version: '2.6.0',\n\n // private\n stages: [],\n idCounter: 0,\n ids: {},\n names: {},\n shapes: {},\n listenClickTap: false,\n inDblClickWindow: false,\n\n isBrowser:\n typeof window !== 'undefined' &&\n // browser case\n ({}.toString.call(window) === '[object Window]' ||\n // electron case\n {}.toString.call(window) === '[object global]'),\n\n isUnminified: /comment/.test(function() {\n /* comment */\n }),\n\n // configurations\n enableTrace: false,\n traceArrMax: 100,\n dblClickWindow: 400,\n /**\n * Global pixel ratio configuration. KonvaJS automatically detect pixel ratio of current device.\n * But you may override such property, if you want to use your value.\n * @property pixelRatio\n * @default undefined\n * @memberof Konva\n * @example\n * Konva.pixelRatio = 1;\n */\n pixelRatio: undefined,\n /**\n * Drag distance property. If you start to drag a node you may want to wait until pointer is moved to some distance from start point,\n * only then start dragging. Default is 3px.\n * @property dragDistance\n * @default 0\n * @memberof Konva\n * @example\n * Konva.dragDistance = 10;\n */\n dragDistance: 3,\n /**\n * Use degree values for angle properties. You may set this property to false if you want to use radiant values.\n * @property angleDeg\n * @default true\n * @memberof Konva\n * @example\n * node.rotation(45); // 45 degrees\n * Konva.angleDeg = false;\n * node.rotation(Math.PI / 2); // PI/2 radian\n */\n angleDeg: true,\n /**\n * Show different warnings about errors or wrong API usage\n * @property showWarnings\n * @default true\n * @memberof Konva\n * @example\n * Konva.showWarnings = false;\n */\n showWarnings: true,\n\n /**\n * @namespace Filters\n * @memberof Konva\n */\n Filters: {},\n\n /**\n * returns whether or not drag and drop is currently active\n * @method\n * @memberof Konva\n */\n isDragging: function() {\n var dd = Konva.DD;\n\n // if DD is not included with the build, then\n // drag and drop is not even possible\n if (dd) {\n return dd.isDragging;\n }\n return false;\n },\n /**\n * returns whether or not a drag and drop operation is ready, but may\n * not necessarily have started\n * @method\n * @memberof Konva\n */\n isDragReady: function() {\n var dd = Konva.DD;\n\n // if DD is not included with the build, then\n // drag and drop is not even possible\n if (dd) {\n return !!dd.node;\n }\n return false;\n },\n _addId: function(node, id) {\n if (!id) {\n return;\n }\n // do we need this warning?\n // if (this.ids[id]) {\n // Konva.Util.warn(\n // 'Duplicate id \"' +\n // id +\n // '\". Please don not use same id several times. It may break find() method look up.'\n // );\n // }\n this.ids[id] = node;\n },\n _removeId: function(id) {\n if (id !== undefined) {\n delete this.ids[id];\n }\n },\n _addName: function(node, name) {\n if (name) {\n if (!this.names[name]) {\n this.names[name] = [];\n }\n this.names[name].push(node);\n }\n },\n _removeName: function(name, _id) {\n if (!name) {\n return;\n }\n var nodes = this.names[name];\n if (!nodes) {\n return;\n }\n for (var n = 0; n < nodes.length; n++) {\n var no = nodes[n];\n if (no._id === _id) {\n nodes.splice(n, 1);\n }\n }\n if (nodes.length === 0) {\n delete this.names[name];\n }\n },\n getAngle: function(angle) {\n return this.angleDeg ? angle * PI_OVER_180 : angle;\n },\n _detectIE: function(ua) {\n var msie = ua.indexOf('msie ');\n if (msie > 0) {\n // IE 10 or older => return version number\n return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);\n }\n\n var trident = ua.indexOf('trident/');\n if (trident > 0) {\n // IE 11 => return version number\n var rv = ua.indexOf('rv:');\n return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);\n }\n\n var edge = ua.indexOf('edge/');\n if (edge > 0) {\n // Edge (IE 12+) => return version number\n return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);\n }\n\n // other browser\n return false;\n },\n _parseUA: function(userAgent) {\n var ua = userAgent.toLowerCase(),\n // jQuery UA regex\n match =\n /(chrome)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+)/.exec(ua) ||\n /(opera)(?:.*version|)[ /]([\\w.]+)/.exec(ua) ||\n /(msie) ([\\w.]+)/.exec(ua) ||\n (ua.indexOf('compatible') < 0 &&\n /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec(ua)) ||\n [],\n // adding mobile flag as well\n mobile = !!userAgent.match(\n /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i\n ),\n ieMobile = !!userAgent.match(/IEMobile/i);\n\n return {\n browser: match[1] || '',\n version: match[2] || '0',\n isIE: Konva._detectIE(ua),\n // adding mobile flab\n mobile: mobile,\n ieMobile: ieMobile // If this is true (i.e., WP8), then Konva touch events are executed instead of equivalent Konva mouse events\n };\n },\n // user agent\n UA: undefined\n };\n\n var glob =\n typeof global !== 'undefined'\n ? global\n : typeof window !== 'undefined'\n ? window\n : typeof WorkerGlobalScope !== 'undefined'\n ? self\n : {};\n\n Konva.UA = Konva._parseUA((glob.navigator && glob.navigator.userAgent) || '');\n\n if (glob.Konva) {\n console.error(\n 'Konva instance is already exist in current eviroment. ' +\n 'Please use only one instance.'\n );\n }\n glob.Konva = Konva;\n Konva.global = glob;\n Konva.window = glob;\n Konva.document = glob.document;\n\n if (true) {\n module.exports = Konva;\n } else {}\n})();\n\n/*eslint-disable eqeqeq, no-cond-assign, no-empty*/\n(function() {\n 'use strict';\n /**\n * Collection constructor. Collection extends\n * Array. This class is used in conjunction with {@link Konva.Container#get}\n * @constructor\n * @memberof Konva\n */\n Konva.Collection = function() {\n var args = [].slice.call(arguments),\n length = args.length,\n i = 0;\n\n this.length = length;\n for (; i < length; i++) {\n this[i] = args[i];\n }\n return this;\n };\n Konva.Collection.prototype = [];\n /**\n * iterate through node array and run a function for each node.\n * The node and index is passed into the function\n * @method\n * @memberof Konva.Collection.prototype\n * @param {Function} func\n * @example\n * // get all nodes with name foo inside layer, and set x to 10 for each\n * layer.get('.foo').each(function(shape, n) {\n * shape.setX(10);\n * });\n */\n Konva.Collection.prototype.each = function(func) {\n for (var n = 0; n < this.length; n++) {\n func(this[n], n);\n }\n };\n /**\n * convert collection into an array\n * @method\n * @memberof Konva.Collection.prototype\n */\n Konva.Collection.prototype.toArray = function() {\n var arr = [],\n len = this.length,\n n;\n\n for (n = 0; n < len; n++) {\n arr.push(this[n]);\n }\n return arr;\n };\n /**\n * convert array into a collection\n * @method\n * @memberof Konva.Collection\n * @param {Array} arr\n */\n Konva.Collection.toCollection = function(arr) {\n var collection = new Konva.Collection(),\n len = arr.length,\n n;\n\n for (n = 0; n < len; n++) {\n collection.push(arr[n]);\n }\n return collection;\n };\n\n // map one method by it's name\n Konva.Collection._mapMethod = function(methodName) {\n Konva.Collection.prototype[methodName] = function() {\n var len = this.length,\n i;\n\n var args = [].slice.call(arguments);\n for (i = 0; i < len; i++) {\n this[i][methodName].apply(this[i], args);\n }\n\n return this;\n };\n };\n\n Konva.Collection.mapMethods = function(constructor) {\n var prot = constructor.prototype;\n for (var methodName in prot) {\n Konva.Collection._mapMethod(methodName);\n }\n };\n\n /*\n * Last updated November 2011\n * By Simon Sarris\n * www.simonsarris.com\n * sarris@acm.org\n *\n * Free to use and distribute at will\n * So long as you are nice to people, etc\n */\n\n /*\n * The usage of this class was inspired by some of the work done by a forked\n * project, KineticJS-Ext by Wappworks, which is based on Simon's Transform\n * class. Modified by Eric Rowell\n */\n\n /**\n * Transform constructor. Transform object is a private class of Konva framework.\n * In most of the cases you don't need to use it in your app.\n * But there is a documentation for that class in case you still want\n * to make some manual calculations.\n * @constructor\n * @param {Array} [m] Optional six-element matrix\n * @memberof Konva\n */\n Konva.Transform = function(m) {\n this.m = (m && m.slice()) || [1, 0, 0, 1, 0, 0];\n };\n\n Konva.Transform.prototype = {\n /**\n * Copy Konva.Transform object\n * @method\n * @memberof Konva.Transform.prototype\n * @returns {Konva.Transform}\n */\n copy: function() {\n return new Konva.Transform(this.m);\n },\n /**\n * Transform point\n * @method\n * @memberof Konva.Transform.prototype\n * @param {Object} point 2D point(x, y)\n * @returns {Object} 2D point(x, y)\n */\n point: function(point) {\n var m = this.m;\n return {\n x: m[0] * point.x + m[2] * point.y + m[4],\n y: m[1] * point.x + m[3] * point.y + m[5]\n };\n },\n /**\n * Apply translation\n * @method\n * @memberof Konva.Transform.prototype\n * @param {Number} x\n * @param {Number} y\n * @returns {Konva.Transform}\n */\n translate: function(x, y) {\n this.m[4] += this.m[0] * x + this.m[2] * y;\n this.m[5] += this.m[1] * x + this.m[3] * y;\n return this;\n },\n /**\n * Apply scale\n * @method\n * @memberof Konva.Transform.prototype\n * @param {Number} sx\n * @param {Number} sy\n * @returns {Konva.Transform}\n */\n scale: function(sx, sy) {\n this.m[0] *= sx;\n this.m[1] *= sx;\n this.m[2] *= sy;\n this.m[3] *= sy;\n return this;\n },\n /**\n * Apply rotation\n * @method\n * @memberof Konva.Transform.prototype\n * @param {Number} rad Angle in radians\n * @returns {Konva.Transform}\n */\n rotate: function(rad) {\n var c = Math.cos(rad);\n var s = Math.sin(rad);\n var m11 = this.m[0] * c + this.m[2] * s;\n var m12 = this.m[1] * c + this.m[3] * s;\n var m21 = this.m[0] * -s + this.m[2] * c;\n var m22 = this.m[1] * -s + this.m[3] * c;\n this.m[0] = m11;\n this.m[1] = m12;\n this.m[2] = m21;\n this.m[3] = m22;\n return this;\n },\n /**\n * Returns the translation\n * @method\n * @memberof Konva.Transform.prototype\n * @returns {Object} 2D point(x, y)\n */\n getTranslation: function() {\n return {\n x: this.m[4],\n y: this.m[5]\n };\n },\n /**\n * Apply skew\n * @method\n * @memberof Konva.Transform.prototype\n * @param {Number} sx\n * @param {Number} sy\n * @returns {Konva.Transform}\n */\n skew: function(sx, sy) {\n var m11 = this.m[0] + this.m[2] * sy;\n var m12 = this.m[1] + this.m[3] * sy;\n var m21 = this.m[2] + this.m[0] * sx;\n var m22 = this.m[3] + this.m[1] * sx;\n this.m[0] = m11;\n this.m[1] = m12;\n this.m[2] = m21;\n this.m[3] = m22;\n return this;\n },\n /**\n * Transform multiplication\n * @method\n * @memberof Konva.Transform.prototype\n * @param {Konva.Transform} matrix\n * @returns {Konva.Transform}\n */\n multiply: function(matrix) {\n var m11 = this.m[0] * matrix.m[0] + this.m[2] * matrix.m[1];\n var m12 = this.m[1] * matrix.m[0] + this.m[3] * matrix.m[1];\n\n var m21 = this.m[0] * matrix.m[2] + this.m[2] * matrix.m[3];\n var m22 = this.m[1] * matrix.m[2] + this.m[3] * matrix.m[3];\n\n var dx = this.m[0] * matrix.m[4] + this.m[2] * matrix.m[5] + this.m[4];\n var dy = this.m[1] * matrix.m[4] + this.m[3] * matrix.m[5] + this.m[5];\n\n this.m[0] = m11;\n this.m[1] = m12;\n this.m[2] = m21;\n this.m[3] = m22;\n this.m[4] = dx;\n this.m[5] = dy;\n return this;\n },\n /**\n * Invert the matrix\n * @method\n * @memberof Konva.Transform.prototype\n * @returns {Konva.Transform}\n */\n invert: function() {\n var d = 1 / (this.m[0] * this.m[3] - this.m[1] * this.m[2]);\n var m0 = this.m[3] * d;\n var m1 = -this.m[1] * d;\n var m2 = -this.m[2] * d;\n var m3 = this.m[0] * d;\n var m4 = d * (this.m[2] * this.m[5] - this.m[3] * this.m[4]);\n var m5 = d * (this.m[1] * this.m[4] - this.m[0] * this.m[5]);\n this.m[0] = m0;\n this.m[1] = m1;\n this.m[2] = m2;\n this.m[3] = m3;\n this.m[4] = m4;\n this.m[5] = m5;\n return this;\n },\n /**\n * return matrix\n * @method\n * @memberof Konva.Transform.prototype\n */\n getMatrix: function() {\n return this.m;\n },\n /**\n * set to absolute position via translation\n * @method\n * @memberof Konva.Transform.prototype\n * @returns {Konva.Transform}\n * @author ericdrowell\n */\n setAbsolutePosition: function(x, y) {\n var m0 = this.m[0],\n m1 = this.m[1],\n m2 = this.m[2],\n m3 = this.m[3],\n m4 = this.m[4],\n m5 = this.m[5],\n yt = (m0 * (y - m5) - m1 * (x - m4)) / (m0 * m3 - m1 * m2),\n xt = (x - m4 - m2 * yt) / m0;\n\n return this.translate(xt, yt);\n }\n };\n\n // CONSTANTS\n var CONTEXT_2D = '2d',\n OBJECT_ARRAY = '[object Array]',\n OBJECT_NUMBER = '[object Number]',\n OBJECT_STRING = '[object String]',\n OBJECT_BOOLEAN = '[object Boolean]',\n PI_OVER_DEG180 = Math.PI / 180,\n DEG180_OVER_PI = 180 / Math.PI,\n HASH = '#',\n EMPTY_STRING = '',\n ZERO = '0',\n KONVA_WARNING = 'Konva warning: ',\n KONVA_ERROR = 'Konva error: ',\n RGB_PAREN = 'rgb(',\n COLORS = {\n aliceblue: [240, 248, 255],\n antiquewhite: [250, 235, 215],\n aqua: [0, 255, 255],\n aquamarine: [127, 255, 212],\n azure: [240, 255, 255],\n beige: [245, 245, 220],\n bisque: [255, 228, 196],\n black: [0, 0, 0],\n blanchedalmond: [255, 235, 205],\n blue: [0, 0, 255],\n blueviolet: [138, 43, 226],\n brown: [165, 42, 42],\n burlywood: [222, 184, 135],\n cadetblue: [95, 158, 160],\n chartreuse: [127, 255, 0],\n chocolate: [210, 105, 30],\n coral: [255, 127, 80],\n cornflowerblue: [100, 149, 237],\n cornsilk: [255, 248, 220],\n crimson: [220, 20, 60],\n cyan: [0, 255, 255],\n darkblue: [0, 0, 139],\n darkcyan: [0, 139, 139],\n darkgoldenrod: [184, 132, 11],\n darkgray: [169, 169, 169],\n darkgreen: [0, 100, 0],\n darkgrey: [169, 169, 169],\n darkkhaki: [189, 183, 107],\n darkmagenta: [139, 0, 139],\n darkolivegreen: [85, 107, 47],\n darkorange: [255, 140, 0],\n darkorchid: [153, 50, 204],\n darkred: [139, 0, 0],\n darksalmon: [233, 150, 122],\n darkseagreen: [143, 188, 143],\n darkslateblue: [72, 61, 139],\n darkslategray: [47, 79, 79],\n darkslategrey: [47, 79, 79],\n darkturquoise: [0, 206, 209],\n darkviolet: [148, 0, 211],\n deeppink: [255, 20, 147],\n deepskyblue: [0, 191, 255],\n dimgray: [105, 105, 105],\n dimgrey: [105, 105, 105],\n dodgerblue: [30, 144, 255],\n firebrick: [178, 34, 34],\n floralwhite: [255, 255, 240],\n forestgreen: [34, 139, 34],\n fuchsia: [255, 0, 255],\n gainsboro: [220, 220, 220],\n ghostwhite: [248, 248, 255],\n gold: [255, 215, 0],\n goldenrod: [218, 165, 32],\n gray: [128, 128, 128],\n green: [0, 128, 0],\n greenyellow: [173, 255, 47],\n grey: [128, 128, 128],\n honeydew: [240, 255, 240],\n hotpink: [255, 105, 180],\n indianred: [205, 92, 92],\n indigo: [75, 0, 130],\n ivory: [255, 255, 240],\n khaki: [240, 230, 140],\n lavender: [230, 230, 250],\n lavenderblush: [255, 240, 245],\n lawngreen: [124, 252, 0],\n lemonchiffon: [255, 250, 205],\n lightblue: [173, 216, 230],\n lightcoral: [240, 128, 128],\n lightcyan: [224, 255, 255],\n lightgoldenrodyellow: [250, 250, 210],\n lightgray: [211, 211, 211],\n lightgreen: [144, 238, 144],\n lightgrey: [211, 211, 211],\n lightpink: [255, 182, 193],\n lightsalmon: [255, 160, 122],\n lightseagreen: [32, 178, 170],\n lightskyblue: [135, 206, 250],\n lightslategray: [119, 136, 153],\n lightslategrey: [119, 136, 153],\n lightsteelblue: [176, 196, 222],\n lightyellow: [255, 255, 224],\n lime: [0, 255, 0],\n limegreen: [50, 205, 50],\n linen: [250, 240, 230],\n magenta: [255, 0, 255],\n maroon: [128, 0, 0],\n mediumaquamarine: [102, 205, 170],\n mediumblue: [0, 0, 205],\n mediumorchid: [186, 85, 211],\n mediumpurple: [147, 112, 219],\n mediumseagreen: [60, 179, 113],\n mediumslateblue: [123, 104, 238],\n mediumspringgreen: [0, 250, 154],\n mediumturquoise: [72, 209, 204],\n mediumvioletred: [199, 21, 133],\n midnightblue: [25, 25, 112],\n mintcream: [245, 255, 250],\n mistyrose: [255, 228, 225],\n moccasin: [255, 228, 181],\n navajowhite: [255, 222, 173],\n navy: [0, 0, 128],\n oldlace: [253, 245, 230],\n olive: [128, 128, 0],\n olivedrab: [107, 142, 35],\n orange: [255, 165, 0],\n orangered: [255, 69, 0],\n orchid: [218, 112, 214],\n palegoldenrod: [238, 232, 170],\n palegreen: [152, 251, 152],\n paleturquoise: [175, 238, 238],\n palevioletred: [219, 112, 147],\n papayawhip: [255, 239, 213],\n peachpuff: [255, 218, 185],\n peru: [205, 133, 63],\n pink: [255, 192, 203],\n plum: [221, 160, 203],\n powderblue: [176, 224, 230],\n purple: [128, 0, 128],\n rebeccapurple: [102, 51, 153],\n red: [255, 0, 0],\n rosybrown: [188, 143, 143],\n royalblue: [65, 105, 225],\n saddlebrown: [139, 69, 19],\n salmon: [250, 128, 114],\n sandybrown: [244, 164, 96],\n seagreen: [46, 139, 87],\n seashell: [255, 245, 238],\n sienna: [160, 82, 45],\n silver: [192, 192, 192],\n skyblue: [135, 206, 235],\n slateblue: [106, 90, 205],\n slategray: [119, 128, 144],\n slategrey: [119, 128, 144],\n snow: [255, 255, 250],\n springgreen: [0, 255, 127],\n steelblue: [70, 130, 180],\n tan: [210, 180, 140],\n teal: [0, 128, 128],\n thistle: [216, 191, 216],\n transparent: [255, 255, 255, 0],\n tomato: [255, 99, 71],\n turquoise: [64, 224, 208],\n violet: [238, 130, 238],\n wheat: [245, 222, 179],\n white: [255, 255, 255],\n whitesmoke: [245, 245, 245],\n yellow: [255, 255, 0],\n yellowgreen: [154, 205, 5]\n },\n RGB_REGEX = /rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)/;\n\n /**\n * @namespace Util\n * @memberof Konva\n */\n Konva.Util = {\n /*\n * cherry-picked utilities from underscore.js\n */\n _isElement: function(obj) {\n return !!(obj && obj.nodeType == 1);\n },\n _isFunction: function(obj) {\n return !!(obj && obj.constructor && obj.call && obj.apply);\n },\n _isObject: function(obj) {\n return !!obj && obj.constructor === Object;\n },\n _isArray: function(obj) {\n return Object.prototype.toString.call(obj) === OBJECT_ARRAY;\n },\n _isNumber: function(obj) {\n return (\n Object.prototype.toString.call(obj) === OBJECT_NUMBER &&\n !isNaN(obj) &&\n isFinite(obj)\n );\n },\n _isString: function(obj) {\n return Object.prototype.toString.call(obj) === OBJECT_STRING;\n },\n _isBoolean: function(obj) {\n return Object.prototype.toString.call(obj) === OBJECT_BOOLEAN;\n },\n // arrays are objects too\n isObject: function(val) {\n return val instanceof Object;\n },\n isValidSelector: function(selector) {\n if (typeof selector !== 'string') {\n return false;\n }\n var firstChar = selector[0];\n return (\n firstChar === '#' ||\n firstChar === '.' ||\n firstChar === firstChar.toUpperCase()\n );\n },\n _sign: function(number) {\n if (number === 0) {\n return 0;\n }\n if (number > 0) {\n return 1;\n } else {\n return -1;\n }\n },\n createCanvasElement: function() {\n var canvas = Konva.isBrowser\n ? Konva.document.createElement('canvas')\n : new Konva._nodeCanvas();\n // on some environments canvas.style is readonly\n try {\n canvas.style = canvas.style || {};\n } catch (e) {}\n return canvas;\n },\n _isInDocument: function(el) {\n while ((el = el.parentNode)) {\n if (el == Konva.document) {\n return true;\n }\n }\n return false;\n },\n _simplifyArray: function(arr) {\n var retArr = [],\n len = arr.length,\n util = Konva.Util,\n n,\n val;\n\n for (n = 0; n < len; n++) {\n val = arr[n];\n if (util._isNumber(val)) {\n val = Math.round(val * 1000) / 1000;\n } else if (!util._isString(val)) {\n val = val.toString();\n }\n\n retArr.push(val);\n }\n\n return retArr;\n },\n /*\n * arg can be an image object or image data\n */\n _getImage: function(arg, callback) {\n var imageObj, canvas;\n\n // if arg is null or undefined\n if (!arg) {\n callback(null);\n } else if (this._isElement(arg)) {\n // if arg is already an image object\n callback(arg);\n } else if (this._isString(arg)) {\n // if arg is a string, then it's a data url\n imageObj = new Konva.window.Image();\n imageObj.onload = function() {\n callback(imageObj);\n };\n imageObj.src = arg;\n } else if (arg.data) {\n //if arg is an object that contains the data property, it's an image object\n canvas = Konva.Util.createCanvasElement();\n canvas.width = arg.width;\n canvas.height = arg.height;\n var _context = canvas.getContext(CONTEXT_2D);\n _context.putImageData(arg, 0, 0);\n this._getImage(canvas.toDataURL(), callback);\n } else {\n callback(null);\n }\n },\n _getRGBAString: function(obj) {\n var red = obj.red || 0,\n green = obj.green || 0,\n blue = obj.blue || 0,\n alpha = obj.alpha || 1;\n\n return ['rgba(', red, ',', green, ',', blue, ',', alpha, ')'].join(\n EMPTY_STRING\n );\n },\n _rgbToHex: function(r, g, b) {\n return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);\n },\n _hexToRgb: function(hex) {\n hex = hex.replace(HASH, EMPTY_STRING);\n var bigint = parseInt(hex, 16);\n return {\n r: (bigint >> 16) & 255,\n g: (bigint >> 8) & 255,\n b: bigint & 255\n };\n },\n /**\n * return random hex color\n * @method\n * @memberof Konva.Util.prototype\n */\n getRandomColor: function() {\n var randColor = ((Math.random() * 0xffffff) << 0).toString(16);\n while (randColor.length < 6) {\n randColor = ZERO + randColor;\n }\n return HASH + randColor;\n },\n /**\n * return value with default fallback\n * @method\n * @memberof Konva.Util.prototype\n */\n get: function(val, def) {\n if (val === undefined) {\n return def;\n } else {\n return val;\n }\n },\n /**\n * get RGB components of a color\n * @method\n * @memberof Konva.Util.prototype\n * @param {String} color\n * @example\n * // each of the following examples return {r:0, g:0, b:255}\n * var rgb = Konva.Util.getRGB('blue');\n * var rgb = Konva.Util.getRGB('#0000ff');\n * var rgb = Konva.Util.getRGB('rgb(0,0,255)');\n */\n getRGB: function(color) {\n var rgb;\n // color string\n if (color in COLORS) {\n rgb = COLORS[color];\n return {\n r: rgb[0],\n g: rgb[1],\n b: rgb[2]\n };\n } else if (color[0] === HASH) {\n // hex\n return this._hexToRgb(color.substring(1));\n } else if (color.substr(0, 4) === RGB_PAREN) {\n // rgb string\n rgb = RGB_REGEX.exec(color.replace(/ /g, ''));\n return {\n r: parseInt(rgb[1], 10),\n g: parseInt(rgb[2], 10),\n b: parseInt(rgb[3], 10)\n };\n } else {\n // default\n return {\n r: 0,\n g: 0,\n b: 0\n };\n }\n },\n // convert any color string to RGBA object\n // from https://github.com/component/color-parser\n colorToRGBA: function(str) {\n str = str || 'black';\n return (\n Konva.Util._namedColorToRBA(str) ||\n Konva.Util._hex3ColorToRGBA(str) ||\n Konva.Util._hex6ColorToRGBA(str) ||\n Konva.Util._rgbColorToRGBA(str) ||\n Konva.Util._rgbaColorToRGBA(str)\n );\n },\n // Parse named css color. Like \"green\"\n _namedColorToRBA: function(str) {\n var c = COLORS[str.toLowerCase()];\n if (!c) {\n return null;\n }\n return {\n r: c[0],\n g: c[1],\n b: c[2],\n a: 1\n };\n },\n // Parse rgb(n, n, n)\n _rgbColorToRGBA: function(str) {\n if (str.indexOf('rgb(') === 0) {\n str = str.match(/rgb\\(([^)]+)\\)/)[1];\n var parts = str.split(/ *, */).map(Number);\n return {\n r: parts[0],\n g: parts[1],\n b: parts[2],\n a: 1\n };\n }\n },\n // Parse rgba(n, n, n, n)\n _rgbaColorToRGBA: function(str) {\n if (str.indexOf('rgba(') === 0) {\n str = str.match(/rgba\\(([^)]+)\\)/)[1];\n var parts = str.split(/ *, */).map(Number);\n return {\n r: parts[0],\n g: parts[1],\n b: parts[2],\n a: parts[3]\n };\n }\n },\n // Parse #nnnnnn\n _hex6ColorToRGBA: function(str) {\n if (str[0] === '#' && str.length === 7) {\n return {\n r: parseInt(str.slice(1, 3), 16),\n g: parseInt(str.slice(3, 5), 16),\n b: parseInt(str.slice(5, 7), 16),\n a: 1\n };\n }\n },\n // Parse #nnn\n _hex3ColorToRGBA: function(str) {\n if (str[0] === '#' && str.length === 4) {\n return {\n r: parseInt(str[1] + str[1], 16),\n g: parseInt(str[2] + str[2], 16),\n b: parseInt(str[3] + str[3], 16),\n a: 1\n };\n }\n },\n // o1 takes precedence over o2\n _merge: function(o1, o2) {\n var retObj = this._clone(o2);\n for (var key in o1) {\n if (this._isObject(o1[key])) {\n retObj[key] = this._merge(o1[key], retObj[key]);\n } else {\n retObj[key] = o1[key];\n }\n }\n return retObj;\n },\n trimRight: function(str) {\n return str.replace(/\\s+$/, '');\n },\n trimLeft: function(str) {\n return str.replace(/^\\s+/, '');\n },\n /**\n * check intersection of two client rectangles\n * @method\n * @memberof Konva.Util.prototype\n */\n haveIntersection: function(r1, r2) {\n return !(\n r2.x > r1.x + r1.width ||\n r2.x + r2.width < r1.x ||\n r2.y > r1.y + r1.height ||\n r2.y + r2.height < r1.y\n );\n },\n cloneObject: function(obj) {\n var retObj = {};\n for (var key in obj) {\n if (this._isObject(obj[key])) {\n retObj[key] = this.cloneObject(obj[key]);\n } else if (this._isArray(obj[key])) {\n retObj[key] = this.cloneArray(obj[key]);\n } else {\n retObj[key] = obj[key];\n }\n }\n return retObj;\n },\n cloneArray: function(arr) {\n return arr.slice(0);\n },\n _degToRad: function(deg) {\n return deg * PI_OVER_DEG180;\n },\n _radToDeg: function(rad) {\n return rad * DEG180_OVER_PI;\n },\n _capitalize: function(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n },\n throw: function(str) {\n throw new Error(KONVA_ERROR + str);\n },\n error: function(str) {\n console.error(KONVA_ERROR + str);\n },\n warn: function(str) {\n /*\n * IE9 on Windows7 64bit will throw a JS error\n * if we don't use window.console in the conditional\n */\n if (Konva.global.console && console.warn && Konva.showWarnings) {\n console.warn(KONVA_WARNING + str);\n }\n },\n extend: function(child, parent) {\n function Ctor() {\n this.constructor = child;\n }\n Ctor.prototype = parent.prototype;\n var oldProto = child.prototype;\n child.prototype = new Ctor();\n for (var key in oldProto) {\n if (oldProto.hasOwnProperty(key)) {\n child.prototype[key] = oldProto[key];\n }\n }\n child.__super__ = parent.prototype;\n // create reference to parent\n child.super = parent;\n },\n /**\n * adds methods to a constructor prototype\n * @method\n * @memberof Konva.Util.prototype\n * @param {Function} constructor\n * @param {Object} methods\n */\n addMethods: function(constructor, methods) {\n var key;\n\n for (key in methods) {\n constructor.prototype[key] = methods[key];\n }\n },\n _getControlPoints: function(x0, y0, x1, y1, x2, y2, t) {\n var d01 = Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2)),\n d12 = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)),\n fa = t * d01 / (d01 + d12),\n fb = t * d12 / (d01 + d12),\n p1x = x1 - fa * (x2 - x0),\n p1y = y1 - fa * (y2 - y0),\n p2x = x1 + fb * (x2 - x0),\n p2y = y1 + fb * (y2 - y0);\n\n return [p1x, p1y, p2x, p2y];\n },\n _expandPoints: function(p, tension) {\n var len = p.length,\n allPoints = [],\n n,\n cp;\n\n for (n = 2; n < len - 2; n += 2) {\n cp = Konva.Util._getControlPoints(\n p[n - 2],\n p[n - 1],\n p[n],\n p[n + 1],\n p[n + 2],\n p[n + 3],\n tension\n );\n allPoints.push(cp[0]);\n allPoints.push(cp[1]);\n allPoints.push(p[n]);\n allPoints.push(p[n + 1]);\n allPoints.push(cp[2]);\n allPoints.push(cp[3]);\n }\n\n return allPoints;\n },\n _removeLastLetter: function(str) {\n return str.substring(0, str.length - 1);\n },\n each: function(obj, func) {\n for (var key in obj) {\n func(key, obj[key]);\n }\n },\n _inRange: function(val, left, right) {\n return left <= val && val < right;\n },\n _getProjectionToSegment: function(x1, y1, x2, y2, x3, y3) {\n var x, y, dist;\n\n var pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);\n if (pd2 == 0) {\n x = x1;\n y = y1;\n dist = (x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2);\n } else {\n var u = ((x3 - x1) * (x2 - x1) + (y3 - y1) * (y2 - y1)) / pd2;\n if (u < 0) {\n x = x1;\n y = y1;\n dist = (x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3);\n } else if (u > 1.0) {\n x = x2;\n y = y2;\n dist = (x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3);\n } else {\n x = x1 + u * (x2 - x1);\n y = y1 + u * (y2 - y1);\n dist = (x - x3) * (x - x3) + (y - y3) * (y - y3);\n }\n }\n return [x, y, dist];\n },\n // line as array of points.\n // line might be closed\n _getProjectionToLine: function(pt, line, isClosed) {\n var pc = Konva.Util.cloneObject(pt);\n var dist = Number.MAX_VALUE;\n line.forEach(function(p1, i) {\n if (!isClosed && i === line.length - 1) {\n return;\n }\n var p2 = line[(i + 1) % line.length];\n var proj = Konva.Util._getProjectionToSegment(\n p1.x,\n p1.y,\n p2.x,\n p2.y,\n pt.x,\n pt.y\n );\n var px = proj[0],\n py = proj[1],\n pdist = proj[2];\n if (pdist < dist) {\n pc.x = px;\n pc.y = py;\n dist = pdist;\n }\n });\n return pc;\n },\n _prepareArrayForTween: function(startArray, endArray, isClosed) {\n var n,\n start = [],\n end = [];\n if (startArray.length > endArray.length) {\n var temp = endArray;\n endArray = startArray;\n startArray = temp;\n }\n for (n = 0; n < startArray.length; n += 2) {\n start.push({\n x: startArray[n],\n y: startArray[n + 1]\n });\n }\n for (n = 0; n < endArray.length; n += 2) {\n end.push({\n x: endArray[n],\n y: endArray[n + 1]\n });\n }\n\n var newStart = [];\n end.forEach(function(point) {\n var pr = Konva.Util._getProjectionToLine(point, start, isClosed);\n newStart.push(pr.x);\n newStart.push(pr.y);\n });\n return newStart;\n },\n _prepareToStringify: function(obj) {\n var desc;\n\n obj.visitedByCircularReferenceRemoval = true;\n\n for (var key in obj) {\n if (\n !(obj.hasOwnProperty(key) && obj[key] && typeof obj[key] == 'object')\n ) {\n continue;\n }\n desc = Object.getOwnPropertyDescriptor(obj, key);\n if (\n obj[key].visitedByCircularReferenceRemoval ||\n Konva.Util._isElement(obj[key])\n ) {\n if (desc.configurable) {\n delete obj[key];\n } else {\n return null;\n }\n } else if (Konva.Util._prepareToStringify(obj[key]) === null) {\n if (desc.configurable) {\n delete obj[key];\n } else {\n return null;\n }\n }\n }\n\n delete obj.visitedByCircularReferenceRemoval;\n\n return obj;\n }\n };\n})();\n\n(function() {\n 'use strict';\n // calculate pixel ratio\n\n var _pixelRatio;\n function getDevicePixelRatio() {\n if (_pixelRatio) {\n return _pixelRatio;\n }\n var canvas = Konva.Util.createCanvasElement();\n var context = canvas.getContext('2d');\n _pixelRatio = (function() {\n var devicePixelRatio = Konva.window.devicePixelRatio || 1,\n backingStoreRatio =\n context.webkitBackingStorePixelRatio ||\n context.mozBackingStorePixelRatio ||\n context.msBackingStorePixelRatio ||\n context.oBackingStorePixelRatio ||\n context.backingStorePixelRatio ||\n 1;\n return devicePixelRatio / backingStoreRatio;\n })();\n return _pixelRatio;\n }\n\n /**\n * Canvas Renderer constructor\n * @constructor\n * @abstract\n * @memberof Konva\n * @param {Object} config\n * @param {Number} config.width\n * @param {Number} config.height\n * @param {Number} config.pixelRatio KonvaJS automatically handles pixel ratio adjustments in order to render crisp drawings\n * on all devices. Most desktops, low end tablets, and low end phones, have device pixel ratios\n * of 1. Some high end tablets and phones, like iPhones and iPads (not the mini) have a device pixel ratio\n * of 2. Some Macbook Pros, and iMacs also have a device pixel ratio of 2. Some high end Android devices have pixel\n * ratios of 2 or 3. Some browsers like Firefox allow you to configure the pixel ratio of the viewport. Unless otherwise\n * specified, the pixel ratio will be defaulted to the actual device pixel ratio. You can override the device pixel\n * ratio for special situations, or, if you don't want the pixel ratio to be taken into account, you can set it to 1.\n */\n Konva.Canvas = function(config) {\n this.init(config);\n };\n\n Konva.Canvas.prototype = {\n init: function(config) {\n var conf = config || {};\n\n var pixelRatio =\n conf.pixelRatio || Konva.pixelRatio || getDevicePixelRatio();\n\n this.pixelRatio = pixelRatio;\n this._canvas = Konva.Util.createCanvasElement();\n\n // set inline styles\n this._canvas.style.padding = 0;\n