From 7d352e8349d83f149492f0d15e780b05de5d37c3 Mon Sep 17 00:00:00 2001 From: jakubfiala Date: Sun, 25 Dec 2016 17:37:44 +0100 Subject: [PATCH 1/3] added npm script for webpack watch --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index eb91658..c3108e0 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "prepublish": "npm run node-compile", "node-compile": "babel src --presets es2015 -d lib/", "build": "webpack --config webpack.config.js", + "watch": "webpack --config webpack.config.js --watch", "test": "jasmine" }, "repository": { From 08a654259f9cce77dc17a50145d536b44dbb91b4 Mon Sep 17 00:00:00 2001 From: jakubfiala Date: Sun, 25 Dec 2016 18:15:35 +0100 Subject: [PATCH 2/3] fixed refill bug --- demo/index.html | 2 +- dist/atrament.min.js | 2 +- dist/atrament.min.js.map | 2 +- src/atrament.js | 10 +++++++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/demo/index.html b/demo/index.html index 114e706..fa27042 100755 --- a/demo/index.html +++ b/demo/index.html @@ -56,7 +56,7 @@

atrament.js


-
+

diff --git a/dist/atrament.min.js b/dist/atrament.min.js index 19e8710..ed68324 100644 --- a/dist/atrament.min.js +++ b/dist/atrament.min.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.atrament=e():t.atrament=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return t[o].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){t.exports=n(1)},function(t,e,n){"use strict";t.exports=n(2)},function(t,e){"use strict";function n(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);ethis._targetThickness?this._thickness-=.5:this._thickness=0&&d(x);)x-=4*c;x+=4*c,++_;for(var w=!1,k=!1;_++0&&(d(x-4)?w||(u.push([g-1,_]),w=!0):w&&(w=!1)),g=1?this.context.globalAlpha=1:this.context.globalAlpha=t/10}}],[{key:"lineDistance",value:function(t,e,n,o){var i=Math.pow(n-t,2),r=Math.pow(o-e,2);return Math.sqrt(i+r)}},{key:"hexToRgb",value:function(t){var e=t.match(/^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{key:"matchColor",value:function(t,e,n,o,i){return function(r){var s=t[r],a=t[r+1],c=t[r+2],h=t[r+3];return s===e&&a===n&&c===o&&h===i}}},{key:"colorPixel",value:function(e,o,i,r,s,a){var c=t.matchColor.apply(t,[e].concat(n(s)));return function(t){e[t]=o,e[t+1]=i,e[t+2]=r,e[t+3]=a,c(t+4)||(e[t+4]=.01*e[t+4]+.99*o,e[t+4+1]=.01*e[t+4+1]+.99*i,e[t+4+2]=.01*e[t+4+2]+.99*r,e[t+4+3]=.01*e[t+4+3]+.99*a),c(t-4)||(e[t-4]=.01*e[t-4]+.99*o,e[t-4+1]=.01*e[t-4+1]+.99*i,e[t-4+2]=.01*e[t-4+2]+.99*r,e[t-4+3]=.01*e[t-4+3]+.99*a)}}}]),t}();t.exports=s,t.exports.Atrament=f}])}); +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.atrament=e():t.atrament=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return t[o].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){t.exports=n(1)},function(t,e,n){"use strict";t.exports=n(2)},function(t,e){"use strict";function n(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);ethis._targetThickness?this._thickness-=.5:this._thickness=0&&d(w);)w-=4*c;w+=4*c,++x;for(var k=!1,b=!1;x++0&&(d(w-4)?k||(u.push([_-1,x]),k=!0):k&&(k=!1)),_=1?this.context.globalAlpha=1:this.context.globalAlpha=t/10}}],[{key:"lineDistance",value:function(t,e,n,o){var i=Math.pow(n-t,2),r=Math.pow(o-e,2);return Math.sqrt(i+r)}},{key:"hexToRgb",value:function(t){var e=t.match(/^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{key:"matchColor",value:function(t,e,n,o,i){return function(r){var s=t[r],a=t[r+1],c=t[r+2],h=t[r+3];return s===e&&a===n&&c===o&&h===i}}},{key:"colorPixel",value:function(e,o,i,r,s,a){var c=t.matchColor.apply(t,[e].concat(n(s)));return function(t){e[t]=o,e[t+1]=i,e[t+2]=r,e[t+3]=a,c(t+4)||(e[t+4]=.01*e[t+4]+.99*o,e[t+4+1]=.01*e[t+4+1]+.99*i,e[t+4+2]=.01*e[t+4+2]+.99*r,e[t+4+3]=.01*e[t+4+3]+.99*a),c(t-4)||(e[t-4]=.01*e[t-4]+.99*o,e[t-4+1]=.01*e[t-4+1]+.99*i,e[t-4+2]=.01*e[t-4+2]+.99*r,e[t-4+3]=.01*e[t-4+3]+.99*a)}}}]),t}();t.exports=s,t.exports.Atrament=f}])}); //# sourceMappingURL=atrament.min.js.map \ No newline at end of file diff --git a/dist/atrament.min.js.map b/dist/atrament.min.js.map index d7560ae..ee1e21b 100644 --- a/dist/atrament.min.js.map +++ b/dist/atrament.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///atrament.min.js","webpack:///webpack/bootstrap 8a98e5ca26a13ff27517","webpack:///./index.js","webpack:///./src/atrament.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","_toConsumableArray","arr","Array","isArray","i","arr2","length","from","_possibleConstructorReturn","self","ReferenceError","_inherits","subClass","superClass","TypeError","prototype","Object","create","constructor","value","enumerable","writable","configurable","setPrototypeOf","__proto__","_classCallCheck","instance","Constructor","atrament","selector","width","height","color","Atrament","_slicedToArray","sliceIterator","_arr","_n","_d","_e","undefined","_s","_i","Symbol","iterator","next","done","push","err","_createClass","defineProperties","target","props","descriptor","defineProperty","key","protoProps","staticProps","Point","x","y","arguments","Error","_x","_y","get","set","Mouse","_Point","_this","getPrototypeOf","_down","_px","_py","d","px","py","_this2","document","Node","tagName","canvas","querySelector","style","cursor","mouse","mouseMove","e","preventDefault","rect","getBoundingClientRect","position","changedTouches","offsetX","offsetY","clientX","documentElement","scrollLeft","left","clientY","scrollTop","top","down","draw","_dirty","fireDirty","mouseDown","mousePosition","_mode","fill","context","beginPath","moveTo","mouseUp","closePath","addEventListener","destroy","clear","removeEventListener","getContext","globalCompositeOperation","globalAlpha","strokeStyle","lineCap","lineJoin","translate","_filling","_fillStack","SMOOTHING_INIT","WEIGHT_SPREAD","_smoothing","_maxWeight","_thickness","_targetThickness","_weight","mX","mY","raw_dist","lineDistance","smoothingFactor","Math","min","dist","lineWidth","quadraticCurveTo","stroke","event","createEvent","initEvent","dispatchEvent","dirty","mode","clearRect","toDataURL","_this3","startColor","slice","getImageData","data","setTimeout","_floodFill","startX","startY","_this4","canvasWidth","canvasHeight","pixelStack","fillColor","hexToRgb","colorLayer","alpha","colorPixel","apply","concat","matchColor","newPos","pop","_newPos","pixelPos","reachLeft","reachRight","putImageData","shift","w","s","o","x1","y1","x2","y2","xs","pow","ys","sqrt","hexColor","match","parseInt","compR","compG","compB","compA","r","g","b","a","fillR","fillG","fillB"],"mappings":"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","file":"atrament.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"atrament\"] = factory();\n\telse\n\t\troot[\"atrament\"] = factory();\n})(this, function() {\nreturn \n\n\n/** WEBPACK FOOTER **\n ** webpack/universalModuleDefinition\n **/","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"atrament\"] = factory();\n\telse\n\t\troot[\"atrament\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(1);\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tmodule.exports = __webpack_require__(2);\n\n/***/ },\n/* 2 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\tvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\t\n\tvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\t\n\tfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\t\n\tfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\t\n\tfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\t\n\tfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\t\n\t//make a class for Point\n\tvar Point = function () {\n\t\tfunction Point(x, y) {\n\t\t\t_classCallCheck(this, Point);\n\t\n\t\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.');\n\t\t\tthis._x = x;\n\t\t\tthis._y = y;\n\t\t}\n\t\n\t\t_createClass(Point, [{\n\t\t\tkey: 'set',\n\t\t\tvalue: function set(x, y) {\n\t\t\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.set');\n\t\t\t\tthis._x = x;\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'x',\n\t\t\tget: function get() {\n\t\t\t\treturn this._x;\n\t\t\t},\n\t\t\tset: function set(x) {\n\t\t\t\tthis._x = x;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'y',\n\t\t\tget: function get() {\n\t\t\t\treturn this._y;\n\t\t\t},\n\t\t\tset: function set(y) {\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Point;\n\t}();\n\t\n\t//make a class for the mouse data\n\t\n\t\n\tvar Mouse = function (_Point) {\n\t\t_inherits(Mouse, _Point);\n\t\n\t\tfunction Mouse() {\n\t\t\t_classCallCheck(this, Mouse);\n\t\n\t\t\tvar _this = _possibleConstructorReturn(this, (Mouse.__proto__ || Object.getPrototypeOf(Mouse)).call(this, 0, 0));\n\t\n\t\t\t_this._down = false;\n\t\t\t_this._px = 0;\n\t\t\t_this._py = 0;\n\t\t\treturn _this;\n\t\t}\n\t\n\t\t_createClass(Mouse, [{\n\t\t\tkey: 'down',\n\t\t\tget: function get() {\n\t\t\t\treturn this._down;\n\t\t\t},\n\t\t\tset: function set(d) {\n\t\t\t\tthis._down = d;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'x',\n\t\t\tget: function get() {\n\t\t\t\treturn this._x;\n\t\t\t},\n\t\t\tset: function set(x) {\n\t\t\t\tthis._x = x;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'y',\n\t\t\tget: function get() {\n\t\t\t\treturn this._y;\n\t\t\t},\n\t\t\tset: function set(y) {\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'px',\n\t\t\tget: function get() {\n\t\t\t\treturn this._px;\n\t\t\t},\n\t\t\tset: function set(px) {\n\t\t\t\tthis._px = px;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'py',\n\t\t\tget: function get() {\n\t\t\t\treturn this._py;\n\t\t\t},\n\t\t\tset: function set(py) {\n\t\t\t\tthis._py = py;\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Mouse;\n\t}(Point);\n\t\n\tvar Atrament = function () {\n\t\tfunction Atrament(selector, width, height, color) {\n\t\t\tvar _this2 = this;\n\t\n\t\t\t_classCallCheck(this, Atrament);\n\t\n\t\t\tif (!document) throw new Error('no DOM found');\n\t\n\t\t\t//get canvas element\n\t\t\tif (selector instanceof Node && selector.tagName === 'CANVAS') this.canvas = selector;else if (typeof selector === 'string') this.canvas = document.querySelector(selector);else throw new Error('can\\'t look for canvas based on \\'' + selector + '\\'');\n\t\t\tif (!this.canvas) throw new Error('canvas not found');\n\t\n\t\t\t//set external canvas params\n\t\t\tthis.canvas.width = width ? width : 500;\n\t\t\tthis.canvas.height = height ? height : 500;\n\t\t\tthis.canvas.style.cursor = 'crosshair';\n\t\n\t\t\t//create a mouse object\n\t\t\tthis.mouse = new Mouse();\n\t\n\t\t\t//mousemove handler\n\t\t\tvar mouseMove = function mouseMove(e) {\n\t\t\t\te.preventDefault();\n\t\n\t\t\t\tvar rect = _this2.canvas.getBoundingClientRect();\n\t\t\t\tvar position = e.changedTouches && e.changedTouches[0] || e;\n\t\t\t\tvar x = position.offsetX;\n\t\t\t\tvar y = position.offsetY;\n\t\n\t\t\t\tif (typeof x === 'undefined') {\n\t\t\t\t\tx = position.clientX + document.documentElement.scrollLeft - rect.left;\n\t\t\t\t}\n\t\t\t\tif (typeof y === 'undefined') {\n\t\t\t\t\ty = position.clientY + document.documentElement.scrollTop - rect.top;\n\t\t\t\t}\n\t\n\t\t\t\t//draw if we should draw\n\t\t\t\tif (_this2.mouse.down) {\n\t\t\t\t\t_this2.draw(x, y);\n\t\t\t\t\tif (!_this2._dirty && (x !== _this2.mouse.x || y !== _this2.mouse.y)) {\n\t\t\t\t\t\t_this2._dirty = true;\n\t\t\t\t\t\t_this2.fireDirty();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t_this2.mouse.x = x;\n\t\t\t\t\t_this2.mouse.y = y;\n\t\t\t\t}\n\t\t\t};\n\t\n\t\t\t//mousedown handler\n\t\t\tvar mouseDown = function mouseDown(mousePosition) {\n\t\t\t\tmousePosition.preventDefault();\n\t\t\t\t//update position just in case\n\t\t\t\tmouseMove(mousePosition);\n\t\n\t\t\t\t//if we are filling - fill and return\n\t\t\t\tif (_this2._mode === 'fill') {\n\t\t\t\t\t_this2.fill();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\t//remember it\n\t\t\t\t_this2.mouse.px = _this2.mouse.x;\n\t\t\t\t_this2.mouse.py = _this2.mouse.y;\n\t\t\t\t//begin drawing\n\t\t\t\t_this2.mouse.down = true;\n\t\t\t\t_this2.context.beginPath();\n\t\t\t\t_this2.context.moveTo(_this2.mouse.px, _this2.mouse.py);\n\t\t\t};\n\t\t\tvar mouseUp = function mouseUp(mousePosition) {\n\t\t\t\tmousePosition.preventDefault();\n\t\t\t\t_this2.mouse.down = false;\n\t\t\t\t//stop drawing\n\t\t\t\t_this2.context.closePath();\n\t\t\t};\n\t\n\t\t\t//attach listeners\n\t\t\tthis.canvas.addEventListener('mousemove', mouseMove);\n\t\t\tthis.canvas.addEventListener('mousedown', mouseDown);\n\t\t\tdocument.addEventListener('mouseup', mouseUp);\n\t\t\tthis.canvas.addEventListener('touchstart', mouseDown);\n\t\t\tthis.canvas.addEventListener('touchend', mouseUp);\n\t\t\tthis.canvas.addEventListener('touchmove', mouseMove);\n\t\n\t\t\t//helper for destroying Atrament (removing event listeners)\n\t\t\tthis.destroy = function () {\n\t\t\t\t_this2.clear();\n\t\t\t\t_this2.canvas.removeEventListener('mousemove', mouseMove);\n\t\t\t\t_this2.canvas.removeEventListener('mousedown', mouseDown);\n\t\t\t\tdocument.removeEventListener('mouseup', mouseUp);\n\t\t\t\t_this2.canvas.removeEventListener('touchstart', mouseDown);\n\t\t\t\t_this2.canvas.removeEventListener('touchend', mouseUp);\n\t\t\t\t_this2.canvas.removeEventListener('touchmove', mouseMove);\n\t\t\t};\n\t\n\t\t\t//set internal canvas params\n\t\t\tthis.context = this.canvas.getContext('2d');\n\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\tthis.context.globalAlpha = 1;\n\t\t\tthis.context.strokeStyle = color ? color : 'black';\n\t\t\tthis.context.lineCap = 'round';\n\t\t\tthis.context.lineJoin = 'round';\n\t\t\tthis.context.translate(0.5, 0.5);\n\t\n\t\t\tthis._filling = false;\n\t\t\tthis._fillStack = [];\n\t\n\t\t\t//set drawing params\n\t\t\tthis.SMOOTHING_INIT = 0.85;\n\t\t\tthis.WEIGHT_SPREAD = 10;\n\t\t\tthis._smoothing = this.SMOOTHING_INIT;\n\t\t\tthis._maxWeight = 12;\n\t\t\tthis._thickness = 2;\n\t\t\tthis._targetThickness = 2;\n\t\t\tthis._weight = 2;\n\t\t\tthis._mode = 'draw';\n\t\t}\n\t\n\t\t_createClass(Atrament, [{\n\t\t\tkey: 'draw',\n\t\t\tvalue: function draw(mX, mY) {\n\t\t\t\tvar mouse = this.mouse;\n\t\t\t\tvar context = this.context;\n\t\n\t\t\t\t//calculate distance from previous point\n\t\t\t\tvar raw_dist = Atrament.lineDistance(mX, mY, mouse.px, mouse.py);\n\t\n\t\t\t\t//now, here we scale the initial smoothing factor by the raw distance\n\t\t\t\t//this means that when the mouse moves fast, there is more smoothing\n\t\t\t\t//and when we're drawing small detailed stuff, we have more control\n\t\t\t\t//also we hard clip at 1\n\t\t\t\tvar smoothingFactor = Math.min(0.87, this._smoothing + (raw_dist - 60) / 3000);\n\t\n\t\t\t\t//calculate smoothed coordinates\n\t\t\t\tmouse.x = mX - (mX - mouse.px) * smoothingFactor;\n\t\t\t\tmouse.y = mY - (mY - mouse.py) * smoothingFactor;\n\t\n\t\t\t\t//recalculate distance from previous point, this time relative to the smoothed coords\n\t\t\t\tvar dist = Atrament.lineDistance(mouse.x, mouse.y, mouse.px, mouse.py);\n\t\n\t\t\t\t//calculate target thickness based on the new distance\n\t\t\t\tthis._targetThickness = (dist - 1) / (50 - 1) * (this._maxWeight - this._weight) + this._weight;\n\t\t\t\t//approach the target gradually\n\t\t\t\tif (this._thickness > this._targetThickness) {\n\t\t\t\t\tthis._thickness -= 0.5;\n\t\t\t\t} else if (this._thickness < this._targetThickness) {\n\t\t\t\t\tthis._thickness += 0.5;\n\t\t\t\t}\n\t\t\t\t//set line width\n\t\t\t\tcontext.lineWidth = this._thickness;\n\t\n\t\t\t\t//draw using quad interpolation\n\t\t\t\tcontext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);\n\t\t\t\tcontext.stroke();\n\t\n\t\t\t\t//remember\n\t\t\t\tmouse.px = mouse.x;\n\t\t\t\tmouse.py = mouse.y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'fireDirty',\n\t\t\tvalue: function fireDirty() {\n\t\t\t\tvar event = document.createEvent('Event');\n\t\t\t\tevent.initEvent('dirty', true, true);\n\t\t\t\tthis.canvas.dispatchEvent(event);\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'clear',\n\t\t\tvalue: function clear() {\n\t\t\t\tif (!this.dirty) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\tthis._dirty = false;\n\t\t\t\tthis.fireDirty();\n\t\n\t\t\t\t//make sure we're in the right compositing mode, and erase everything\n\t\t\t\tif (this.context.globalCompositeOperation === 'destination-out') {\n\t\t\t\t\tthis.mode = 'draw';\n\t\t\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\t\t\tthis.mode = 'erase';\n\t\t\t\t} else {\n\t\t\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'toImage',\n\t\t\tvalue: function toImage() {\n\t\t\t\treturn this.canvas.toDataURL();\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'fill',\n\t\t\tvalue: function fill() {\n\t\t\t\tvar _this3 = this;\n\t\n\t\t\t\tvar mouse = this.mouse;\n\t\t\t\tvar context = this.context;\n\t\t\t\tvar startColor = Array.prototype.slice.call(context.getImageData(mouse.x, mouse.y, 1, 1).data, 0); //converting to Array because Safari 9\n\t\n\t\t\t\tif (!this._filling) {\n\t\t\t\t\tthis.canvas.style.cursor = 'progress';\n\t\t\t\t\tthis._filling = true;\n\t\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this3._floodFill(mouse.x, mouse.y, startColor);\n\t\t\t\t\t}, 100);\n\t\t\t\t} else {\n\t\t\t\t\tthis._fillStack.push([mouse.x, mouse.y, startColor]);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: '_floodFill',\n\t\t\tvalue: function _floodFill(startX, startY, startColor) {\n\t\t\t\tvar _this4 = this;\n\t\n\t\t\t\tvar context = this.context,\n\t\t\t\t canvasWidth = context.canvas.width,\n\t\t\t\t canvasHeight = context.canvas.height,\n\t\t\t\t pixelStack = [[startX, startY]],\n\t\n\t\t\t\t//hex needs to be trasformed to rgb since colorLayer accepts RGB\n\t\t\t\tfillColor = Atrament.hexToRgb(this.color),\n\t\n\t\t\t\t//Need to save current context with colors, we will update it\n\t\t\t\tcolorLayer = context.getImageData(0, 0, context.canvas.width, context.canvas.height),\n\t\t\t\t alpha = Math.min(context.globalAlpha * 10 * 255, 255),\n\t\t\t\t colorPixel = Atrament.colorPixel.apply(Atrament, [colorLayer.data].concat(_toConsumableArray(fillColor), [startColor, alpha])),\n\t\t\t\t matchColor = Atrament.matchColor.apply(Atrament, [colorLayer.data].concat(_toConsumableArray(startColor)));\n\t\n\t\t\t\twhile (pixelStack.length) {\n\t\t\t\t\tvar newPos = pixelStack.pop();\n\t\n\t\t\t\t\tvar _newPos = _slicedToArray(newPos, 2);\n\t\n\t\t\t\t\tvar x = _newPos[0];\n\t\t\t\t\tvar y = _newPos[1];\n\t\n\t\n\t\t\t\t\tvar pixelPos = (y * canvasWidth + x) * 4;\n\t\n\t\t\t\t\twhile (y-- >= 0 && matchColor(pixelPos)) {\n\t\t\t\t\t\tpixelPos -= canvasWidth * 4;\n\t\t\t\t\t}\n\t\t\t\t\tpixelPos += canvasWidth * 4;\n\t\n\t\t\t\t\t++y;\n\t\n\t\t\t\t\tvar reachLeft = false;\n\t\t\t\t\tvar reachRight = false;\n\t\n\t\t\t\t\twhile (y++ < canvasHeight - 1 && matchColor(pixelPos)) {\n\t\t\t\t\t\tcolorPixel(pixelPos);\n\t\n\t\t\t\t\t\tif (x > 0) {\n\t\t\t\t\t\t\tif (matchColor(pixelPos - 4)) {\n\t\t\t\t\t\t\t\tif (!reachLeft) {\n\t\t\t\t\t\t\t\t\tpixelStack.push([x - 1, y]);\n\t\t\t\t\t\t\t\t\treachLeft = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (reachLeft) {\n\t\t\t\t\t\t\t\treachLeft = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tif (x < canvasWidth - 1) {\n\t\t\t\t\t\t\tif (matchColor(pixelPos + 4)) {\n\t\t\t\t\t\t\t\tif (!reachRight) {\n\t\t\t\t\t\t\t\t\tpixelStack.push([x + 1, y]);\n\t\t\t\t\t\t\t\t\treachRight = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (reachRight) {\n\t\t\t\t\t\t\t\treachRight = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tpixelPos += canvasWidth * 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\n\t\t\t\t//Update context with filled bucket!\n\t\t\t\tcontext.putImageData(colorLayer, 0, 0);\n\t\n\t\t\t\tif (this._fillStack.length) {\n\t\t\t\t\tthis._floodFill.apply(this, _toConsumableArray(this._fillStack.shift()));\n\t\t\t\t} else {\n\t\t\t\t\tthis._filling = false;\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this4.canvas.style.cursor = 'crosshair';\n\t\t\t\t\t}, 100);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'color',\n\t\t\tget: function get() {\n\t\t\t\treturn this.context.strokeStyle;\n\t\t\t},\n\t\t\tset: function set(c) {\n\t\t\t\tif (typeof c !== 'string') throw new Error('wrong argument type');\n\t\t\t\tthis.context.strokeStyle = c;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'weight',\n\t\t\tget: function get() {\n\t\t\t\treturn this._weight;\n\t\t\t},\n\t\t\tset: function set(w) {\n\t\t\t\tif (typeof w !== 'number') throw new Error('wrong argument type');\n\t\t\t\tthis._weight = w;\n\t\t\t\tthis._thickness = w;\n\t\t\t\tthis._targetThickness = w;\n\t\t\t\tthis._maxWeight = w + this.WEIGHT_SPREAD;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'mode',\n\t\t\tget: function get() {\n\t\t\t\treturn this._mode;\n\t\t\t},\n\t\t\tset: function set(m) {\n\t\t\t\tif (typeof m !== 'string') throw new Error('wrong argument type');\n\t\t\t\tswitch (m) {\n\t\t\t\t\tcase 'erase':\n\t\t\t\t\t\tthis._mode = 'erase';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'destination-out';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'fill':\n\t\t\t\t\t\tthis._mode = 'fill';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthis._mode = 'draw';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'dirty',\n\t\t\tget: function get() {\n\t\t\t\treturn !!this._dirty;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'smoothing',\n\t\t\tget: function get() {\n\t\t\t\treturn this._smoothing === this.SMOOTHING_INIT;\n\t\t\t},\n\t\t\tset: function set(s) {\n\t\t\t\tif (typeof s !== 'boolean') throw new Error('wrong argument type');\n\t\t\t\tthis._smoothing = s ? this.SMOOTHING_INIT : 0;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'opacity',\n\t\t\tset: function set(o) {\n\t\t\t\tif (typeof o !== 'number') throw new Error('wrong argument type');\n\t\t\t\t//now, we need to scale this, because our drawing method means we don't just get uniform transparency all over the drawn line.\n\t\t\t\t//so we scale it down a lot, meaning that it'll look nicely semi-transparent\n\t\t\t\t//unless opacity is 1, then we should go full on to 1\n\t\t\t\tif (o >= 1) this.context.globalAlpha = 1;else this.context.globalAlpha = o / 10;\n\t\t\t}\n\t\t}], [{\n\t\t\tkey: 'lineDistance',\n\t\t\tvalue: function lineDistance(x1, y1, x2, y2) {\n\t\t\t\t//calculate euclidean distance between (x1, y1) and (x2, y2)\n\t\t\t\tvar xs = Math.pow(x2 - x1, 2);\n\t\t\t\tvar ys = Math.pow(y2 - y1, 2);\n\t\t\t\treturn Math.sqrt(xs + ys);\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'hexToRgb',\n\t\t\tvalue: function hexToRgb(hexColor) {\n\t\t\t\t//Since input type color provides hex and ImageData accepts RGB need to transform\n\t\t\t\tvar m = hexColor.match(/^#?([\\da-f]{2})([\\da-f]{2})([\\da-f]{2})$/i);\n\t\t\t\treturn [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16)];\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'matchColor',\n\t\t\tvalue: function matchColor(data, compR, compG, compB, compA) {\n\t\t\t\treturn function (pixelPos) {\n\t\t\t\t\t//Pixel color equals comp color?\n\t\t\t\t\tvar r = data[pixelPos],\n\t\t\t\t\t g = data[pixelPos + 1],\n\t\t\t\t\t b = data[pixelPos + 2],\n\t\t\t\t\t a = data[pixelPos + 3];\n\t\t\t\t\treturn r === compR && g === compG && b === compB && a === compA;\n\t\t\t\t};\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'colorPixel',\n\t\t\tvalue: function colorPixel(data, fillR, fillG, fillB, startColor, alpha) {\n\t\t\t\tvar matchColor = Atrament.matchColor.apply(Atrament, [data].concat(_toConsumableArray(startColor)));\n\t\n\t\t\t\treturn function (pixelPos) {\n\t\t\t\t\t//Update fill color in matrix\n\t\t\t\t\tdata[pixelPos] = fillR;\n\t\t\t\t\tdata[pixelPos + 1] = fillG;\n\t\t\t\t\tdata[pixelPos + 2] = fillB;\n\t\t\t\t\tdata[pixelPos + 3] = alpha;\n\t\n\t\t\t\t\tif (!matchColor(pixelPos + 4)) {\n\t\t\t\t\t\tdata[pixelPos + 4] = data[pixelPos + 4] * 0.01 + fillR * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 1] = data[pixelPos + 4 + 1] * 0.01 + fillG * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 2] = data[pixelPos + 4 + 2] * 0.01 + fillB * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 3] = data[pixelPos + 4 + 3] * 0.01 + alpha * 0.99;\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (!matchColor(pixelPos - 4)) {\n\t\t\t\t\t\tdata[pixelPos - 4] = data[pixelPos - 4] * 0.01 + fillR * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 1] = data[pixelPos - 4 + 1] * 0.01 + fillG * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 2] = data[pixelPos - 4 + 2] * 0.01 + fillB * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 3] = data[pixelPos - 4 + 3] * 0.01 + alpha * 0.99;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Atrament;\n\t}();\n\t\n\t//for people who like functional programming\n\t\n\t\n\tfunction atrament(selector, width, height, color) {\n\t\treturn new Atrament(selector, width, height, color);\n\t}\n\t\n\tmodule.exports = atrament;\n\tmodule.exports.Atrament = Atrament;\n\n/***/ }\n/******/ ])\n});\n;\n\n\n/** WEBPACK FOOTER **\n ** atrament.min.js\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 8a98e5ca26a13ff27517\n **/","module.exports = require('./src/atrament.js');\n\n\n/** WEBPACK FOOTER **\n ** ./index.js\n **/","//make a class for Point\nclass Point {\n\tconstructor(x, y) {\n\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.');\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t}\n\n\tget x() {\n\t\treturn this._x;\n\t}\n\n\tget y() {\n\t\treturn this._y;\n\t}\n\n\tset x(x) {\n\t\tthis._x = x;\n\t}\n\n\tset y(y) {\n\t\tthis._y = y;\n\t}\n\n\tset(x, y) {\n\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.set');\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t}\n}\n\n//make a class for the mouse data\nclass Mouse extends Point {\n\tconstructor() {\n\t\tsuper(0, 0);\n\t\tthis._down = false;\n\t\tthis._px = 0;\n\t\tthis._py = 0;\n\t}\n\n\tget down() {\n\t\treturn this._down;\n\t}\n\n\tset down(d) {\n\t\tthis._down = d;\n\t}\n\n\tget x() {\n\t\treturn this._x;\n\t}\n\n\tget y() {\n\t\treturn this._y;\n\t}\n\n\tset x(x) {\n\t\tthis._x = x;\n\t}\n\n\tset y(y) {\n\t\tthis._y = y;\n\t}\n\n\tget px() {\n\t\treturn this._px;\n\t}\n\n\tget py() {\n\t\treturn this._py;\n\t}\n\n\tset px(px) {\n\t\tthis._px = px;\n\t}\n\n\tset py(py) {\n\t\tthis._py = py;\n\t}\n\n}\n\n\nclass Atrament {\n\tconstructor(selector, width, height, color) {\n\t\tif (!document) throw new Error('no DOM found');\n\n\t\t//get canvas element\n\t\tif (selector instanceof Node && selector.tagName === 'CANVAS') this.canvas = selector;\n\t\telse if (typeof selector === 'string') this.canvas = document.querySelector(selector);\n\t\telse throw new Error(`can\\'t look for canvas based on \\'${selector}\\'`);\n\t\tif (!this.canvas) throw new Error('canvas not found');\n\n\t\t//set external canvas params\n\t\tthis.canvas.width = width ? width : 500;\n\t\tthis.canvas.height = height ? height : 500;\n\t\tthis.canvas.style.cursor = 'crosshair';\n\n\t\t//create a mouse object\n\t\tthis.mouse = new Mouse();\n\n\t\t//mousemove handler\n\t\tlet mouseMove = e => {\n\t\t\te.preventDefault();\n\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tconst position = e.changedTouches && e.changedTouches[0] || e;\n\t\t\tlet x = position.offsetX;\n\t\t\tlet y = position.offsetY;\n\n\t\t\tif (typeof x === 'undefined') {\n\t\t\t\tx = position.clientX + document.documentElement.scrollLeft - rect.left;\n\t\t\t}\n\t\t\tif (typeof y === 'undefined') {\n\t\t\t\ty = position.clientY + document.documentElement.scrollTop - rect.top;\n\t\t\t}\n\n\t\t\t//draw if we should draw\n\t\t\tif (this.mouse.down) {\n\t\t\t\tthis.draw(x, y);\n\t\t\t\tif (!this._dirty && (x !== this.mouse.x || y !== this.mouse.y)) {\n\t\t\t\t\tthis._dirty = true;\n\t\t\t\t\tthis.fireDirty();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.mouse.x = x;\n\t\t\t\tthis.mouse.y = y;\n\t\t\t}\n\t\t}\n\n\t\t//mousedown handler\n\t\tlet mouseDown = (mousePosition) => {\n\t\t\tmousePosition.preventDefault();\n\t\t\t//update position just in case\n\t\t\tmouseMove(mousePosition);\n\n\t\t\t//if we are filling - fill and return\n\t\t\tif(this._mode === 'fill'){\n\t\t\t\tthis.fill();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//remember it\n\t\t\tthis.mouse.px = this.mouse.x;\n\t\t\tthis.mouse.py = this.mouse.y;\n\t\t\t//begin drawing\n\t\t\tthis.mouse.down = true;\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.moveTo(this.mouse.px, this.mouse.py);\n\t\t}\n\t\tlet mouseUp = (mousePosition) => {\n\t\t\tmousePosition.preventDefault();\n\t\t\tthis.mouse.down = false;\n\t\t\t//stop drawing\n\t\t\tthis.context.closePath();\n\t\t}\n\n\t\t//attach listeners\n\t\tthis.canvas.addEventListener('mousemove', mouseMove);\n\t\tthis.canvas.addEventListener('mousedown', mouseDown);\n\t\tdocument.addEventListener('mouseup', mouseUp);\n\t\tthis.canvas.addEventListener('touchstart', mouseDown);\n\t\tthis.canvas.addEventListener('touchend', mouseUp);\n\t\tthis.canvas.addEventListener('touchmove', mouseMove);\n\n\t\t//helper for destroying Atrament (removing event listeners)\n\t\tthis.destroy = () => {\n\t\t\tthis.clear();\n\t\t\tthis.canvas.removeEventListener('mousemove', mouseMove);\n\t\t\tthis.canvas.removeEventListener('mousedown', mouseDown);\n\t\t\tdocument.removeEventListener('mouseup', mouseUp);\n\t\t\tthis.canvas.removeEventListener('touchstart', mouseDown);\n\t\t\tthis.canvas.removeEventListener('touchend', mouseUp);\n\t\t\tthis.canvas.removeEventListener('touchmove', mouseMove);\n\t\t};\n\n\t\t//set internal canvas params\n\t\tthis.context = this.canvas.getContext('2d');\n\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\tthis.context.globalAlpha = 1;\n\t\tthis.context.strokeStyle = color ? color : 'black';\n\t\tthis.context.lineCap = 'round';\n\t\tthis.context.lineJoin = 'round';\n\t\tthis.context.translate(0.5, 0.5);\n\n\t\tthis._filling = false;\n\t\tthis._fillStack = [];\n\n\t\t//set drawing params\n\t\tthis.SMOOTHING_INIT = 0.85;\n\t\tthis.WEIGHT_SPREAD = 10;\n\t\tthis._smoothing = this.SMOOTHING_INIT;\n\t\tthis._maxWeight = 12;\n\t\tthis._thickness = 2;\n\t\tthis._targetThickness = 2;\n\t\tthis._weight = 2;\n\t\tthis._mode = 'draw';\n\t}\n\n\tstatic lineDistance(x1, y1, x2, y2) {\n\t\t//calculate euclidean distance between (x1, y1) and (x2, y2)\n\t let xs = Math.pow(x2 - x1, 2);\n\t\tlet ys = Math.pow(y2 - y1, 2);\n\t return Math.sqrt( xs + ys );\n\t}\n\n\tstatic hexToRgb(hexColor){\n\t\t//Since input type color provides hex and ImageData accepts RGB need to transform\n\t\tlet m = hexColor.match(/^#?([\\da-f]{2})([\\da-f]{2})([\\da-f]{2})$/i);\n\t\treturn [\n\t\t\tparseInt(m[1], 16),\n\t\t\tparseInt(m[2], 16),\n\t\t\tparseInt(m[3], 16)\n\t\t];\n\t}\n\n\tstatic matchColor(data, compR, compG, compB, compA) {\n\t\treturn (pixelPos)=>{\n\t\t\t//Pixel color equals comp color?\n\t\t\tlet r = data[pixelPos],\n\t\t\t\tg = data[pixelPos+1],\n\t\t\t\tb = data[pixelPos+2],\n\t\t\t\ta = data[pixelPos+3];\n\t\t\treturn (r === compR && g === compG && b === compB && a === compA);\n\t\t}\n\t}\n\n\tstatic colorPixel(data, fillR, fillG, fillB, startColor, alpha) {\n\t\tlet matchColor = Atrament.matchColor(data, ...startColor);\n\n\t\treturn (pixelPos)=>{\n\t\t\t//Update fill color in matrix\n\t\t\tdata[pixelPos] = fillR;\n\t\t\tdata[pixelPos+1] = fillG;\n\t\t\tdata[pixelPos+2] = fillB;\n\t\t\tdata[pixelPos+3] = alpha;\n\n\t\t\tif (!matchColor(pixelPos + 4)) {\n\t\t\t\tdata[pixelPos+4] = data[pixelPos+4] * 0.01 + fillR*0.99;\n\t\t\t\tdata[pixelPos+4+1] = data[pixelPos+4+1] * 0.01 + fillG*0.99;\n\t\t\t\tdata[pixelPos+4+2] = data[pixelPos+4+2] * 0.01 + fillB*0.99;\n\t\t\t\tdata[pixelPos+4+3] = data[pixelPos+4+3] * 0.01 + alpha*0.99;\n\t\t\t}\n\n\t\t\tif (!matchColor(pixelPos - 4)) {\n\t\t\t\tdata[pixelPos-4] = data[pixelPos-4] * 0.01 + fillR*0.99;\n\t\t\t\tdata[pixelPos-4+1] = data[pixelPos-4+1] * 0.01 + fillG*0.99;\n\t\t\t\tdata[pixelPos-4+2] = data[pixelPos-4+2] * 0.01 + fillB*0.99;\n\t\t\t\tdata[pixelPos-4+3] = data[pixelPos-4+3] * 0.01 + alpha*0.99;\n\t\t\t}\n\t\t}\n\n\t}\n\n\tdraw(mX, mY) {\n\t\tlet mouse = this.mouse;\n\t\tlet context = this.context;\n\n\t\t//calculate distance from previous point\n\t\tlet raw_dist = Atrament.lineDistance(mX, mY, mouse.px, mouse.py)\n\n\t\t//now, here we scale the initial smoothing factor by the raw distance\n\t\t//this means that when the mouse moves fast, there is more smoothing\n\t\t//and when we're drawing small detailed stuff, we have more control\n\t\t//also we hard clip at 1\n\t\tlet smoothingFactor = Math.min(0.87, this._smoothing + (raw_dist - 60) / 3000);\n\n\t\t//calculate smoothed coordinates\n\t\tmouse.x = mX - (mX - mouse.px) * smoothingFactor;\n\t\tmouse.y = mY - (mY - mouse.py) * smoothingFactor;\n\n\t\t//recalculate distance from previous point, this time relative to the smoothed coords\n\t\tlet dist = Atrament.lineDistance(mouse.x, mouse.y, mouse.px, mouse.py)\n\n\t\t//calculate target thickness based on the new distance\n\t\tthis._targetThickness = (dist - 1) / (50 - 1) * (this._maxWeight - this._weight) + this._weight;\n\t\t//approach the target gradually\n\t\tif (this._thickness > this._targetThickness) {\n\t\t\tthis._thickness -= 0.5;\n\t\t}\n\t\telse if (this._thickness < this._targetThickness) {\n\t\t\tthis._thickness += 0.5;\n\t\t}\n\t\t//set line width\n\t\tcontext.lineWidth = this._thickness;\n\n\t\t//draw using quad interpolation\n\t\tcontext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);\n\t\tcontext.stroke();\n\n\t\t//remember\n\t\tmouse.px = mouse.x;\n\t\tmouse.py = mouse.y;\n\t}\n\n\tget color() {\n\t\treturn this.context.strokeStyle;\n\t}\n\n\tset color(c) {\n\t\tif (typeof c !== 'string') throw new Error('wrong argument type');\n\t\tthis.context.strokeStyle = c;\n\t}\n\n\tget weight() {\n\t\treturn this._weight;\n\t}\n\n\tset weight(w) {\n\t\tif (typeof w !== 'number') throw new Error('wrong argument type');\n\t\tthis._weight = w;\n\t\tthis._thickness = w;\n\t\tthis._targetThickness = w;\n\t\tthis._maxWeight = w + this.WEIGHT_SPREAD;\n\t}\n\n\tget mode() {\n\t\treturn this._mode;\n\t}\n\n\tget dirty() {\n\t\treturn !!this._dirty;\n\t}\n\n\tset mode(m) {\n\t\tif (typeof m !== 'string') throw new Error('wrong argument type');\n\t\tswitch (m) {\n\t\t\tcase 'erase':\n\t\t\t\tthis._mode = 'erase';\n\t\t\t\tthis.context.globalCompositeOperation = 'destination-out';\n\t\t\t\tbreak;\n\t\t\tcase 'fill':\n\t\t\t\tthis._mode = 'fill';\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis._mode = 'draw';\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tget smoothing() {\n\t\treturn this._smoothing === this.SMOOTHING_INIT;\n\t}\n\n\tset smoothing(s) {\n\t\tif (typeof s !== 'boolean') throw new Error('wrong argument type');\n\t\tthis._smoothing = s ? this.SMOOTHING_INIT : 0;\n\t}\n\n\tset opacity(o) {\n\t\tif (typeof o !== 'number') throw new Error('wrong argument type');\n\t\t//now, we need to scale this, because our drawing method means we don't just get uniform transparency all over the drawn line.\n\t\t//so we scale it down a lot, meaning that it'll look nicely semi-transparent\n\t\t//unless opacity is 1, then we should go full on to 1\n\t\tif (o >= 1) this.context.globalAlpha = 1;\n\t\telse this.context.globalAlpha = o/10;\n\t}\n\n\tfireDirty() {\n\t\tconst event = document.createEvent('Event');\n\t\tevent.initEvent('dirty', true, true);\n\t\tthis.canvas.dispatchEvent(event);\n\t}\n\n\tclear() {\n\t\tif (!this.dirty) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._dirty = false;\n\t\tthis.fireDirty();\n\n\t\t//make sure we're in the right compositing mode, and erase everything\n\t\tif (this.context.globalCompositeOperation === 'destination-out') {\n\t\t\tthis.mode = 'draw';\n\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\tthis.mode = 'erase';\n\t\t}\n\t\telse {\n\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t}\n\t}\n\n\ttoImage() {\n\t\treturn this.canvas.toDataURL();\n\t}\n\n\tfill(){\n\t\tlet mouse = this.mouse;\n\t\tlet context = this.context;\n\t\tlet startColor = Array.prototype.slice.call(context.getImageData(mouse.x, mouse.y, 1, 1).data,0); //converting to Array because Safari 9\n\n\t\tif (!this._filling) {\n\t\t\tthis.canvas.style.cursor = 'progress';\n\t\t\tthis._filling = true;\n\n\t\t\tsetTimeout(() => { this._floodFill(mouse.x, mouse.y, startColor); }, 100);\n\t\t}\n\t\telse {\n\t\t\tthis._fillStack.push([\n\t\t\t\tmouse.x,\n\t\t\t\tmouse.y,\n\t\t\t\tstartColor\n\t\t\t]);\n\t\t}\n\t}\n\n\t_floodFill(startX, startY, startColor){\n\t\tlet context = this.context,\n\t\t\tcanvasWidth = context.canvas.width,\n\t\t\tcanvasHeight = context.canvas.height,\n\t\t\tpixelStack = [[startX, startY]],\n\t\t\t//hex needs to be trasformed to rgb since colorLayer accepts RGB\n\t\t\tfillColor = Atrament.hexToRgb(this.color),\n\t\t\t//Need to save current context with colors, we will update it\n\t\t\tcolorLayer = context.getImageData(0, 0, context.canvas.width, context.canvas.height),\n\t\t\talpha = Math.min(context.globalAlpha * 10 * 255, 255),\n\t\t\tcolorPixel = Atrament.colorPixel(colorLayer.data, ...fillColor, startColor, alpha),\n\t\t\tmatchColor = Atrament.matchColor(colorLayer.data, ...startColor);\n\n\n\t\twhile(pixelStack.length) {\n\t\t\tlet newPos = pixelStack.pop();\n\t\t\tlet [x,y] = newPos;\n\n\t\t\tlet pixelPos = (y*canvasWidth + x) * 4;\n\n\t\t\twhile(y-- >= 0 && matchColor(pixelPos))\n\t\t\t{\n\t\t\t\tpixelPos -= canvasWidth * 4;\n\t\t\t}\n\t\t\tpixelPos += canvasWidth * 4;\n\n\t\t\t++y;\n\n\t\t\tlet reachLeft = false;\n\t\t\tlet reachRight = false;\n\n\t\t\twhile(y++ < canvasHeight-1 && matchColor(pixelPos))\n\t\t\t{\n\t\t\t\tcolorPixel(pixelPos);\n\n\t\t\t\tif(x > 0)\n\t\t\t\t{\n\t\t\t\t\tif(matchColor(pixelPos - 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!reachLeft){\n\t\t\t\t\t\t\tpixelStack.push([x - 1, y]);\n\t\t\t\t\t\t\treachLeft = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(reachLeft)\n\t\t\t\t\t{\n\t\t\t\t\t\treachLeft = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(x < canvasWidth-1)\n\t\t\t\t{\n\t\t\t\t\tif(matchColor(pixelPos + 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!reachRight)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpixelStack.push([x + 1, y]);\n\t\t\t\t\t\t\treachRight = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(reachRight)\n\t\t\t\t\t{\n\t\t\t\t\t\treachRight = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpixelPos += canvasWidth * 4;\n\t\t\t}\n\t\t}\n\n\t\t//Update context with filled bucket!\n\t\tcontext.putImageData(colorLayer, 0, 0);\n\n\t\tif (this._fillStack.length) {\n\t\t\tthis._floodFill(...this._fillStack.shift());\n\t\t}\n\t\telse {\n\t\t\tthis._filling = false;\n\t\t\tsetTimeout(() => { this.canvas.style.cursor = 'crosshair'; }, 100);\n\t\t}\n\n\t}\n\n}\n\n//for people who like functional programming\nfunction atrament(selector, width, height, color) {\n\treturn new Atrament(selector, width, height, color);\n}\n\nmodule.exports = atrament;\nmodule.exports.Atrament = Atrament;\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/atrament.js\n **/"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///atrament.min.js","webpack:///webpack/bootstrap 56eadc523feeb4c79eb1","webpack:///./index.js","webpack:///./src/atrament.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","_toConsumableArray","arr","Array","isArray","i","arr2","length","from","_possibleConstructorReturn","self","ReferenceError","_inherits","subClass","superClass","TypeError","prototype","Object","create","constructor","value","enumerable","writable","configurable","setPrototypeOf","__proto__","_classCallCheck","instance","Constructor","atrament","selector","width","height","color","Atrament","_slicedToArray","sliceIterator","_arr","_n","_d","_e","undefined","_s","_i","Symbol","iterator","next","done","push","err","_createClass","defineProperties","target","props","descriptor","defineProperty","key","protoProps","staticProps","Point","x","y","arguments","Error","_x","_y","get","set","Mouse","_Point","_this","getPrototypeOf","_down","_px","_py","d","px","py","_this2","document","Node","tagName","canvas","querySelector","style","cursor","mouse","mouseMove","e","preventDefault","rect","getBoundingClientRect","position","changedTouches","offsetX","offsetY","clientX","documentElement","scrollLeft","left","clientY","scrollTop","top","down","draw","_dirty","fireDirty","mouseDown","mousePosition","_mode","fill","context","beginPath","moveTo","mouseUp","closePath","addEventListener","destroy","clear","removeEventListener","getContext","globalCompositeOperation","globalAlpha","strokeStyle","lineCap","lineJoin","translate","_filling","_fillStack","SMOOTHING_INIT","WEIGHT_SPREAD","_smoothing","_maxWeight","_thickness","_targetThickness","_weight","mX","mY","raw_dist","lineDistance","smoothingFactor","Math","min","dist","lineWidth","quadraticCurveTo","stroke","event","createEvent","initEvent","dispatchEvent","dirty","mode","clearRect","toDataURL","_this3","startColor","slice","getImageData","data","setTimeout","_floodFill","startX","startY","_this4","canvasWidth","canvasHeight","pixelStack","fillColor","hexToRgb","colorLayer","alpha","colorPixel","apply","concat","matchColor","matchFillColor","newPos","pop","_newPos","pixelPos","reachLeft","reachRight","putImageData","shift","w","s","o","x1","y1","x2","y2","xs","pow","ys","sqrt","hexColor","match","parseInt","compR","compG","compB","compA","r","g","b","a","fillR","fillG","fillB"],"mappings":"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","file":"atrament.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"atrament\"] = factory();\n\telse\n\t\troot[\"atrament\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"atrament\"] = factory();\n\telse\n\t\troot[\"atrament\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(1);\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tmodule.exports = __webpack_require__(2);\n\n/***/ },\n/* 2 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\tvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\t\n\tvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\t\n\tfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\t\n\tfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\t\n\tfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\t\n\tfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\t\n\t//make a class for Point\n\tvar Point = function () {\n\t\tfunction Point(x, y) {\n\t\t\t_classCallCheck(this, Point);\n\t\n\t\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.');\n\t\t\tthis._x = x;\n\t\t\tthis._y = y;\n\t\t}\n\t\n\t\t_createClass(Point, [{\n\t\t\tkey: 'set',\n\t\t\tvalue: function set(x, y) {\n\t\t\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.set');\n\t\t\t\tthis._x = x;\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'x',\n\t\t\tget: function get() {\n\t\t\t\treturn this._x;\n\t\t\t},\n\t\t\tset: function set(x) {\n\t\t\t\tthis._x = x;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'y',\n\t\t\tget: function get() {\n\t\t\t\treturn this._y;\n\t\t\t},\n\t\t\tset: function set(y) {\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Point;\n\t}();\n\t\n\t//make a class for the mouse data\n\t\n\t\n\tvar Mouse = function (_Point) {\n\t\t_inherits(Mouse, _Point);\n\t\n\t\tfunction Mouse() {\n\t\t\t_classCallCheck(this, Mouse);\n\t\n\t\t\tvar _this = _possibleConstructorReturn(this, (Mouse.__proto__ || Object.getPrototypeOf(Mouse)).call(this, 0, 0));\n\t\n\t\t\t_this._down = false;\n\t\t\t_this._px = 0;\n\t\t\t_this._py = 0;\n\t\t\treturn _this;\n\t\t}\n\t\n\t\t_createClass(Mouse, [{\n\t\t\tkey: 'down',\n\t\t\tget: function get() {\n\t\t\t\treturn this._down;\n\t\t\t},\n\t\t\tset: function set(d) {\n\t\t\t\tthis._down = d;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'x',\n\t\t\tget: function get() {\n\t\t\t\treturn this._x;\n\t\t\t},\n\t\t\tset: function set(x) {\n\t\t\t\tthis._x = x;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'y',\n\t\t\tget: function get() {\n\t\t\t\treturn this._y;\n\t\t\t},\n\t\t\tset: function set(y) {\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'px',\n\t\t\tget: function get() {\n\t\t\t\treturn this._px;\n\t\t\t},\n\t\t\tset: function set(px) {\n\t\t\t\tthis._px = px;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'py',\n\t\t\tget: function get() {\n\t\t\t\treturn this._py;\n\t\t\t},\n\t\t\tset: function set(py) {\n\t\t\t\tthis._py = py;\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Mouse;\n\t}(Point);\n\t\n\tvar Atrament = function () {\n\t\tfunction Atrament(selector, width, height, color) {\n\t\t\tvar _this2 = this;\n\t\n\t\t\t_classCallCheck(this, Atrament);\n\t\n\t\t\tif (!document) throw new Error('no DOM found');\n\t\n\t\t\t//get canvas element\n\t\t\tif (selector instanceof Node && selector.tagName === 'CANVAS') this.canvas = selector;else if (typeof selector === 'string') this.canvas = document.querySelector(selector);else throw new Error('can\\'t look for canvas based on \\'' + selector + '\\'');\n\t\t\tif (!this.canvas) throw new Error('canvas not found');\n\t\n\t\t\t//set external canvas params\n\t\t\tthis.canvas.width = width ? width : 500;\n\t\t\tthis.canvas.height = height ? height : 500;\n\t\t\tthis.canvas.style.cursor = 'crosshair';\n\t\n\t\t\t//create a mouse object\n\t\t\tthis.mouse = new Mouse();\n\t\n\t\t\t//mousemove handler\n\t\t\tvar mouseMove = function mouseMove(e) {\n\t\t\t\te.preventDefault();\n\t\n\t\t\t\tvar rect = _this2.canvas.getBoundingClientRect();\n\t\t\t\tvar position = e.changedTouches && e.changedTouches[0] || e;\n\t\t\t\tvar x = position.offsetX;\n\t\t\t\tvar y = position.offsetY;\n\t\n\t\t\t\tif (typeof x === 'undefined') {\n\t\t\t\t\tx = position.clientX + document.documentElement.scrollLeft - rect.left;\n\t\t\t\t}\n\t\t\t\tif (typeof y === 'undefined') {\n\t\t\t\t\ty = position.clientY + document.documentElement.scrollTop - rect.top;\n\t\t\t\t}\n\t\n\t\t\t\t//draw if we should draw\n\t\t\t\tif (_this2.mouse.down) {\n\t\t\t\t\t_this2.draw(x, y);\n\t\t\t\t\tif (!_this2._dirty && (x !== _this2.mouse.x || y !== _this2.mouse.y)) {\n\t\t\t\t\t\t_this2._dirty = true;\n\t\t\t\t\t\t_this2.fireDirty();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t_this2.mouse.x = x;\n\t\t\t\t\t_this2.mouse.y = y;\n\t\t\t\t}\n\t\t\t};\n\t\n\t\t\t//mousedown handler\n\t\t\tvar mouseDown = function mouseDown(mousePosition) {\n\t\t\t\tmousePosition.preventDefault();\n\t\t\t\t//update position just in case\n\t\t\t\tmouseMove(mousePosition);\n\t\n\t\t\t\t//if we are filling - fill and return\n\t\t\t\tif (_this2._mode === 'fill') {\n\t\t\t\t\t_this2.fill();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\t//remember it\n\t\t\t\t_this2.mouse.px = _this2.mouse.x;\n\t\t\t\t_this2.mouse.py = _this2.mouse.y;\n\t\t\t\t//begin drawing\n\t\t\t\t_this2.mouse.down = true;\n\t\t\t\t_this2.context.beginPath();\n\t\t\t\t_this2.context.moveTo(_this2.mouse.px, _this2.mouse.py);\n\t\t\t};\n\t\t\tvar mouseUp = function mouseUp(mousePosition) {\n\t\t\t\tmousePosition.preventDefault();\n\t\t\t\t_this2.mouse.down = false;\n\t\t\t\t//stop drawing\n\t\t\t\t_this2.context.closePath();\n\t\t\t};\n\t\n\t\t\t//attach listeners\n\t\t\tthis.canvas.addEventListener('mousemove', mouseMove);\n\t\t\tthis.canvas.addEventListener('mousedown', mouseDown);\n\t\t\tdocument.addEventListener('mouseup', mouseUp);\n\t\t\tthis.canvas.addEventListener('touchstart', mouseDown);\n\t\t\tthis.canvas.addEventListener('touchend', mouseUp);\n\t\t\tthis.canvas.addEventListener('touchmove', mouseMove);\n\t\n\t\t\t//helper for destroying Atrament (removing event listeners)\n\t\t\tthis.destroy = function () {\n\t\t\t\t_this2.clear();\n\t\t\t\t_this2.canvas.removeEventListener('mousemove', mouseMove);\n\t\t\t\t_this2.canvas.removeEventListener('mousedown', mouseDown);\n\t\t\t\tdocument.removeEventListener('mouseup', mouseUp);\n\t\t\t\t_this2.canvas.removeEventListener('touchstart', mouseDown);\n\t\t\t\t_this2.canvas.removeEventListener('touchend', mouseUp);\n\t\t\t\t_this2.canvas.removeEventListener('touchmove', mouseMove);\n\t\t\t};\n\t\n\t\t\t//set internal canvas params\n\t\t\tthis.context = this.canvas.getContext('2d');\n\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\tthis.context.globalAlpha = 1;\n\t\t\tthis.context.strokeStyle = color ? color : 'rgba(0,0,0,1)';\n\t\t\tthis.context.lineCap = 'round';\n\t\t\tthis.context.lineJoin = 'round';\n\t\t\tthis.context.translate(0.5, 0.5);\n\t\n\t\t\tthis._filling = false;\n\t\t\tthis._fillStack = [];\n\t\n\t\t\t//set drawing params\n\t\t\tthis.SMOOTHING_INIT = 0.85;\n\t\t\tthis.WEIGHT_SPREAD = 10;\n\t\t\tthis._smoothing = this.SMOOTHING_INIT;\n\t\t\tthis._maxWeight = 12;\n\t\t\tthis._thickness = 2;\n\t\t\tthis._targetThickness = 2;\n\t\t\tthis._weight = 2;\n\t\t\tthis._mode = 'draw';\n\t\t}\n\t\n\t\t_createClass(Atrament, [{\n\t\t\tkey: 'draw',\n\t\t\tvalue: function draw(mX, mY) {\n\t\t\t\tvar mouse = this.mouse;\n\t\t\t\tvar context = this.context;\n\t\n\t\t\t\t//calculate distance from previous point\n\t\t\t\tvar raw_dist = Atrament.lineDistance(mX, mY, mouse.px, mouse.py);\n\t\n\t\t\t\t//now, here we scale the initial smoothing factor by the raw distance\n\t\t\t\t//this means that when the mouse moves fast, there is more smoothing\n\t\t\t\t//and when we're drawing small detailed stuff, we have more control\n\t\t\t\t//also we hard clip at 1\n\t\t\t\tvar smoothingFactor = Math.min(0.87, this._smoothing + (raw_dist - 60) / 3000);\n\t\n\t\t\t\t//calculate smoothed coordinates\n\t\t\t\tmouse.x = mX - (mX - mouse.px) * smoothingFactor;\n\t\t\t\tmouse.y = mY - (mY - mouse.py) * smoothingFactor;\n\t\n\t\t\t\t//recalculate distance from previous point, this time relative to the smoothed coords\n\t\t\t\tvar dist = Atrament.lineDistance(mouse.x, mouse.y, mouse.px, mouse.py);\n\t\n\t\t\t\t//calculate target thickness based on the new distance\n\t\t\t\tthis._targetThickness = (dist - 1) / (50 - 1) * (this._maxWeight - this._weight) + this._weight;\n\t\t\t\t//approach the target gradually\n\t\t\t\tif (this._thickness > this._targetThickness) {\n\t\t\t\t\tthis._thickness -= 0.5;\n\t\t\t\t} else if (this._thickness < this._targetThickness) {\n\t\t\t\t\tthis._thickness += 0.5;\n\t\t\t\t}\n\t\t\t\t//set line width\n\t\t\t\tcontext.lineWidth = this._thickness;\n\t\n\t\t\t\t//draw using quad interpolation\n\t\t\t\tcontext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);\n\t\t\t\tcontext.stroke();\n\t\n\t\t\t\t//remember\n\t\t\t\tmouse.px = mouse.x;\n\t\t\t\tmouse.py = mouse.y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'fireDirty',\n\t\t\tvalue: function fireDirty() {\n\t\t\t\tvar event = document.createEvent('Event');\n\t\t\t\tevent.initEvent('dirty', true, true);\n\t\t\t\tthis.canvas.dispatchEvent(event);\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'clear',\n\t\t\tvalue: function clear() {\n\t\t\t\tif (!this.dirty) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\tthis._dirty = false;\n\t\t\t\tthis.fireDirty();\n\t\n\t\t\t\t//make sure we're in the right compositing mode, and erase everything\n\t\t\t\tif (this.context.globalCompositeOperation === 'destination-out') {\n\t\t\t\t\tthis.mode = 'draw';\n\t\t\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\t\t\tthis.mode = 'erase';\n\t\t\t\t} else {\n\t\t\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'toImage',\n\t\t\tvalue: function toImage() {\n\t\t\t\treturn this.canvas.toDataURL();\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'fill',\n\t\t\tvalue: function fill() {\n\t\t\t\tvar _this3 = this;\n\t\n\t\t\t\tvar mouse = this.mouse;\n\t\t\t\tvar context = this.context;\n\t\t\t\tvar startColor = Array.prototype.slice.call(context.getImageData(mouse.x, mouse.y, 1, 1).data, 0); //converting to Array because Safari 9\n\t\n\t\t\t\tif (!this._filling) {\n\t\t\t\t\tthis.canvas.style.cursor = 'progress';\n\t\t\t\t\tthis._filling = true;\n\t\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this3._floodFill(mouse.x, mouse.y, startColor);\n\t\t\t\t\t}, 100);\n\t\t\t\t} else {\n\t\t\t\t\tthis._fillStack.push([mouse.x, mouse.y, startColor]);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: '_floodFill',\n\t\t\tvalue: function _floodFill(startX, startY, startColor) {\n\t\t\t\tvar _this4 = this;\n\t\n\t\t\t\tvar context = this.context,\n\t\t\t\t canvasWidth = context.canvas.width,\n\t\t\t\t canvasHeight = context.canvas.height,\n\t\t\t\t pixelStack = [[startX, startY]],\n\t\n\t\t\t\t//hex needs to be trasformed to rgb since colorLayer accepts RGB\n\t\t\t\tfillColor = Atrament.hexToRgb(this.color),\n\t\n\t\t\t\t//Need to save current context with colors, we will update it\n\t\t\t\tcolorLayer = context.getImageData(0, 0, context.canvas.width, context.canvas.height),\n\t\t\t\t alpha = Math.min(context.globalAlpha * 10 * 255, 255),\n\t\t\t\t colorPixel = Atrament.colorPixel.apply(Atrament, [colorLayer.data].concat(_toConsumableArray(fillColor), [startColor, alpha])),\n\t\t\t\t matchColor = Atrament.matchColor.apply(Atrament, [colorLayer.data].concat(_toConsumableArray(startColor)));\n\t\n\t\t\t\tvar matchFillColor = Atrament.matchColor.apply(Atrament, [colorLayer.data].concat([].concat(_toConsumableArray(fillColor), [255])));\n\t\t\t\t// check if we're trying to fill with the same colour, if so, stop\n\t\t\t\tif (matchFillColor((startY * context.canvas.width + startX) * 4)) {\n\t\t\t\t\tthis._filling = false;\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this4.canvas.style.cursor = 'crosshair';\n\t\t\t\t\t}, 100);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\twhile (pixelStack.length) {\n\t\t\t\t\tvar newPos = pixelStack.pop();\n\t\n\t\t\t\t\tvar _newPos = _slicedToArray(newPos, 2),\n\t\t\t\t\t x = _newPos[0],\n\t\t\t\t\t y = _newPos[1];\n\t\n\t\t\t\t\tvar pixelPos = (y * canvasWidth + x) * 4;\n\t\n\t\t\t\t\twhile (y-- >= 0 && matchColor(pixelPos)) {\n\t\t\t\t\t\tpixelPos -= canvasWidth * 4;\n\t\t\t\t\t}\n\t\t\t\t\tpixelPos += canvasWidth * 4;\n\t\n\t\t\t\t\t++y;\n\t\n\t\t\t\t\tvar reachLeft = false;\n\t\t\t\t\tvar reachRight = false;\n\t\n\t\t\t\t\twhile (y++ < canvasHeight - 1 && matchColor(pixelPos)) {\n\t\t\t\t\t\tcolorPixel(pixelPos);\n\t\n\t\t\t\t\t\tif (x > 0) {\n\t\t\t\t\t\t\tif (matchColor(pixelPos - 4)) {\n\t\t\t\t\t\t\t\tif (!reachLeft) {\n\t\t\t\t\t\t\t\t\tpixelStack.push([x - 1, y]);\n\t\t\t\t\t\t\t\t\treachLeft = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (reachLeft) {\n\t\t\t\t\t\t\t\treachLeft = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tif (x < canvasWidth - 1) {\n\t\t\t\t\t\t\tif (matchColor(pixelPos + 4)) {\n\t\t\t\t\t\t\t\tif (!reachRight) {\n\t\t\t\t\t\t\t\t\tpixelStack.push([x + 1, y]);\n\t\t\t\t\t\t\t\t\treachRight = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (reachRight) {\n\t\t\t\t\t\t\t\treachRight = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tpixelPos += canvasWidth * 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\n\t\t\t\t//Update context with filled bucket!\n\t\t\t\tcontext.putImageData(colorLayer, 0, 0);\n\t\n\t\t\t\tif (this._fillStack.length) {\n\t\t\t\t\tthis._floodFill.apply(this, _toConsumableArray(this._fillStack.shift()));\n\t\t\t\t} else {\n\t\t\t\t\tthis._filling = false;\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this4.canvas.style.cursor = 'crosshair';\n\t\t\t\t\t}, 100);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'color',\n\t\t\tget: function get() {\n\t\t\t\treturn this.context.strokeStyle;\n\t\t\t},\n\t\t\tset: function set(c) {\n\t\t\t\tif (typeof c !== 'string') throw new Error('wrong argument type');\n\t\t\t\tthis.context.strokeStyle = c;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'weight',\n\t\t\tget: function get() {\n\t\t\t\treturn this._weight;\n\t\t\t},\n\t\t\tset: function set(w) {\n\t\t\t\tif (typeof w !== 'number') throw new Error('wrong argument type');\n\t\t\t\tthis._weight = w;\n\t\t\t\tthis._thickness = w;\n\t\t\t\tthis._targetThickness = w;\n\t\t\t\tthis._maxWeight = w + this.WEIGHT_SPREAD;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'mode',\n\t\t\tget: function get() {\n\t\t\t\treturn this._mode;\n\t\t\t},\n\t\t\tset: function set(m) {\n\t\t\t\tif (typeof m !== 'string') throw new Error('wrong argument type');\n\t\t\t\tswitch (m) {\n\t\t\t\t\tcase 'erase':\n\t\t\t\t\t\tthis._mode = 'erase';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'destination-out';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'fill':\n\t\t\t\t\t\tthis._mode = 'fill';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthis._mode = 'draw';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'dirty',\n\t\t\tget: function get() {\n\t\t\t\treturn !!this._dirty;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'smoothing',\n\t\t\tget: function get() {\n\t\t\t\treturn this._smoothing === this.SMOOTHING_INIT;\n\t\t\t},\n\t\t\tset: function set(s) {\n\t\t\t\tif (typeof s !== 'boolean') throw new Error('wrong argument type');\n\t\t\t\tthis._smoothing = s ? this.SMOOTHING_INIT : 0;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'opacity',\n\t\t\tset: function set(o) {\n\t\t\t\tif (typeof o !== 'number') throw new Error('wrong argument type');\n\t\t\t\t//now, we need to scale this, because our drawing method means we don't just get uniform transparency all over the drawn line.\n\t\t\t\t//so we scale it down a lot, meaning that it'll look nicely semi-transparent\n\t\t\t\t//unless opacity is 1, then we should go full on to 1\n\t\t\t\tif (o >= 1) this.context.globalAlpha = 1;else this.context.globalAlpha = o / 10;\n\t\t\t}\n\t\t}], [{\n\t\t\tkey: 'lineDistance',\n\t\t\tvalue: function lineDistance(x1, y1, x2, y2) {\n\t\t\t\t//calculate euclidean distance between (x1, y1) and (x2, y2)\n\t\t\t\tvar xs = Math.pow(x2 - x1, 2);\n\t\t\t\tvar ys = Math.pow(y2 - y1, 2);\n\t\t\t\treturn Math.sqrt(xs + ys);\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'hexToRgb',\n\t\t\tvalue: function hexToRgb(hexColor) {\n\t\t\t\t//Since input type color provides hex and ImageData accepts RGB need to transform\n\t\t\t\tvar m = hexColor.match(/^#?([\\da-f]{2})([\\da-f]{2})([\\da-f]{2})$/i);\n\t\t\t\treturn [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16)];\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'matchColor',\n\t\t\tvalue: function matchColor(data, compR, compG, compB, compA) {\n\t\t\t\treturn function (pixelPos) {\n\t\t\t\t\t//Pixel color equals comp color?\n\t\t\t\t\tvar r = data[pixelPos],\n\t\t\t\t\t g = data[pixelPos + 1],\n\t\t\t\t\t b = data[pixelPos + 2],\n\t\t\t\t\t a = data[pixelPos + 3];\n\t\n\t\t\t\t\treturn r === compR && g === compG && b === compB && a === compA;\n\t\t\t\t};\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'colorPixel',\n\t\t\tvalue: function colorPixel(data, fillR, fillG, fillB, startColor, alpha) {\n\t\t\t\tvar matchColor = Atrament.matchColor.apply(Atrament, [data].concat(_toConsumableArray(startColor)));\n\t\n\t\t\t\treturn function (pixelPos) {\n\t\t\t\t\t//Update fill color in matrix\n\t\t\t\t\tdata[pixelPos] = fillR;\n\t\t\t\t\tdata[pixelPos + 1] = fillG;\n\t\t\t\t\tdata[pixelPos + 2] = fillB;\n\t\t\t\t\tdata[pixelPos + 3] = alpha;\n\t\n\t\t\t\t\tif (!matchColor(pixelPos + 4)) {\n\t\t\t\t\t\tdata[pixelPos + 4] = data[pixelPos + 4] * 0.01 + fillR * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 1] = data[pixelPos + 4 + 1] * 0.01 + fillG * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 2] = data[pixelPos + 4 + 2] * 0.01 + fillB * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 3] = data[pixelPos + 4 + 3] * 0.01 + alpha * 0.99;\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (!matchColor(pixelPos - 4)) {\n\t\t\t\t\t\tdata[pixelPos - 4] = data[pixelPos - 4] * 0.01 + fillR * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 1] = data[pixelPos - 4 + 1] * 0.01 + fillG * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 2] = data[pixelPos - 4 + 2] * 0.01 + fillB * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 3] = data[pixelPos - 4 + 3] * 0.01 + alpha * 0.99;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Atrament;\n\t}();\n\t\n\t//for people who like functional programming\n\t\n\t\n\tfunction atrament(selector, width, height, color) {\n\t\treturn new Atrament(selector, width, height, color);\n\t}\n\t\n\tmodule.exports = atrament;\n\tmodule.exports.Atrament = Atrament;\n\n/***/ }\n/******/ ])\n});\n;\n\n\n// WEBPACK FOOTER //\n// atrament.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 56eadc523feeb4c79eb1","module.exports = require('./src/atrament.js');\n\n\n// WEBPACK FOOTER //\n// ./index.js","//make a class for Point\nclass Point {\n\tconstructor(x, y) {\n\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.');\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t}\n\n\tget x() {\n\t\treturn this._x;\n\t}\n\n\tget y() {\n\t\treturn this._y;\n\t}\n\n\tset x(x) {\n\t\tthis._x = x;\n\t}\n\n\tset y(y) {\n\t\tthis._y = y;\n\t}\n\n\tset(x, y) {\n\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.set');\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t}\n}\n\n//make a class for the mouse data\nclass Mouse extends Point {\n\tconstructor() {\n\t\tsuper(0, 0);\n\t\tthis._down = false;\n\t\tthis._px = 0;\n\t\tthis._py = 0;\n\t}\n\n\tget down() {\n\t\treturn this._down;\n\t}\n\n\tset down(d) {\n\t\tthis._down = d;\n\t}\n\n\tget x() {\n\t\treturn this._x;\n\t}\n\n\tget y() {\n\t\treturn this._y;\n\t}\n\n\tset x(x) {\n\t\tthis._x = x;\n\t}\n\n\tset y(y) {\n\t\tthis._y = y;\n\t}\n\n\tget px() {\n\t\treturn this._px;\n\t}\n\n\tget py() {\n\t\treturn this._py;\n\t}\n\n\tset px(px) {\n\t\tthis._px = px;\n\t}\n\n\tset py(py) {\n\t\tthis._py = py;\n\t}\n\n}\n\n\nclass Atrament {\n\tconstructor(selector, width, height, color) {\n\t\tif (!document) throw new Error('no DOM found');\n\n\t\t//get canvas element\n\t\tif (selector instanceof Node && selector.tagName === 'CANVAS') this.canvas = selector;\n\t\telse if (typeof selector === 'string') this.canvas = document.querySelector(selector);\n\t\telse throw new Error(`can\\'t look for canvas based on \\'${selector}\\'`);\n\t\tif (!this.canvas) throw new Error('canvas not found');\n\n\t\t//set external canvas params\n\t\tthis.canvas.width = width ? width : 500;\n\t\tthis.canvas.height = height ? height : 500;\n\t\tthis.canvas.style.cursor = 'crosshair';\n\n\t\t//create a mouse object\n\t\tthis.mouse = new Mouse();\n\n\t\t//mousemove handler\n\t\tlet mouseMove = e => {\n\t\t\te.preventDefault();\n\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tconst position = e.changedTouches && e.changedTouches[0] || e;\n\t\t\tlet x = position.offsetX;\n\t\t\tlet y = position.offsetY;\n\n\t\t\tif (typeof x === 'undefined') {\n\t\t\t\tx = position.clientX + document.documentElement.scrollLeft - rect.left;\n\t\t\t}\n\t\t\tif (typeof y === 'undefined') {\n\t\t\t\ty = position.clientY + document.documentElement.scrollTop - rect.top;\n\t\t\t}\n\n\t\t\t//draw if we should draw\n\t\t\tif (this.mouse.down) {\n\t\t\t\tthis.draw(x, y);\n\t\t\t\tif (!this._dirty && (x !== this.mouse.x || y !== this.mouse.y)) {\n\t\t\t\t\tthis._dirty = true;\n\t\t\t\t\tthis.fireDirty();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.mouse.x = x;\n\t\t\t\tthis.mouse.y = y;\n\t\t\t}\n\t\t}\n\n\t\t//mousedown handler\n\t\tlet mouseDown = (mousePosition) => {\n\t\t\tmousePosition.preventDefault();\n\t\t\t//update position just in case\n\t\t\tmouseMove(mousePosition);\n\n\t\t\t//if we are filling - fill and return\n\t\t\tif(this._mode === 'fill'){\n\t\t\t\tthis.fill();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//remember it\n\t\t\tthis.mouse.px = this.mouse.x;\n\t\t\tthis.mouse.py = this.mouse.y;\n\t\t\t//begin drawing\n\t\t\tthis.mouse.down = true;\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.moveTo(this.mouse.px, this.mouse.py);\n\t\t}\n\t\tlet mouseUp = (mousePosition) => {\n\t\t\tmousePosition.preventDefault();\n\t\t\tthis.mouse.down = false;\n\t\t\t//stop drawing\n\t\t\tthis.context.closePath();\n\t\t}\n\n\t\t//attach listeners\n\t\tthis.canvas.addEventListener('mousemove', mouseMove);\n\t\tthis.canvas.addEventListener('mousedown', mouseDown);\n\t\tdocument.addEventListener('mouseup', mouseUp);\n\t\tthis.canvas.addEventListener('touchstart', mouseDown);\n\t\tthis.canvas.addEventListener('touchend', mouseUp);\n\t\tthis.canvas.addEventListener('touchmove', mouseMove);\n\n\t\t//helper for destroying Atrament (removing event listeners)\n\t\tthis.destroy = () => {\n\t\t\tthis.clear();\n\t\t\tthis.canvas.removeEventListener('mousemove', mouseMove);\n\t\t\tthis.canvas.removeEventListener('mousedown', mouseDown);\n\t\t\tdocument.removeEventListener('mouseup', mouseUp);\n\t\t\tthis.canvas.removeEventListener('touchstart', mouseDown);\n\t\t\tthis.canvas.removeEventListener('touchend', mouseUp);\n\t\t\tthis.canvas.removeEventListener('touchmove', mouseMove);\n\t\t};\n\n\t\t//set internal canvas params\n\t\tthis.context = this.canvas.getContext('2d');\n\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\tthis.context.globalAlpha = 1;\n\t\tthis.context.strokeStyle = color ? color : 'rgba(0,0,0,1)';\n\t\tthis.context.lineCap = 'round';\n\t\tthis.context.lineJoin = 'round';\n\t\tthis.context.translate(0.5, 0.5);\n\n\t\tthis._filling = false;\n\t\tthis._fillStack = [];\n\n\t\t//set drawing params\n\t\tthis.SMOOTHING_INIT = 0.85;\n\t\tthis.WEIGHT_SPREAD = 10;\n\t\tthis._smoothing = this.SMOOTHING_INIT;\n\t\tthis._maxWeight = 12;\n\t\tthis._thickness = 2;\n\t\tthis._targetThickness = 2;\n\t\tthis._weight = 2;\n\t\tthis._mode = 'draw';\n\t}\n\n\tstatic lineDistance(x1, y1, x2, y2) {\n\t\t//calculate euclidean distance between (x1, y1) and (x2, y2)\n\t let xs = Math.pow(x2 - x1, 2);\n\t\tlet ys = Math.pow(y2 - y1, 2);\n\t return Math.sqrt( xs + ys );\n\t}\n\n\tstatic hexToRgb(hexColor){\n\t\t//Since input type color provides hex and ImageData accepts RGB need to transform\n\t\tlet m = hexColor.match(/^#?([\\da-f]{2})([\\da-f]{2})([\\da-f]{2})$/i);\n\t\treturn [\n\t\t\tparseInt(m[1], 16),\n\t\t\tparseInt(m[2], 16),\n\t\t\tparseInt(m[3], 16)\n\t\t];\n\t}\n\n\tstatic matchColor(data, compR, compG, compB, compA) {\n\t\treturn (pixelPos)=>{\n\t\t\t//Pixel color equals comp color?\n\t\t\tlet r = data[pixelPos],\n\t\t\t\tg = data[pixelPos+1],\n\t\t\t\tb = data[pixelPos+2],\n\t\t\t\ta = data[pixelPos+3];\n\n\t\t\treturn (r === compR && g === compG && b === compB && a === compA);\n\t\t}\n\t}\n\n\tstatic colorPixel(data, fillR, fillG, fillB, startColor, alpha) {\n\t\tlet matchColor = Atrament.matchColor(data, ...startColor);\n\n\t\treturn (pixelPos)=>{\n\t\t\t//Update fill color in matrix\n\t\t\tdata[pixelPos] = fillR;\n\t\t\tdata[pixelPos+1] = fillG;\n\t\t\tdata[pixelPos+2] = fillB;\n\t\t\tdata[pixelPos+3] = alpha;\n\n\t\t\tif (!matchColor(pixelPos + 4)) {\n\t\t\t\tdata[pixelPos+4] = data[pixelPos+4] * 0.01 + fillR*0.99;\n\t\t\t\tdata[pixelPos+4+1] = data[pixelPos+4+1] * 0.01 + fillG*0.99;\n\t\t\t\tdata[pixelPos+4+2] = data[pixelPos+4+2] * 0.01 + fillB*0.99;\n\t\t\t\tdata[pixelPos+4+3] = data[pixelPos+4+3] * 0.01 + alpha*0.99;\n\t\t\t}\n\n\t\t\tif (!matchColor(pixelPos - 4)) {\n\t\t\t\tdata[pixelPos-4] = data[pixelPos-4] * 0.01 + fillR*0.99;\n\t\t\t\tdata[pixelPos-4+1] = data[pixelPos-4+1] * 0.01 + fillG*0.99;\n\t\t\t\tdata[pixelPos-4+2] = data[pixelPos-4+2] * 0.01 + fillB*0.99;\n\t\t\t\tdata[pixelPos-4+3] = data[pixelPos-4+3] * 0.01 + alpha*0.99;\n\t\t\t}\n\t\t}\n\n\t}\n\n\tdraw(mX, mY) {\n\t\tlet mouse = this.mouse;\n\t\tlet context = this.context;\n\n\t\t//calculate distance from previous point\n\t\tlet raw_dist = Atrament.lineDistance(mX, mY, mouse.px, mouse.py)\n\n\t\t//now, here we scale the initial smoothing factor by the raw distance\n\t\t//this means that when the mouse moves fast, there is more smoothing\n\t\t//and when we're drawing small detailed stuff, we have more control\n\t\t//also we hard clip at 1\n\t\tlet smoothingFactor = Math.min(0.87, this._smoothing + (raw_dist - 60) / 3000);\n\n\t\t//calculate smoothed coordinates\n\t\tmouse.x = mX - (mX - mouse.px) * smoothingFactor;\n\t\tmouse.y = mY - (mY - mouse.py) * smoothingFactor;\n\n\t\t//recalculate distance from previous point, this time relative to the smoothed coords\n\t\tlet dist = Atrament.lineDistance(mouse.x, mouse.y, mouse.px, mouse.py)\n\n\t\t//calculate target thickness based on the new distance\n\t\tthis._targetThickness = (dist - 1) / (50 - 1) * (this._maxWeight - this._weight) + this._weight;\n\t\t//approach the target gradually\n\t\tif (this._thickness > this._targetThickness) {\n\t\t\tthis._thickness -= 0.5;\n\t\t}\n\t\telse if (this._thickness < this._targetThickness) {\n\t\t\tthis._thickness += 0.5;\n\t\t}\n\t\t//set line width\n\t\tcontext.lineWidth = this._thickness;\n\n\t\t//draw using quad interpolation\n\t\tcontext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);\n\t\tcontext.stroke();\n\n\t\t//remember\n\t\tmouse.px = mouse.x;\n\t\tmouse.py = mouse.y;\n\t}\n\n\tget color() {\n\t\treturn this.context.strokeStyle;\n\t}\n\n\tset color(c) {\n\t\tif (typeof c !== 'string') throw new Error('wrong argument type');\n\t\tthis.context.strokeStyle = c;\n\t}\n\n\tget weight() {\n\t\treturn this._weight;\n\t}\n\n\tset weight(w) {\n\t\tif (typeof w !== 'number') throw new Error('wrong argument type');\n\t\tthis._weight = w;\n\t\tthis._thickness = w;\n\t\tthis._targetThickness = w;\n\t\tthis._maxWeight = w + this.WEIGHT_SPREAD;\n\t}\n\n\tget mode() {\n\t\treturn this._mode;\n\t}\n\n\tget dirty() {\n\t\treturn !!this._dirty;\n\t}\n\n\tset mode(m) {\n\t\tif (typeof m !== 'string') throw new Error('wrong argument type');\n\t\tswitch (m) {\n\t\t\tcase 'erase':\n\t\t\t\tthis._mode = 'erase';\n\t\t\t\tthis.context.globalCompositeOperation = 'destination-out';\n\t\t\t\tbreak;\n\t\t\tcase 'fill':\n\t\t\t\tthis._mode = 'fill';\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis._mode = 'draw';\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tget smoothing() {\n\t\treturn this._smoothing === this.SMOOTHING_INIT;\n\t}\n\n\tset smoothing(s) {\n\t\tif (typeof s !== 'boolean') throw new Error('wrong argument type');\n\t\tthis._smoothing = s ? this.SMOOTHING_INIT : 0;\n\t}\n\n\tset opacity(o) {\n\t\tif (typeof o !== 'number') throw new Error('wrong argument type');\n\t\t//now, we need to scale this, because our drawing method means we don't just get uniform transparency all over the drawn line.\n\t\t//so we scale it down a lot, meaning that it'll look nicely semi-transparent\n\t\t//unless opacity is 1, then we should go full on to 1\n\t\tif (o >= 1) this.context.globalAlpha = 1;\n\t\telse this.context.globalAlpha = o/10;\n\t}\n\n\tfireDirty() {\n\t\tconst event = document.createEvent('Event');\n\t\tevent.initEvent('dirty', true, true);\n\t\tthis.canvas.dispatchEvent(event);\n\t}\n\n\tclear() {\n\t\tif (!this.dirty) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._dirty = false;\n\t\tthis.fireDirty();\n\n\t\t//make sure we're in the right compositing mode, and erase everything\n\t\tif (this.context.globalCompositeOperation === 'destination-out') {\n\t\t\tthis.mode = 'draw';\n\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\tthis.mode = 'erase';\n\t\t}\n\t\telse {\n\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t}\n\t}\n\n\ttoImage() {\n\t\treturn this.canvas.toDataURL();\n\t}\n\n\tfill(){\n\t\tlet mouse = this.mouse;\n\t\tlet context = this.context;\n\t\tlet startColor = Array.prototype.slice.call(context.getImageData(mouse.x, mouse.y, 1, 1).data,0); //converting to Array because Safari 9\n\n\t\tif (!this._filling) {\n\t\t\tthis.canvas.style.cursor = 'progress';\n\t\t\tthis._filling = true;\n\n\t\t\tsetTimeout(() => { this._floodFill(mouse.x, mouse.y, startColor); }, 100);\n\t\t}\n\t\telse {\n\t\t\tthis._fillStack.push([\n\t\t\t\tmouse.x,\n\t\t\t\tmouse.y,\n\t\t\t\tstartColor\n\t\t\t]);\n\t\t}\n\t}\n\n\t_floodFill(startX, startY, startColor){\n\t\tlet context = this.context,\n\t\t\tcanvasWidth = context.canvas.width,\n\t\t\tcanvasHeight = context.canvas.height,\n\t\t\tpixelStack = [[startX, startY]],\n\t\t\t//hex needs to be trasformed to rgb since colorLayer accepts RGB\n\t\t\tfillColor = Atrament.hexToRgb(this.color),\n\t\t\t//Need to save current context with colors, we will update it\n\t\t\tcolorLayer = context.getImageData(0, 0, context.canvas.width, context.canvas.height),\n\t\t\talpha = Math.min(context.globalAlpha * 10 * 255, 255),\n\t\t\tcolorPixel = Atrament.colorPixel(colorLayer.data, ...fillColor, startColor, alpha),\n\t\t\tmatchColor = Atrament.matchColor(colorLayer.data, ...startColor);\n\n\t\tconst matchFillColor = Atrament.matchColor(colorLayer.data, ...[...fillColor, 255]);\n\t\t// check if we're trying to fill with the same colour, if so, stop\n\t\tif (matchFillColor((startY*context.canvas.width + startX) * 4)) {\n\t\t\tthis._filling = false;\n\t\t\tsetTimeout(() => { this.canvas.style.cursor = 'crosshair'; }, 100);\n\t\t\treturn;\n\t\t}\n\n\t\twhile(pixelStack.length) {\n\t\t\tlet newPos = pixelStack.pop();\n\t\t\tlet [x,y] = newPos;\n\n\t\t\tlet pixelPos = (y*canvasWidth + x) * 4;\n\n\t\t\twhile(y-- >= 0 && matchColor(pixelPos))\n\t\t\t{\n\t\t\t\tpixelPos -= canvasWidth * 4;\n\t\t\t}\n\t\t\tpixelPos += canvasWidth * 4;\n\n\t\t\t++y;\n\n\t\t\tlet reachLeft = false;\n\t\t\tlet reachRight = false;\n\n\t\t\twhile(y++ < canvasHeight-1 && matchColor(pixelPos))\n\t\t\t{\n\t\t\t\tcolorPixel(pixelPos);\n\n\t\t\t\tif(x > 0)\n\t\t\t\t{\n\t\t\t\t\tif(matchColor(pixelPos - 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!reachLeft){\n\t\t\t\t\t\t\tpixelStack.push([x - 1, y]);\n\t\t\t\t\t\t\treachLeft = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(reachLeft)\n\t\t\t\t\t{\n\t\t\t\t\t\treachLeft = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(x < canvasWidth-1)\n\t\t\t\t{\n\t\t\t\t\tif(matchColor(pixelPos + 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!reachRight)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpixelStack.push([x + 1, y]);\n\t\t\t\t\t\t\treachRight = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(reachRight)\n\t\t\t\t\t{\n\t\t\t\t\t\treachRight = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpixelPos += canvasWidth * 4;\n\t\t\t}\n\t\t}\n\n\t\t//Update context with filled bucket!\n\t\tcontext.putImageData(colorLayer, 0, 0);\n\n\t\tif (this._fillStack.length) {\n\t\t\tthis._floodFill(...this._fillStack.shift());\n\t\t}\n\t\telse {\n\t\t\tthis._filling = false;\n\t\t\tsetTimeout(() => { this.canvas.style.cursor = 'crosshair'; }, 100);\n\t\t}\n\n\t}\n\n}\n\n//for people who like functional programming\nfunction atrament(selector, width, height, color) {\n\treturn new Atrament(selector, width, height, color);\n}\n\nmodule.exports = atrament;\nmodule.exports.Atrament = Atrament;\n\n\n\n// WEBPACK FOOTER //\n// ./src/atrament.js"],"sourceRoot":""} \ No newline at end of file diff --git a/src/atrament.js b/src/atrament.js index e7d99d1..0a4acdb 100755 --- a/src/atrament.js +++ b/src/atrament.js @@ -179,7 +179,7 @@ class Atrament { this.context = this.canvas.getContext('2d'); this.context.globalCompositeOperation = 'source-over'; this.context.globalAlpha = 1; - this.context.strokeStyle = color ? color : 'black'; + this.context.strokeStyle = color ? color : 'rgba(0,0,0,1)'; this.context.lineCap = 'round'; this.context.lineJoin = 'round'; this.context.translate(0.5, 0.5); @@ -222,6 +222,7 @@ class Atrament { g = data[pixelPos+1], b = data[pixelPos+2], a = data[pixelPos+3]; + return (r === compR && g === compG && b === compB && a === compA); } } @@ -421,6 +422,13 @@ class Atrament { colorPixel = Atrament.colorPixel(colorLayer.data, ...fillColor, startColor, alpha), matchColor = Atrament.matchColor(colorLayer.data, ...startColor); + const matchFillColor = Atrament.matchColor(colorLayer.data, ...[...fillColor, 255]); + // check if we're trying to fill with the same colour, if so, stop + if (matchFillColor((startY*context.canvas.width + startX) * 4)) { + this._filling = false; + setTimeout(() => { this.canvas.style.cursor = 'crosshair'; }, 100); + return; + } while(pixelStack.length) { let newPos = pixelStack.pop(); From 6c05006629fd516b8eeb57a9f7dfd4d22c5d804b Mon Sep 17 00:00:00 2001 From: jakubfiala Date: Sun, 25 Dec 2016 18:22:24 +0100 Subject: [PATCH 3/3] probably fixed issue where UI stopped being interactive when atrament was initialized by not preventing default behaviour on mouseup --- dist/atrament.min.js | 2 +- dist/atrament.min.js.map | 2 +- src/atrament.js | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/dist/atrament.min.js b/dist/atrament.min.js index ed68324..4220326 100644 --- a/dist/atrament.min.js +++ b/dist/atrament.min.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.atrament=e():t.atrament=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return t[o].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){t.exports=n(1)},function(t,e,n){"use strict";t.exports=n(2)},function(t,e){"use strict";function n(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);ethis._targetThickness?this._thickness-=.5:this._thickness=0&&d(w);)w-=4*c;w+=4*c,++x;for(var k=!1,b=!1;x++0&&(d(w-4)?k||(u.push([_-1,x]),k=!0):k&&(k=!1)),_=1?this.context.globalAlpha=1:this.context.globalAlpha=t/10}}],[{key:"lineDistance",value:function(t,e,n,o){var i=Math.pow(n-t,2),r=Math.pow(o-e,2);return Math.sqrt(i+r)}},{key:"hexToRgb",value:function(t){var e=t.match(/^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{key:"matchColor",value:function(t,e,n,o,i){return function(r){var s=t[r],a=t[r+1],c=t[r+2],h=t[r+3];return s===e&&a===n&&c===o&&h===i}}},{key:"colorPixel",value:function(e,o,i,r,s,a){var c=t.matchColor.apply(t,[e].concat(n(s)));return function(t){e[t]=o,e[t+1]=i,e[t+2]=r,e[t+3]=a,c(t+4)||(e[t+4]=.01*e[t+4]+.99*o,e[t+4+1]=.01*e[t+4+1]+.99*i,e[t+4+2]=.01*e[t+4+2]+.99*r,e[t+4+3]=.01*e[t+4+3]+.99*a),c(t-4)||(e[t-4]=.01*e[t-4]+.99*o,e[t-4+1]=.01*e[t-4+1]+.99*i,e[t-4+2]=.01*e[t-4+2]+.99*r,e[t-4+3]=.01*e[t-4+3]+.99*a)}}}]),t}();t.exports=s,t.exports.Atrament=f}])}); +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.atrament=e():t.atrament=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return t[o].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){t.exports=n(1)},function(t,e,n){"use strict";t.exports=n(2)},function(t,e){"use strict";function n(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);ethis._targetThickness?this._thickness-=.5:this._thickness=0&&d(w);)w-=4*c;w+=4*c,++x;for(var k=!1,b=!1;x++0&&(d(w-4)?k||(u.push([_-1,x]),k=!0):k&&(k=!1)),_=1?this.context.globalAlpha=1:this.context.globalAlpha=t/10}}],[{key:"lineDistance",value:function(t,e,n,o){var i=Math.pow(n-t,2),r=Math.pow(o-e,2);return Math.sqrt(i+r)}},{key:"hexToRgb",value:function(t){var e=t.match(/^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{key:"matchColor",value:function(t,e,n,o,i){return function(r){var s=t[r],a=t[r+1],c=t[r+2],h=t[r+3];return s===e&&a===n&&c===o&&h===i}}},{key:"colorPixel",value:function(e,o,i,r,s,a){var c=t.matchColor.apply(t,[e].concat(n(s)));return function(t){e[t]=o,e[t+1]=i,e[t+2]=r,e[t+3]=a,c(t+4)||(e[t+4]=.01*e[t+4]+.99*o,e[t+4+1]=.01*e[t+4+1]+.99*i,e[t+4+2]=.01*e[t+4+2]+.99*r,e[t+4+3]=.01*e[t+4+3]+.99*a),c(t-4)||(e[t-4]=.01*e[t-4]+.99*o,e[t-4+1]=.01*e[t-4+1]+.99*i,e[t-4+2]=.01*e[t-4+2]+.99*r,e[t-4+3]=.01*e[t-4+3]+.99*a)}}}]),t}();t.exports=s,t.exports.Atrament=f}])}); //# sourceMappingURL=atrament.min.js.map \ No newline at end of file diff --git a/dist/atrament.min.js.map b/dist/atrament.min.js.map index ee1e21b..2a27e1b 100644 --- a/dist/atrament.min.js.map +++ b/dist/atrament.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///atrament.min.js","webpack:///webpack/bootstrap 56eadc523feeb4c79eb1","webpack:///./index.js","webpack:///./src/atrament.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","_toConsumableArray","arr","Array","isArray","i","arr2","length","from","_possibleConstructorReturn","self","ReferenceError","_inherits","subClass","superClass","TypeError","prototype","Object","create","constructor","value","enumerable","writable","configurable","setPrototypeOf","__proto__","_classCallCheck","instance","Constructor","atrament","selector","width","height","color","Atrament","_slicedToArray","sliceIterator","_arr","_n","_d","_e","undefined","_s","_i","Symbol","iterator","next","done","push","err","_createClass","defineProperties","target","props","descriptor","defineProperty","key","protoProps","staticProps","Point","x","y","arguments","Error","_x","_y","get","set","Mouse","_Point","_this","getPrototypeOf","_down","_px","_py","d","px","py","_this2","document","Node","tagName","canvas","querySelector","style","cursor","mouse","mouseMove","e","preventDefault","rect","getBoundingClientRect","position","changedTouches","offsetX","offsetY","clientX","documentElement","scrollLeft","left","clientY","scrollTop","top","down","draw","_dirty","fireDirty","mouseDown","mousePosition","_mode","fill","context","beginPath","moveTo","mouseUp","closePath","addEventListener","destroy","clear","removeEventListener","getContext","globalCompositeOperation","globalAlpha","strokeStyle","lineCap","lineJoin","translate","_filling","_fillStack","SMOOTHING_INIT","WEIGHT_SPREAD","_smoothing","_maxWeight","_thickness","_targetThickness","_weight","mX","mY","raw_dist","lineDistance","smoothingFactor","Math","min","dist","lineWidth","quadraticCurveTo","stroke","event","createEvent","initEvent","dispatchEvent","dirty","mode","clearRect","toDataURL","_this3","startColor","slice","getImageData","data","setTimeout","_floodFill","startX","startY","_this4","canvasWidth","canvasHeight","pixelStack","fillColor","hexToRgb","colorLayer","alpha","colorPixel","apply","concat","matchColor","matchFillColor","newPos","pop","_newPos","pixelPos","reachLeft","reachRight","putImageData","shift","w","s","o","x1","y1","x2","y2","xs","pow","ys","sqrt","hexColor","match","parseInt","compR","compG","compB","compA","r","g","b","a","fillR","fillG","fillB"],"mappings":"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","file":"atrament.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"atrament\"] = factory();\n\telse\n\t\troot[\"atrament\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"atrament\"] = factory();\n\telse\n\t\troot[\"atrament\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(1);\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tmodule.exports = __webpack_require__(2);\n\n/***/ },\n/* 2 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\tvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\t\n\tvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\t\n\tfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\t\n\tfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\t\n\tfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\t\n\tfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\t\n\t//make a class for Point\n\tvar Point = function () {\n\t\tfunction Point(x, y) {\n\t\t\t_classCallCheck(this, Point);\n\t\n\t\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.');\n\t\t\tthis._x = x;\n\t\t\tthis._y = y;\n\t\t}\n\t\n\t\t_createClass(Point, [{\n\t\t\tkey: 'set',\n\t\t\tvalue: function set(x, y) {\n\t\t\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.set');\n\t\t\t\tthis._x = x;\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'x',\n\t\t\tget: function get() {\n\t\t\t\treturn this._x;\n\t\t\t},\n\t\t\tset: function set(x) {\n\t\t\t\tthis._x = x;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'y',\n\t\t\tget: function get() {\n\t\t\t\treturn this._y;\n\t\t\t},\n\t\t\tset: function set(y) {\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Point;\n\t}();\n\t\n\t//make a class for the mouse data\n\t\n\t\n\tvar Mouse = function (_Point) {\n\t\t_inherits(Mouse, _Point);\n\t\n\t\tfunction Mouse() {\n\t\t\t_classCallCheck(this, Mouse);\n\t\n\t\t\tvar _this = _possibleConstructorReturn(this, (Mouse.__proto__ || Object.getPrototypeOf(Mouse)).call(this, 0, 0));\n\t\n\t\t\t_this._down = false;\n\t\t\t_this._px = 0;\n\t\t\t_this._py = 0;\n\t\t\treturn _this;\n\t\t}\n\t\n\t\t_createClass(Mouse, [{\n\t\t\tkey: 'down',\n\t\t\tget: function get() {\n\t\t\t\treturn this._down;\n\t\t\t},\n\t\t\tset: function set(d) {\n\t\t\t\tthis._down = d;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'x',\n\t\t\tget: function get() {\n\t\t\t\treturn this._x;\n\t\t\t},\n\t\t\tset: function set(x) {\n\t\t\t\tthis._x = x;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'y',\n\t\t\tget: function get() {\n\t\t\t\treturn this._y;\n\t\t\t},\n\t\t\tset: function set(y) {\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'px',\n\t\t\tget: function get() {\n\t\t\t\treturn this._px;\n\t\t\t},\n\t\t\tset: function set(px) {\n\t\t\t\tthis._px = px;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'py',\n\t\t\tget: function get() {\n\t\t\t\treturn this._py;\n\t\t\t},\n\t\t\tset: function set(py) {\n\t\t\t\tthis._py = py;\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Mouse;\n\t}(Point);\n\t\n\tvar Atrament = function () {\n\t\tfunction Atrament(selector, width, height, color) {\n\t\t\tvar _this2 = this;\n\t\n\t\t\t_classCallCheck(this, Atrament);\n\t\n\t\t\tif (!document) throw new Error('no DOM found');\n\t\n\t\t\t//get canvas element\n\t\t\tif (selector instanceof Node && selector.tagName === 'CANVAS') this.canvas = selector;else if (typeof selector === 'string') this.canvas = document.querySelector(selector);else throw new Error('can\\'t look for canvas based on \\'' + selector + '\\'');\n\t\t\tif (!this.canvas) throw new Error('canvas not found');\n\t\n\t\t\t//set external canvas params\n\t\t\tthis.canvas.width = width ? width : 500;\n\t\t\tthis.canvas.height = height ? height : 500;\n\t\t\tthis.canvas.style.cursor = 'crosshair';\n\t\n\t\t\t//create a mouse object\n\t\t\tthis.mouse = new Mouse();\n\t\n\t\t\t//mousemove handler\n\t\t\tvar mouseMove = function mouseMove(e) {\n\t\t\t\te.preventDefault();\n\t\n\t\t\t\tvar rect = _this2.canvas.getBoundingClientRect();\n\t\t\t\tvar position = e.changedTouches && e.changedTouches[0] || e;\n\t\t\t\tvar x = position.offsetX;\n\t\t\t\tvar y = position.offsetY;\n\t\n\t\t\t\tif (typeof x === 'undefined') {\n\t\t\t\t\tx = position.clientX + document.documentElement.scrollLeft - rect.left;\n\t\t\t\t}\n\t\t\t\tif (typeof y === 'undefined') {\n\t\t\t\t\ty = position.clientY + document.documentElement.scrollTop - rect.top;\n\t\t\t\t}\n\t\n\t\t\t\t//draw if we should draw\n\t\t\t\tif (_this2.mouse.down) {\n\t\t\t\t\t_this2.draw(x, y);\n\t\t\t\t\tif (!_this2._dirty && (x !== _this2.mouse.x || y !== _this2.mouse.y)) {\n\t\t\t\t\t\t_this2._dirty = true;\n\t\t\t\t\t\t_this2.fireDirty();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t_this2.mouse.x = x;\n\t\t\t\t\t_this2.mouse.y = y;\n\t\t\t\t}\n\t\t\t};\n\t\n\t\t\t//mousedown handler\n\t\t\tvar mouseDown = function mouseDown(mousePosition) {\n\t\t\t\tmousePosition.preventDefault();\n\t\t\t\t//update position just in case\n\t\t\t\tmouseMove(mousePosition);\n\t\n\t\t\t\t//if we are filling - fill and return\n\t\t\t\tif (_this2._mode === 'fill') {\n\t\t\t\t\t_this2.fill();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\t//remember it\n\t\t\t\t_this2.mouse.px = _this2.mouse.x;\n\t\t\t\t_this2.mouse.py = _this2.mouse.y;\n\t\t\t\t//begin drawing\n\t\t\t\t_this2.mouse.down = true;\n\t\t\t\t_this2.context.beginPath();\n\t\t\t\t_this2.context.moveTo(_this2.mouse.px, _this2.mouse.py);\n\t\t\t};\n\t\t\tvar mouseUp = function mouseUp(mousePosition) {\n\t\t\t\tmousePosition.preventDefault();\n\t\t\t\t_this2.mouse.down = false;\n\t\t\t\t//stop drawing\n\t\t\t\t_this2.context.closePath();\n\t\t\t};\n\t\n\t\t\t//attach listeners\n\t\t\tthis.canvas.addEventListener('mousemove', mouseMove);\n\t\t\tthis.canvas.addEventListener('mousedown', mouseDown);\n\t\t\tdocument.addEventListener('mouseup', mouseUp);\n\t\t\tthis.canvas.addEventListener('touchstart', mouseDown);\n\t\t\tthis.canvas.addEventListener('touchend', mouseUp);\n\t\t\tthis.canvas.addEventListener('touchmove', mouseMove);\n\t\n\t\t\t//helper for destroying Atrament (removing event listeners)\n\t\t\tthis.destroy = function () {\n\t\t\t\t_this2.clear();\n\t\t\t\t_this2.canvas.removeEventListener('mousemove', mouseMove);\n\t\t\t\t_this2.canvas.removeEventListener('mousedown', mouseDown);\n\t\t\t\tdocument.removeEventListener('mouseup', mouseUp);\n\t\t\t\t_this2.canvas.removeEventListener('touchstart', mouseDown);\n\t\t\t\t_this2.canvas.removeEventListener('touchend', mouseUp);\n\t\t\t\t_this2.canvas.removeEventListener('touchmove', mouseMove);\n\t\t\t};\n\t\n\t\t\t//set internal canvas params\n\t\t\tthis.context = this.canvas.getContext('2d');\n\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\tthis.context.globalAlpha = 1;\n\t\t\tthis.context.strokeStyle = color ? color : 'rgba(0,0,0,1)';\n\t\t\tthis.context.lineCap = 'round';\n\t\t\tthis.context.lineJoin = 'round';\n\t\t\tthis.context.translate(0.5, 0.5);\n\t\n\t\t\tthis._filling = false;\n\t\t\tthis._fillStack = [];\n\t\n\t\t\t//set drawing params\n\t\t\tthis.SMOOTHING_INIT = 0.85;\n\t\t\tthis.WEIGHT_SPREAD = 10;\n\t\t\tthis._smoothing = this.SMOOTHING_INIT;\n\t\t\tthis._maxWeight = 12;\n\t\t\tthis._thickness = 2;\n\t\t\tthis._targetThickness = 2;\n\t\t\tthis._weight = 2;\n\t\t\tthis._mode = 'draw';\n\t\t}\n\t\n\t\t_createClass(Atrament, [{\n\t\t\tkey: 'draw',\n\t\t\tvalue: function draw(mX, mY) {\n\t\t\t\tvar mouse = this.mouse;\n\t\t\t\tvar context = this.context;\n\t\n\t\t\t\t//calculate distance from previous point\n\t\t\t\tvar raw_dist = Atrament.lineDistance(mX, mY, mouse.px, mouse.py);\n\t\n\t\t\t\t//now, here we scale the initial smoothing factor by the raw distance\n\t\t\t\t//this means that when the mouse moves fast, there is more smoothing\n\t\t\t\t//and when we're drawing small detailed stuff, we have more control\n\t\t\t\t//also we hard clip at 1\n\t\t\t\tvar smoothingFactor = Math.min(0.87, this._smoothing + (raw_dist - 60) / 3000);\n\t\n\t\t\t\t//calculate smoothed coordinates\n\t\t\t\tmouse.x = mX - (mX - mouse.px) * smoothingFactor;\n\t\t\t\tmouse.y = mY - (mY - mouse.py) * smoothingFactor;\n\t\n\t\t\t\t//recalculate distance from previous point, this time relative to the smoothed coords\n\t\t\t\tvar dist = Atrament.lineDistance(mouse.x, mouse.y, mouse.px, mouse.py);\n\t\n\t\t\t\t//calculate target thickness based on the new distance\n\t\t\t\tthis._targetThickness = (dist - 1) / (50 - 1) * (this._maxWeight - this._weight) + this._weight;\n\t\t\t\t//approach the target gradually\n\t\t\t\tif (this._thickness > this._targetThickness) {\n\t\t\t\t\tthis._thickness -= 0.5;\n\t\t\t\t} else if (this._thickness < this._targetThickness) {\n\t\t\t\t\tthis._thickness += 0.5;\n\t\t\t\t}\n\t\t\t\t//set line width\n\t\t\t\tcontext.lineWidth = this._thickness;\n\t\n\t\t\t\t//draw using quad interpolation\n\t\t\t\tcontext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);\n\t\t\t\tcontext.stroke();\n\t\n\t\t\t\t//remember\n\t\t\t\tmouse.px = mouse.x;\n\t\t\t\tmouse.py = mouse.y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'fireDirty',\n\t\t\tvalue: function fireDirty() {\n\t\t\t\tvar event = document.createEvent('Event');\n\t\t\t\tevent.initEvent('dirty', true, true);\n\t\t\t\tthis.canvas.dispatchEvent(event);\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'clear',\n\t\t\tvalue: function clear() {\n\t\t\t\tif (!this.dirty) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\tthis._dirty = false;\n\t\t\t\tthis.fireDirty();\n\t\n\t\t\t\t//make sure we're in the right compositing mode, and erase everything\n\t\t\t\tif (this.context.globalCompositeOperation === 'destination-out') {\n\t\t\t\t\tthis.mode = 'draw';\n\t\t\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\t\t\tthis.mode = 'erase';\n\t\t\t\t} else {\n\t\t\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'toImage',\n\t\t\tvalue: function toImage() {\n\t\t\t\treturn this.canvas.toDataURL();\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'fill',\n\t\t\tvalue: function fill() {\n\t\t\t\tvar _this3 = this;\n\t\n\t\t\t\tvar mouse = this.mouse;\n\t\t\t\tvar context = this.context;\n\t\t\t\tvar startColor = Array.prototype.slice.call(context.getImageData(mouse.x, mouse.y, 1, 1).data, 0); //converting to Array because Safari 9\n\t\n\t\t\t\tif (!this._filling) {\n\t\t\t\t\tthis.canvas.style.cursor = 'progress';\n\t\t\t\t\tthis._filling = true;\n\t\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this3._floodFill(mouse.x, mouse.y, startColor);\n\t\t\t\t\t}, 100);\n\t\t\t\t} else {\n\t\t\t\t\tthis._fillStack.push([mouse.x, mouse.y, startColor]);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: '_floodFill',\n\t\t\tvalue: function _floodFill(startX, startY, startColor) {\n\t\t\t\tvar _this4 = this;\n\t\n\t\t\t\tvar context = this.context,\n\t\t\t\t canvasWidth = context.canvas.width,\n\t\t\t\t canvasHeight = context.canvas.height,\n\t\t\t\t pixelStack = [[startX, startY]],\n\t\n\t\t\t\t//hex needs to be trasformed to rgb since colorLayer accepts RGB\n\t\t\t\tfillColor = Atrament.hexToRgb(this.color),\n\t\n\t\t\t\t//Need to save current context with colors, we will update it\n\t\t\t\tcolorLayer = context.getImageData(0, 0, context.canvas.width, context.canvas.height),\n\t\t\t\t alpha = Math.min(context.globalAlpha * 10 * 255, 255),\n\t\t\t\t colorPixel = Atrament.colorPixel.apply(Atrament, [colorLayer.data].concat(_toConsumableArray(fillColor), [startColor, alpha])),\n\t\t\t\t matchColor = Atrament.matchColor.apply(Atrament, [colorLayer.data].concat(_toConsumableArray(startColor)));\n\t\n\t\t\t\tvar matchFillColor = Atrament.matchColor.apply(Atrament, [colorLayer.data].concat([].concat(_toConsumableArray(fillColor), [255])));\n\t\t\t\t// check if we're trying to fill with the same colour, if so, stop\n\t\t\t\tif (matchFillColor((startY * context.canvas.width + startX) * 4)) {\n\t\t\t\t\tthis._filling = false;\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this4.canvas.style.cursor = 'crosshair';\n\t\t\t\t\t}, 100);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\twhile (pixelStack.length) {\n\t\t\t\t\tvar newPos = pixelStack.pop();\n\t\n\t\t\t\t\tvar _newPos = _slicedToArray(newPos, 2),\n\t\t\t\t\t x = _newPos[0],\n\t\t\t\t\t y = _newPos[1];\n\t\n\t\t\t\t\tvar pixelPos = (y * canvasWidth + x) * 4;\n\t\n\t\t\t\t\twhile (y-- >= 0 && matchColor(pixelPos)) {\n\t\t\t\t\t\tpixelPos -= canvasWidth * 4;\n\t\t\t\t\t}\n\t\t\t\t\tpixelPos += canvasWidth * 4;\n\t\n\t\t\t\t\t++y;\n\t\n\t\t\t\t\tvar reachLeft = false;\n\t\t\t\t\tvar reachRight = false;\n\t\n\t\t\t\t\twhile (y++ < canvasHeight - 1 && matchColor(pixelPos)) {\n\t\t\t\t\t\tcolorPixel(pixelPos);\n\t\n\t\t\t\t\t\tif (x > 0) {\n\t\t\t\t\t\t\tif (matchColor(pixelPos - 4)) {\n\t\t\t\t\t\t\t\tif (!reachLeft) {\n\t\t\t\t\t\t\t\t\tpixelStack.push([x - 1, y]);\n\t\t\t\t\t\t\t\t\treachLeft = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (reachLeft) {\n\t\t\t\t\t\t\t\treachLeft = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tif (x < canvasWidth - 1) {\n\t\t\t\t\t\t\tif (matchColor(pixelPos + 4)) {\n\t\t\t\t\t\t\t\tif (!reachRight) {\n\t\t\t\t\t\t\t\t\tpixelStack.push([x + 1, y]);\n\t\t\t\t\t\t\t\t\treachRight = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (reachRight) {\n\t\t\t\t\t\t\t\treachRight = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tpixelPos += canvasWidth * 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\n\t\t\t\t//Update context with filled bucket!\n\t\t\t\tcontext.putImageData(colorLayer, 0, 0);\n\t\n\t\t\t\tif (this._fillStack.length) {\n\t\t\t\t\tthis._floodFill.apply(this, _toConsumableArray(this._fillStack.shift()));\n\t\t\t\t} else {\n\t\t\t\t\tthis._filling = false;\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this4.canvas.style.cursor = 'crosshair';\n\t\t\t\t\t}, 100);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'color',\n\t\t\tget: function get() {\n\t\t\t\treturn this.context.strokeStyle;\n\t\t\t},\n\t\t\tset: function set(c) {\n\t\t\t\tif (typeof c !== 'string') throw new Error('wrong argument type');\n\t\t\t\tthis.context.strokeStyle = c;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'weight',\n\t\t\tget: function get() {\n\t\t\t\treturn this._weight;\n\t\t\t},\n\t\t\tset: function set(w) {\n\t\t\t\tif (typeof w !== 'number') throw new Error('wrong argument type');\n\t\t\t\tthis._weight = w;\n\t\t\t\tthis._thickness = w;\n\t\t\t\tthis._targetThickness = w;\n\t\t\t\tthis._maxWeight = w + this.WEIGHT_SPREAD;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'mode',\n\t\t\tget: function get() {\n\t\t\t\treturn this._mode;\n\t\t\t},\n\t\t\tset: function set(m) {\n\t\t\t\tif (typeof m !== 'string') throw new Error('wrong argument type');\n\t\t\t\tswitch (m) {\n\t\t\t\t\tcase 'erase':\n\t\t\t\t\t\tthis._mode = 'erase';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'destination-out';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'fill':\n\t\t\t\t\t\tthis._mode = 'fill';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthis._mode = 'draw';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'dirty',\n\t\t\tget: function get() {\n\t\t\t\treturn !!this._dirty;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'smoothing',\n\t\t\tget: function get() {\n\t\t\t\treturn this._smoothing === this.SMOOTHING_INIT;\n\t\t\t},\n\t\t\tset: function set(s) {\n\t\t\t\tif (typeof s !== 'boolean') throw new Error('wrong argument type');\n\t\t\t\tthis._smoothing = s ? this.SMOOTHING_INIT : 0;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'opacity',\n\t\t\tset: function set(o) {\n\t\t\t\tif (typeof o !== 'number') throw new Error('wrong argument type');\n\t\t\t\t//now, we need to scale this, because our drawing method means we don't just get uniform transparency all over the drawn line.\n\t\t\t\t//so we scale it down a lot, meaning that it'll look nicely semi-transparent\n\t\t\t\t//unless opacity is 1, then we should go full on to 1\n\t\t\t\tif (o >= 1) this.context.globalAlpha = 1;else this.context.globalAlpha = o / 10;\n\t\t\t}\n\t\t}], [{\n\t\t\tkey: 'lineDistance',\n\t\t\tvalue: function lineDistance(x1, y1, x2, y2) {\n\t\t\t\t//calculate euclidean distance between (x1, y1) and (x2, y2)\n\t\t\t\tvar xs = Math.pow(x2 - x1, 2);\n\t\t\t\tvar ys = Math.pow(y2 - y1, 2);\n\t\t\t\treturn Math.sqrt(xs + ys);\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'hexToRgb',\n\t\t\tvalue: function hexToRgb(hexColor) {\n\t\t\t\t//Since input type color provides hex and ImageData accepts RGB need to transform\n\t\t\t\tvar m = hexColor.match(/^#?([\\da-f]{2})([\\da-f]{2})([\\da-f]{2})$/i);\n\t\t\t\treturn [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16)];\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'matchColor',\n\t\t\tvalue: function matchColor(data, compR, compG, compB, compA) {\n\t\t\t\treturn function (pixelPos) {\n\t\t\t\t\t//Pixel color equals comp color?\n\t\t\t\t\tvar r = data[pixelPos],\n\t\t\t\t\t g = data[pixelPos + 1],\n\t\t\t\t\t b = data[pixelPos + 2],\n\t\t\t\t\t a = data[pixelPos + 3];\n\t\n\t\t\t\t\treturn r === compR && g === compG && b === compB && a === compA;\n\t\t\t\t};\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'colorPixel',\n\t\t\tvalue: function colorPixel(data, fillR, fillG, fillB, startColor, alpha) {\n\t\t\t\tvar matchColor = Atrament.matchColor.apply(Atrament, [data].concat(_toConsumableArray(startColor)));\n\t\n\t\t\t\treturn function (pixelPos) {\n\t\t\t\t\t//Update fill color in matrix\n\t\t\t\t\tdata[pixelPos] = fillR;\n\t\t\t\t\tdata[pixelPos + 1] = fillG;\n\t\t\t\t\tdata[pixelPos + 2] = fillB;\n\t\t\t\t\tdata[pixelPos + 3] = alpha;\n\t\n\t\t\t\t\tif (!matchColor(pixelPos + 4)) {\n\t\t\t\t\t\tdata[pixelPos + 4] = data[pixelPos + 4] * 0.01 + fillR * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 1] = data[pixelPos + 4 + 1] * 0.01 + fillG * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 2] = data[pixelPos + 4 + 2] * 0.01 + fillB * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 3] = data[pixelPos + 4 + 3] * 0.01 + alpha * 0.99;\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (!matchColor(pixelPos - 4)) {\n\t\t\t\t\t\tdata[pixelPos - 4] = data[pixelPos - 4] * 0.01 + fillR * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 1] = data[pixelPos - 4 + 1] * 0.01 + fillG * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 2] = data[pixelPos - 4 + 2] * 0.01 + fillB * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 3] = data[pixelPos - 4 + 3] * 0.01 + alpha * 0.99;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Atrament;\n\t}();\n\t\n\t//for people who like functional programming\n\t\n\t\n\tfunction atrament(selector, width, height, color) {\n\t\treturn new Atrament(selector, width, height, color);\n\t}\n\t\n\tmodule.exports = atrament;\n\tmodule.exports.Atrament = Atrament;\n\n/***/ }\n/******/ ])\n});\n;\n\n\n// WEBPACK FOOTER //\n// atrament.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 56eadc523feeb4c79eb1","module.exports = require('./src/atrament.js');\n\n\n// WEBPACK FOOTER //\n// ./index.js","//make a class for Point\nclass Point {\n\tconstructor(x, y) {\n\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.');\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t}\n\n\tget x() {\n\t\treturn this._x;\n\t}\n\n\tget y() {\n\t\treturn this._y;\n\t}\n\n\tset x(x) {\n\t\tthis._x = x;\n\t}\n\n\tset y(y) {\n\t\tthis._y = y;\n\t}\n\n\tset(x, y) {\n\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.set');\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t}\n}\n\n//make a class for the mouse data\nclass Mouse extends Point {\n\tconstructor() {\n\t\tsuper(0, 0);\n\t\tthis._down = false;\n\t\tthis._px = 0;\n\t\tthis._py = 0;\n\t}\n\n\tget down() {\n\t\treturn this._down;\n\t}\n\n\tset down(d) {\n\t\tthis._down = d;\n\t}\n\n\tget x() {\n\t\treturn this._x;\n\t}\n\n\tget y() {\n\t\treturn this._y;\n\t}\n\n\tset x(x) {\n\t\tthis._x = x;\n\t}\n\n\tset y(y) {\n\t\tthis._y = y;\n\t}\n\n\tget px() {\n\t\treturn this._px;\n\t}\n\n\tget py() {\n\t\treturn this._py;\n\t}\n\n\tset px(px) {\n\t\tthis._px = px;\n\t}\n\n\tset py(py) {\n\t\tthis._py = py;\n\t}\n\n}\n\n\nclass Atrament {\n\tconstructor(selector, width, height, color) {\n\t\tif (!document) throw new Error('no DOM found');\n\n\t\t//get canvas element\n\t\tif (selector instanceof Node && selector.tagName === 'CANVAS') this.canvas = selector;\n\t\telse if (typeof selector === 'string') this.canvas = document.querySelector(selector);\n\t\telse throw new Error(`can\\'t look for canvas based on \\'${selector}\\'`);\n\t\tif (!this.canvas) throw new Error('canvas not found');\n\n\t\t//set external canvas params\n\t\tthis.canvas.width = width ? width : 500;\n\t\tthis.canvas.height = height ? height : 500;\n\t\tthis.canvas.style.cursor = 'crosshair';\n\n\t\t//create a mouse object\n\t\tthis.mouse = new Mouse();\n\n\t\t//mousemove handler\n\t\tlet mouseMove = e => {\n\t\t\te.preventDefault();\n\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tconst position = e.changedTouches && e.changedTouches[0] || e;\n\t\t\tlet x = position.offsetX;\n\t\t\tlet y = position.offsetY;\n\n\t\t\tif (typeof x === 'undefined') {\n\t\t\t\tx = position.clientX + document.documentElement.scrollLeft - rect.left;\n\t\t\t}\n\t\t\tif (typeof y === 'undefined') {\n\t\t\t\ty = position.clientY + document.documentElement.scrollTop - rect.top;\n\t\t\t}\n\n\t\t\t//draw if we should draw\n\t\t\tif (this.mouse.down) {\n\t\t\t\tthis.draw(x, y);\n\t\t\t\tif (!this._dirty && (x !== this.mouse.x || y !== this.mouse.y)) {\n\t\t\t\t\tthis._dirty = true;\n\t\t\t\t\tthis.fireDirty();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.mouse.x = x;\n\t\t\t\tthis.mouse.y = y;\n\t\t\t}\n\t\t}\n\n\t\t//mousedown handler\n\t\tlet mouseDown = (mousePosition) => {\n\t\t\tmousePosition.preventDefault();\n\t\t\t//update position just in case\n\t\t\tmouseMove(mousePosition);\n\n\t\t\t//if we are filling - fill and return\n\t\t\tif(this._mode === 'fill'){\n\t\t\t\tthis.fill();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//remember it\n\t\t\tthis.mouse.px = this.mouse.x;\n\t\t\tthis.mouse.py = this.mouse.y;\n\t\t\t//begin drawing\n\t\t\tthis.mouse.down = true;\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.moveTo(this.mouse.px, this.mouse.py);\n\t\t}\n\t\tlet mouseUp = (mousePosition) => {\n\t\t\tmousePosition.preventDefault();\n\t\t\tthis.mouse.down = false;\n\t\t\t//stop drawing\n\t\t\tthis.context.closePath();\n\t\t}\n\n\t\t//attach listeners\n\t\tthis.canvas.addEventListener('mousemove', mouseMove);\n\t\tthis.canvas.addEventListener('mousedown', mouseDown);\n\t\tdocument.addEventListener('mouseup', mouseUp);\n\t\tthis.canvas.addEventListener('touchstart', mouseDown);\n\t\tthis.canvas.addEventListener('touchend', mouseUp);\n\t\tthis.canvas.addEventListener('touchmove', mouseMove);\n\n\t\t//helper for destroying Atrament (removing event listeners)\n\t\tthis.destroy = () => {\n\t\t\tthis.clear();\n\t\t\tthis.canvas.removeEventListener('mousemove', mouseMove);\n\t\t\tthis.canvas.removeEventListener('mousedown', mouseDown);\n\t\t\tdocument.removeEventListener('mouseup', mouseUp);\n\t\t\tthis.canvas.removeEventListener('touchstart', mouseDown);\n\t\t\tthis.canvas.removeEventListener('touchend', mouseUp);\n\t\t\tthis.canvas.removeEventListener('touchmove', mouseMove);\n\t\t};\n\n\t\t//set internal canvas params\n\t\tthis.context = this.canvas.getContext('2d');\n\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\tthis.context.globalAlpha = 1;\n\t\tthis.context.strokeStyle = color ? color : 'rgba(0,0,0,1)';\n\t\tthis.context.lineCap = 'round';\n\t\tthis.context.lineJoin = 'round';\n\t\tthis.context.translate(0.5, 0.5);\n\n\t\tthis._filling = false;\n\t\tthis._fillStack = [];\n\n\t\t//set drawing params\n\t\tthis.SMOOTHING_INIT = 0.85;\n\t\tthis.WEIGHT_SPREAD = 10;\n\t\tthis._smoothing = this.SMOOTHING_INIT;\n\t\tthis._maxWeight = 12;\n\t\tthis._thickness = 2;\n\t\tthis._targetThickness = 2;\n\t\tthis._weight = 2;\n\t\tthis._mode = 'draw';\n\t}\n\n\tstatic lineDistance(x1, y1, x2, y2) {\n\t\t//calculate euclidean distance between (x1, y1) and (x2, y2)\n\t let xs = Math.pow(x2 - x1, 2);\n\t\tlet ys = Math.pow(y2 - y1, 2);\n\t return Math.sqrt( xs + ys );\n\t}\n\n\tstatic hexToRgb(hexColor){\n\t\t//Since input type color provides hex and ImageData accepts RGB need to transform\n\t\tlet m = hexColor.match(/^#?([\\da-f]{2})([\\da-f]{2})([\\da-f]{2})$/i);\n\t\treturn [\n\t\t\tparseInt(m[1], 16),\n\t\t\tparseInt(m[2], 16),\n\t\t\tparseInt(m[3], 16)\n\t\t];\n\t}\n\n\tstatic matchColor(data, compR, compG, compB, compA) {\n\t\treturn (pixelPos)=>{\n\t\t\t//Pixel color equals comp color?\n\t\t\tlet r = data[pixelPos],\n\t\t\t\tg = data[pixelPos+1],\n\t\t\t\tb = data[pixelPos+2],\n\t\t\t\ta = data[pixelPos+3];\n\n\t\t\treturn (r === compR && g === compG && b === compB && a === compA);\n\t\t}\n\t}\n\n\tstatic colorPixel(data, fillR, fillG, fillB, startColor, alpha) {\n\t\tlet matchColor = Atrament.matchColor(data, ...startColor);\n\n\t\treturn (pixelPos)=>{\n\t\t\t//Update fill color in matrix\n\t\t\tdata[pixelPos] = fillR;\n\t\t\tdata[pixelPos+1] = fillG;\n\t\t\tdata[pixelPos+2] = fillB;\n\t\t\tdata[pixelPos+3] = alpha;\n\n\t\t\tif (!matchColor(pixelPos + 4)) {\n\t\t\t\tdata[pixelPos+4] = data[pixelPos+4] * 0.01 + fillR*0.99;\n\t\t\t\tdata[pixelPos+4+1] = data[pixelPos+4+1] * 0.01 + fillG*0.99;\n\t\t\t\tdata[pixelPos+4+2] = data[pixelPos+4+2] * 0.01 + fillB*0.99;\n\t\t\t\tdata[pixelPos+4+3] = data[pixelPos+4+3] * 0.01 + alpha*0.99;\n\t\t\t}\n\n\t\t\tif (!matchColor(pixelPos - 4)) {\n\t\t\t\tdata[pixelPos-4] = data[pixelPos-4] * 0.01 + fillR*0.99;\n\t\t\t\tdata[pixelPos-4+1] = data[pixelPos-4+1] * 0.01 + fillG*0.99;\n\t\t\t\tdata[pixelPos-4+2] = data[pixelPos-4+2] * 0.01 + fillB*0.99;\n\t\t\t\tdata[pixelPos-4+3] = data[pixelPos-4+3] * 0.01 + alpha*0.99;\n\t\t\t}\n\t\t}\n\n\t}\n\n\tdraw(mX, mY) {\n\t\tlet mouse = this.mouse;\n\t\tlet context = this.context;\n\n\t\t//calculate distance from previous point\n\t\tlet raw_dist = Atrament.lineDistance(mX, mY, mouse.px, mouse.py)\n\n\t\t//now, here we scale the initial smoothing factor by the raw distance\n\t\t//this means that when the mouse moves fast, there is more smoothing\n\t\t//and when we're drawing small detailed stuff, we have more control\n\t\t//also we hard clip at 1\n\t\tlet smoothingFactor = Math.min(0.87, this._smoothing + (raw_dist - 60) / 3000);\n\n\t\t//calculate smoothed coordinates\n\t\tmouse.x = mX - (mX - mouse.px) * smoothingFactor;\n\t\tmouse.y = mY - (mY - mouse.py) * smoothingFactor;\n\n\t\t//recalculate distance from previous point, this time relative to the smoothed coords\n\t\tlet dist = Atrament.lineDistance(mouse.x, mouse.y, mouse.px, mouse.py)\n\n\t\t//calculate target thickness based on the new distance\n\t\tthis._targetThickness = (dist - 1) / (50 - 1) * (this._maxWeight - this._weight) + this._weight;\n\t\t//approach the target gradually\n\t\tif (this._thickness > this._targetThickness) {\n\t\t\tthis._thickness -= 0.5;\n\t\t}\n\t\telse if (this._thickness < this._targetThickness) {\n\t\t\tthis._thickness += 0.5;\n\t\t}\n\t\t//set line width\n\t\tcontext.lineWidth = this._thickness;\n\n\t\t//draw using quad interpolation\n\t\tcontext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);\n\t\tcontext.stroke();\n\n\t\t//remember\n\t\tmouse.px = mouse.x;\n\t\tmouse.py = mouse.y;\n\t}\n\n\tget color() {\n\t\treturn this.context.strokeStyle;\n\t}\n\n\tset color(c) {\n\t\tif (typeof c !== 'string') throw new Error('wrong argument type');\n\t\tthis.context.strokeStyle = c;\n\t}\n\n\tget weight() {\n\t\treturn this._weight;\n\t}\n\n\tset weight(w) {\n\t\tif (typeof w !== 'number') throw new Error('wrong argument type');\n\t\tthis._weight = w;\n\t\tthis._thickness = w;\n\t\tthis._targetThickness = w;\n\t\tthis._maxWeight = w + this.WEIGHT_SPREAD;\n\t}\n\n\tget mode() {\n\t\treturn this._mode;\n\t}\n\n\tget dirty() {\n\t\treturn !!this._dirty;\n\t}\n\n\tset mode(m) {\n\t\tif (typeof m !== 'string') throw new Error('wrong argument type');\n\t\tswitch (m) {\n\t\t\tcase 'erase':\n\t\t\t\tthis._mode = 'erase';\n\t\t\t\tthis.context.globalCompositeOperation = 'destination-out';\n\t\t\t\tbreak;\n\t\t\tcase 'fill':\n\t\t\t\tthis._mode = 'fill';\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis._mode = 'draw';\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tget smoothing() {\n\t\treturn this._smoothing === this.SMOOTHING_INIT;\n\t}\n\n\tset smoothing(s) {\n\t\tif (typeof s !== 'boolean') throw new Error('wrong argument type');\n\t\tthis._smoothing = s ? this.SMOOTHING_INIT : 0;\n\t}\n\n\tset opacity(o) {\n\t\tif (typeof o !== 'number') throw new Error('wrong argument type');\n\t\t//now, we need to scale this, because our drawing method means we don't just get uniform transparency all over the drawn line.\n\t\t//so we scale it down a lot, meaning that it'll look nicely semi-transparent\n\t\t//unless opacity is 1, then we should go full on to 1\n\t\tif (o >= 1) this.context.globalAlpha = 1;\n\t\telse this.context.globalAlpha = o/10;\n\t}\n\n\tfireDirty() {\n\t\tconst event = document.createEvent('Event');\n\t\tevent.initEvent('dirty', true, true);\n\t\tthis.canvas.dispatchEvent(event);\n\t}\n\n\tclear() {\n\t\tif (!this.dirty) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._dirty = false;\n\t\tthis.fireDirty();\n\n\t\t//make sure we're in the right compositing mode, and erase everything\n\t\tif (this.context.globalCompositeOperation === 'destination-out') {\n\t\t\tthis.mode = 'draw';\n\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\tthis.mode = 'erase';\n\t\t}\n\t\telse {\n\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t}\n\t}\n\n\ttoImage() {\n\t\treturn this.canvas.toDataURL();\n\t}\n\n\tfill(){\n\t\tlet mouse = this.mouse;\n\t\tlet context = this.context;\n\t\tlet startColor = Array.prototype.slice.call(context.getImageData(mouse.x, mouse.y, 1, 1).data,0); //converting to Array because Safari 9\n\n\t\tif (!this._filling) {\n\t\t\tthis.canvas.style.cursor = 'progress';\n\t\t\tthis._filling = true;\n\n\t\t\tsetTimeout(() => { this._floodFill(mouse.x, mouse.y, startColor); }, 100);\n\t\t}\n\t\telse {\n\t\t\tthis._fillStack.push([\n\t\t\t\tmouse.x,\n\t\t\t\tmouse.y,\n\t\t\t\tstartColor\n\t\t\t]);\n\t\t}\n\t}\n\n\t_floodFill(startX, startY, startColor){\n\t\tlet context = this.context,\n\t\t\tcanvasWidth = context.canvas.width,\n\t\t\tcanvasHeight = context.canvas.height,\n\t\t\tpixelStack = [[startX, startY]],\n\t\t\t//hex needs to be trasformed to rgb since colorLayer accepts RGB\n\t\t\tfillColor = Atrament.hexToRgb(this.color),\n\t\t\t//Need to save current context with colors, we will update it\n\t\t\tcolorLayer = context.getImageData(0, 0, context.canvas.width, context.canvas.height),\n\t\t\talpha = Math.min(context.globalAlpha * 10 * 255, 255),\n\t\t\tcolorPixel = Atrament.colorPixel(colorLayer.data, ...fillColor, startColor, alpha),\n\t\t\tmatchColor = Atrament.matchColor(colorLayer.data, ...startColor);\n\n\t\tconst matchFillColor = Atrament.matchColor(colorLayer.data, ...[...fillColor, 255]);\n\t\t// check if we're trying to fill with the same colour, if so, stop\n\t\tif (matchFillColor((startY*context.canvas.width + startX) * 4)) {\n\t\t\tthis._filling = false;\n\t\t\tsetTimeout(() => { this.canvas.style.cursor = 'crosshair'; }, 100);\n\t\t\treturn;\n\t\t}\n\n\t\twhile(pixelStack.length) {\n\t\t\tlet newPos = pixelStack.pop();\n\t\t\tlet [x,y] = newPos;\n\n\t\t\tlet pixelPos = (y*canvasWidth + x) * 4;\n\n\t\t\twhile(y-- >= 0 && matchColor(pixelPos))\n\t\t\t{\n\t\t\t\tpixelPos -= canvasWidth * 4;\n\t\t\t}\n\t\t\tpixelPos += canvasWidth * 4;\n\n\t\t\t++y;\n\n\t\t\tlet reachLeft = false;\n\t\t\tlet reachRight = false;\n\n\t\t\twhile(y++ < canvasHeight-1 && matchColor(pixelPos))\n\t\t\t{\n\t\t\t\tcolorPixel(pixelPos);\n\n\t\t\t\tif(x > 0)\n\t\t\t\t{\n\t\t\t\t\tif(matchColor(pixelPos - 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!reachLeft){\n\t\t\t\t\t\t\tpixelStack.push([x - 1, y]);\n\t\t\t\t\t\t\treachLeft = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(reachLeft)\n\t\t\t\t\t{\n\t\t\t\t\t\treachLeft = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(x < canvasWidth-1)\n\t\t\t\t{\n\t\t\t\t\tif(matchColor(pixelPos + 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!reachRight)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpixelStack.push([x + 1, y]);\n\t\t\t\t\t\t\treachRight = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(reachRight)\n\t\t\t\t\t{\n\t\t\t\t\t\treachRight = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpixelPos += canvasWidth * 4;\n\t\t\t}\n\t\t}\n\n\t\t//Update context with filled bucket!\n\t\tcontext.putImageData(colorLayer, 0, 0);\n\n\t\tif (this._fillStack.length) {\n\t\t\tthis._floodFill(...this._fillStack.shift());\n\t\t}\n\t\telse {\n\t\t\tthis._filling = false;\n\t\t\tsetTimeout(() => { this.canvas.style.cursor = 'crosshair'; }, 100);\n\t\t}\n\n\t}\n\n}\n\n//for people who like functional programming\nfunction atrament(selector, width, height, color) {\n\treturn new Atrament(selector, width, height, color);\n}\n\nmodule.exports = atrament;\nmodule.exports.Atrament = Atrament;\n\n\n\n// WEBPACK FOOTER //\n// ./src/atrament.js"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///atrament.min.js","webpack:///webpack/bootstrap 3e2f0076246328c814ab","webpack:///./index.js","webpack:///./src/atrament.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","_toConsumableArray","arr","Array","isArray","i","arr2","length","from","_possibleConstructorReturn","self","ReferenceError","_inherits","subClass","superClass","TypeError","prototype","Object","create","constructor","value","enumerable","writable","configurable","setPrototypeOf","__proto__","_classCallCheck","instance","Constructor","atrament","selector","width","height","color","Atrament","_slicedToArray","sliceIterator","_arr","_n","_d","_e","undefined","_s","_i","Symbol","iterator","next","done","push","err","_createClass","defineProperties","target","props","descriptor","defineProperty","key","protoProps","staticProps","Point","x","y","arguments","Error","_x","_y","get","set","Mouse","_Point","_this","getPrototypeOf","_down","_px","_py","d","px","py","_this2","document","Node","tagName","canvas","querySelector","style","cursor","mouse","mouseMove","e","preventDefault","rect","getBoundingClientRect","position","changedTouches","offsetX","offsetY","clientX","documentElement","scrollLeft","left","clientY","scrollTop","top","down","draw","_dirty","fireDirty","mouseDown","mousePosition","_mode","fill","context","beginPath","moveTo","mouseUp","closePath","addEventListener","destroy","clear","removeEventListener","getContext","globalCompositeOperation","globalAlpha","strokeStyle","lineCap","lineJoin","translate","_filling","_fillStack","SMOOTHING_INIT","WEIGHT_SPREAD","_smoothing","_maxWeight","_thickness","_targetThickness","_weight","mX","mY","raw_dist","lineDistance","smoothingFactor","Math","min","dist","lineWidth","quadraticCurveTo","stroke","event","createEvent","initEvent","dispatchEvent","dirty","mode","clearRect","toDataURL","_this3","startColor","slice","getImageData","data","setTimeout","_floodFill","startX","startY","_this4","canvasWidth","canvasHeight","pixelStack","fillColor","hexToRgb","colorLayer","alpha","colorPixel","apply","concat","matchColor","matchFillColor","newPos","pop","_newPos","pixelPos","reachLeft","reachRight","putImageData","shift","w","s","o","x1","y1","x2","y2","xs","pow","ys","sqrt","hexColor","match","parseInt","compR","compG","compB","compA","r","g","b","a","fillR","fillG","fillB"],"mappings":"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","file":"atrament.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"atrament\"] = factory();\n\telse\n\t\troot[\"atrament\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"atrament\"] = factory();\n\telse\n\t\troot[\"atrament\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(1);\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tmodule.exports = __webpack_require__(2);\n\n/***/ },\n/* 2 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\tvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\t\n\tvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\t\n\tfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\t\n\tfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\t\n\tfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\t\n\tfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\t\n\t//make a class for Point\n\tvar Point = function () {\n\t\tfunction Point(x, y) {\n\t\t\t_classCallCheck(this, Point);\n\t\n\t\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.');\n\t\t\tthis._x = x;\n\t\t\tthis._y = y;\n\t\t}\n\t\n\t\t_createClass(Point, [{\n\t\t\tkey: 'set',\n\t\t\tvalue: function set(x, y) {\n\t\t\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.set');\n\t\t\t\tthis._x = x;\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'x',\n\t\t\tget: function get() {\n\t\t\t\treturn this._x;\n\t\t\t},\n\t\t\tset: function set(x) {\n\t\t\t\tthis._x = x;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'y',\n\t\t\tget: function get() {\n\t\t\t\treturn this._y;\n\t\t\t},\n\t\t\tset: function set(y) {\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Point;\n\t}();\n\t\n\t//make a class for the mouse data\n\t\n\t\n\tvar Mouse = function (_Point) {\n\t\t_inherits(Mouse, _Point);\n\t\n\t\tfunction Mouse() {\n\t\t\t_classCallCheck(this, Mouse);\n\t\n\t\t\tvar _this = _possibleConstructorReturn(this, (Mouse.__proto__ || Object.getPrototypeOf(Mouse)).call(this, 0, 0));\n\t\n\t\t\t_this._down = false;\n\t\t\t_this._px = 0;\n\t\t\t_this._py = 0;\n\t\t\treturn _this;\n\t\t}\n\t\n\t\t_createClass(Mouse, [{\n\t\t\tkey: 'down',\n\t\t\tget: function get() {\n\t\t\t\treturn this._down;\n\t\t\t},\n\t\t\tset: function set(d) {\n\t\t\t\tthis._down = d;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'x',\n\t\t\tget: function get() {\n\t\t\t\treturn this._x;\n\t\t\t},\n\t\t\tset: function set(x) {\n\t\t\t\tthis._x = x;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'y',\n\t\t\tget: function get() {\n\t\t\t\treturn this._y;\n\t\t\t},\n\t\t\tset: function set(y) {\n\t\t\t\tthis._y = y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'px',\n\t\t\tget: function get() {\n\t\t\t\treturn this._px;\n\t\t\t},\n\t\t\tset: function set(px) {\n\t\t\t\tthis._px = px;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'py',\n\t\t\tget: function get() {\n\t\t\t\treturn this._py;\n\t\t\t},\n\t\t\tset: function set(py) {\n\t\t\t\tthis._py = py;\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Mouse;\n\t}(Point);\n\t\n\tvar Atrament = function () {\n\t\tfunction Atrament(selector, width, height, color) {\n\t\t\tvar _this2 = this;\n\t\n\t\t\t_classCallCheck(this, Atrament);\n\t\n\t\t\tif (!document) throw new Error('no DOM found');\n\t\n\t\t\t//get canvas element\n\t\t\tif (selector instanceof Node && selector.tagName === 'CANVAS') this.canvas = selector;else if (typeof selector === 'string') this.canvas = document.querySelector(selector);else throw new Error('can\\'t look for canvas based on \\'' + selector + '\\'');\n\t\t\tif (!this.canvas) throw new Error('canvas not found');\n\t\n\t\t\t//set external canvas params\n\t\t\tthis.canvas.width = width ? width : 500;\n\t\t\tthis.canvas.height = height ? height : 500;\n\t\t\tthis.canvas.style.cursor = 'crosshair';\n\t\n\t\t\t//create a mouse object\n\t\t\tthis.mouse = new Mouse();\n\t\n\t\t\t//mousemove handler\n\t\t\tvar mouseMove = function mouseMove(e) {\n\t\t\t\te.preventDefault();\n\t\n\t\t\t\tvar rect = _this2.canvas.getBoundingClientRect();\n\t\t\t\tvar position = e.changedTouches && e.changedTouches[0] || e;\n\t\t\t\tvar x = position.offsetX;\n\t\t\t\tvar y = position.offsetY;\n\t\n\t\t\t\tif (typeof x === 'undefined') {\n\t\t\t\t\tx = position.clientX + document.documentElement.scrollLeft - rect.left;\n\t\t\t\t}\n\t\t\t\tif (typeof y === 'undefined') {\n\t\t\t\t\ty = position.clientY + document.documentElement.scrollTop - rect.top;\n\t\t\t\t}\n\t\n\t\t\t\t//draw if we should draw\n\t\t\t\tif (_this2.mouse.down) {\n\t\t\t\t\t_this2.draw(x, y);\n\t\t\t\t\tif (!_this2._dirty && (x !== _this2.mouse.x || y !== _this2.mouse.y)) {\n\t\t\t\t\t\t_this2._dirty = true;\n\t\t\t\t\t\t_this2.fireDirty();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t_this2.mouse.x = x;\n\t\t\t\t\t_this2.mouse.y = y;\n\t\t\t\t}\n\t\t\t};\n\t\n\t\t\t//mousedown handler\n\t\t\tvar mouseDown = function mouseDown(mousePosition) {\n\t\t\t\tmousePosition.preventDefault();\n\t\t\t\t//update position just in case\n\t\t\t\tmouseMove(mousePosition);\n\t\n\t\t\t\t//if we are filling - fill and return\n\t\t\t\tif (_this2._mode === 'fill') {\n\t\t\t\t\t_this2.fill();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\t//remember it\n\t\t\t\t_this2.mouse.px = _this2.mouse.x;\n\t\t\t\t_this2.mouse.py = _this2.mouse.y;\n\t\t\t\t//begin drawing\n\t\t\t\t_this2.mouse.down = true;\n\t\t\t\t_this2.context.beginPath();\n\t\t\t\t_this2.context.moveTo(_this2.mouse.px, _this2.mouse.py);\n\t\t\t};\n\t\t\tvar mouseUp = function mouseUp(mousePosition) {\n\t\t\t\t_this2.mouse.down = false;\n\t\t\t\t//stop drawing\n\t\t\t\t_this2.context.closePath();\n\t\t\t};\n\t\n\t\t\t//attach listeners\n\t\t\tthis.canvas.addEventListener('mousemove', mouseMove);\n\t\t\tthis.canvas.addEventListener('mousedown', mouseDown);\n\t\t\tdocument.addEventListener('mouseup', mouseUp);\n\t\t\tthis.canvas.addEventListener('touchstart', mouseDown);\n\t\t\tthis.canvas.addEventListener('touchend', mouseUp);\n\t\t\tthis.canvas.addEventListener('touchmove', mouseMove);\n\t\n\t\t\t//helper for destroying Atrament (removing event listeners)\n\t\t\tthis.destroy = function () {\n\t\t\t\t_this2.clear();\n\t\t\t\t_this2.canvas.removeEventListener('mousemove', mouseMove);\n\t\t\t\t_this2.canvas.removeEventListener('mousedown', mouseDown);\n\t\t\t\tdocument.removeEventListener('mouseup', mouseUp);\n\t\t\t\t_this2.canvas.removeEventListener('touchstart', mouseDown);\n\t\t\t\t_this2.canvas.removeEventListener('touchend', mouseUp);\n\t\t\t\t_this2.canvas.removeEventListener('touchmove', mouseMove);\n\t\t\t};\n\t\n\t\t\t//set internal canvas params\n\t\t\tthis.context = this.canvas.getContext('2d');\n\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\tthis.context.globalAlpha = 1;\n\t\t\tthis.context.strokeStyle = color ? color : 'rgba(0,0,0,1)';\n\t\t\tthis.context.lineCap = 'round';\n\t\t\tthis.context.lineJoin = 'round';\n\t\t\tthis.context.translate(0.5, 0.5);\n\t\n\t\t\tthis._filling = false;\n\t\t\tthis._fillStack = [];\n\t\n\t\t\t//set drawing params\n\t\t\tthis.SMOOTHING_INIT = 0.85;\n\t\t\tthis.WEIGHT_SPREAD = 10;\n\t\t\tthis._smoothing = this.SMOOTHING_INIT;\n\t\t\tthis._maxWeight = 12;\n\t\t\tthis._thickness = 2;\n\t\t\tthis._targetThickness = 2;\n\t\t\tthis._weight = 2;\n\t\t\tthis._mode = 'draw';\n\t\t}\n\t\n\t\t_createClass(Atrament, [{\n\t\t\tkey: 'draw',\n\t\t\tvalue: function draw(mX, mY) {\n\t\t\t\tvar mouse = this.mouse;\n\t\t\t\tvar context = this.context;\n\t\n\t\t\t\t//calculate distance from previous point\n\t\t\t\tvar raw_dist = Atrament.lineDistance(mX, mY, mouse.px, mouse.py);\n\t\n\t\t\t\t//now, here we scale the initial smoothing factor by the raw distance\n\t\t\t\t//this means that when the mouse moves fast, there is more smoothing\n\t\t\t\t//and when we're drawing small detailed stuff, we have more control\n\t\t\t\t//also we hard clip at 1\n\t\t\t\tvar smoothingFactor = Math.min(0.87, this._smoothing + (raw_dist - 60) / 3000);\n\t\n\t\t\t\t//calculate smoothed coordinates\n\t\t\t\tmouse.x = mX - (mX - mouse.px) * smoothingFactor;\n\t\t\t\tmouse.y = mY - (mY - mouse.py) * smoothingFactor;\n\t\n\t\t\t\t//recalculate distance from previous point, this time relative to the smoothed coords\n\t\t\t\tvar dist = Atrament.lineDistance(mouse.x, mouse.y, mouse.px, mouse.py);\n\t\n\t\t\t\t//calculate target thickness based on the new distance\n\t\t\t\tthis._targetThickness = (dist - 1) / (50 - 1) * (this._maxWeight - this._weight) + this._weight;\n\t\t\t\t//approach the target gradually\n\t\t\t\tif (this._thickness > this._targetThickness) {\n\t\t\t\t\tthis._thickness -= 0.5;\n\t\t\t\t} else if (this._thickness < this._targetThickness) {\n\t\t\t\t\tthis._thickness += 0.5;\n\t\t\t\t}\n\t\t\t\t//set line width\n\t\t\t\tcontext.lineWidth = this._thickness;\n\t\n\t\t\t\t//draw using quad interpolation\n\t\t\t\tcontext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);\n\t\t\t\tcontext.stroke();\n\t\n\t\t\t\t//remember\n\t\t\t\tmouse.px = mouse.x;\n\t\t\t\tmouse.py = mouse.y;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'fireDirty',\n\t\t\tvalue: function fireDirty() {\n\t\t\t\tvar event = document.createEvent('Event');\n\t\t\t\tevent.initEvent('dirty', true, true);\n\t\t\t\tthis.canvas.dispatchEvent(event);\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'clear',\n\t\t\tvalue: function clear() {\n\t\t\t\tif (!this.dirty) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\tthis._dirty = false;\n\t\t\t\tthis.fireDirty();\n\t\n\t\t\t\t//make sure we're in the right compositing mode, and erase everything\n\t\t\t\tif (this.context.globalCompositeOperation === 'destination-out') {\n\t\t\t\t\tthis.mode = 'draw';\n\t\t\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\t\t\tthis.mode = 'erase';\n\t\t\t\t} else {\n\t\t\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'toImage',\n\t\t\tvalue: function toImage() {\n\t\t\t\treturn this.canvas.toDataURL();\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'fill',\n\t\t\tvalue: function fill() {\n\t\t\t\tvar _this3 = this;\n\t\n\t\t\t\tvar mouse = this.mouse;\n\t\t\t\tvar context = this.context;\n\t\t\t\tvar startColor = Array.prototype.slice.call(context.getImageData(mouse.x, mouse.y, 1, 1).data, 0); //converting to Array because Safari 9\n\t\n\t\t\t\tif (!this._filling) {\n\t\t\t\t\tthis.canvas.style.cursor = 'progress';\n\t\t\t\t\tthis._filling = true;\n\t\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this3._floodFill(mouse.x, mouse.y, startColor);\n\t\t\t\t\t}, 100);\n\t\t\t\t} else {\n\t\t\t\t\tthis._fillStack.push([mouse.x, mouse.y, startColor]);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: '_floodFill',\n\t\t\tvalue: function _floodFill(startX, startY, startColor) {\n\t\t\t\tvar _this4 = this;\n\t\n\t\t\t\tvar context = this.context,\n\t\t\t\t canvasWidth = context.canvas.width,\n\t\t\t\t canvasHeight = context.canvas.height,\n\t\t\t\t pixelStack = [[startX, startY]],\n\t\n\t\t\t\t//hex needs to be trasformed to rgb since colorLayer accepts RGB\n\t\t\t\tfillColor = Atrament.hexToRgb(this.color),\n\t\n\t\t\t\t//Need to save current context with colors, we will update it\n\t\t\t\tcolorLayer = context.getImageData(0, 0, context.canvas.width, context.canvas.height),\n\t\t\t\t alpha = Math.min(context.globalAlpha * 10 * 255, 255),\n\t\t\t\t colorPixel = Atrament.colorPixel.apply(Atrament, [colorLayer.data].concat(_toConsumableArray(fillColor), [startColor, alpha])),\n\t\t\t\t matchColor = Atrament.matchColor.apply(Atrament, [colorLayer.data].concat(_toConsumableArray(startColor)));\n\t\n\t\t\t\tvar matchFillColor = Atrament.matchColor.apply(Atrament, [colorLayer.data].concat([].concat(_toConsumableArray(fillColor), [255])));\n\t\t\t\t// check if we're trying to fill with the same colour, if so, stop\n\t\t\t\tif (matchFillColor((startY * context.canvas.width + startX) * 4)) {\n\t\t\t\t\tthis._filling = false;\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this4.canvas.style.cursor = 'crosshair';\n\t\t\t\t\t}, 100);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\n\t\t\t\twhile (pixelStack.length) {\n\t\t\t\t\tvar newPos = pixelStack.pop();\n\t\n\t\t\t\t\tvar _newPos = _slicedToArray(newPos, 2),\n\t\t\t\t\t x = _newPos[0],\n\t\t\t\t\t y = _newPos[1];\n\t\n\t\t\t\t\tvar pixelPos = (y * canvasWidth + x) * 4;\n\t\n\t\t\t\t\twhile (y-- >= 0 && matchColor(pixelPos)) {\n\t\t\t\t\t\tpixelPos -= canvasWidth * 4;\n\t\t\t\t\t}\n\t\t\t\t\tpixelPos += canvasWidth * 4;\n\t\n\t\t\t\t\t++y;\n\t\n\t\t\t\t\tvar reachLeft = false;\n\t\t\t\t\tvar reachRight = false;\n\t\n\t\t\t\t\twhile (y++ < canvasHeight - 1 && matchColor(pixelPos)) {\n\t\t\t\t\t\tcolorPixel(pixelPos);\n\t\n\t\t\t\t\t\tif (x > 0) {\n\t\t\t\t\t\t\tif (matchColor(pixelPos - 4)) {\n\t\t\t\t\t\t\t\tif (!reachLeft) {\n\t\t\t\t\t\t\t\t\tpixelStack.push([x - 1, y]);\n\t\t\t\t\t\t\t\t\treachLeft = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (reachLeft) {\n\t\t\t\t\t\t\t\treachLeft = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tif (x < canvasWidth - 1) {\n\t\t\t\t\t\t\tif (matchColor(pixelPos + 4)) {\n\t\t\t\t\t\t\t\tif (!reachRight) {\n\t\t\t\t\t\t\t\t\tpixelStack.push([x + 1, y]);\n\t\t\t\t\t\t\t\t\treachRight = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (reachRight) {\n\t\t\t\t\t\t\t\treachRight = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tpixelPos += canvasWidth * 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\n\t\t\t\t//Update context with filled bucket!\n\t\t\t\tcontext.putImageData(colorLayer, 0, 0);\n\t\n\t\t\t\tif (this._fillStack.length) {\n\t\t\t\t\tthis._floodFill.apply(this, _toConsumableArray(this._fillStack.shift()));\n\t\t\t\t} else {\n\t\t\t\t\tthis._filling = false;\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t_this4.canvas.style.cursor = 'crosshair';\n\t\t\t\t\t}, 100);\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'color',\n\t\t\tget: function get() {\n\t\t\t\treturn this.context.strokeStyle;\n\t\t\t},\n\t\t\tset: function set(c) {\n\t\t\t\tif (typeof c !== 'string') throw new Error('wrong argument type');\n\t\t\t\tthis.context.strokeStyle = c;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'weight',\n\t\t\tget: function get() {\n\t\t\t\treturn this._weight;\n\t\t\t},\n\t\t\tset: function set(w) {\n\t\t\t\tif (typeof w !== 'number') throw new Error('wrong argument type');\n\t\t\t\tthis._weight = w;\n\t\t\t\tthis._thickness = w;\n\t\t\t\tthis._targetThickness = w;\n\t\t\t\tthis._maxWeight = w + this.WEIGHT_SPREAD;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'mode',\n\t\t\tget: function get() {\n\t\t\t\treturn this._mode;\n\t\t\t},\n\t\t\tset: function set(m) {\n\t\t\t\tif (typeof m !== 'string') throw new Error('wrong argument type');\n\t\t\t\tswitch (m) {\n\t\t\t\t\tcase 'erase':\n\t\t\t\t\t\tthis._mode = 'erase';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'destination-out';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'fill':\n\t\t\t\t\t\tthis._mode = 'fill';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthis._mode = 'draw';\n\t\t\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'dirty',\n\t\t\tget: function get() {\n\t\t\t\treturn !!this._dirty;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'smoothing',\n\t\t\tget: function get() {\n\t\t\t\treturn this._smoothing === this.SMOOTHING_INIT;\n\t\t\t},\n\t\t\tset: function set(s) {\n\t\t\t\tif (typeof s !== 'boolean') throw new Error('wrong argument type');\n\t\t\t\tthis._smoothing = s ? this.SMOOTHING_INIT : 0;\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'opacity',\n\t\t\tset: function set(o) {\n\t\t\t\tif (typeof o !== 'number') throw new Error('wrong argument type');\n\t\t\t\t//now, we need to scale this, because our drawing method means we don't just get uniform transparency all over the drawn line.\n\t\t\t\t//so we scale it down a lot, meaning that it'll look nicely semi-transparent\n\t\t\t\t//unless opacity is 1, then we should go full on to 1\n\t\t\t\tif (o >= 1) this.context.globalAlpha = 1;else this.context.globalAlpha = o / 10;\n\t\t\t}\n\t\t}], [{\n\t\t\tkey: 'lineDistance',\n\t\t\tvalue: function lineDistance(x1, y1, x2, y2) {\n\t\t\t\t//calculate euclidean distance between (x1, y1) and (x2, y2)\n\t\t\t\tvar xs = Math.pow(x2 - x1, 2);\n\t\t\t\tvar ys = Math.pow(y2 - y1, 2);\n\t\t\t\treturn Math.sqrt(xs + ys);\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'hexToRgb',\n\t\t\tvalue: function hexToRgb(hexColor) {\n\t\t\t\t//Since input type color provides hex and ImageData accepts RGB need to transform\n\t\t\t\tvar m = hexColor.match(/^#?([\\da-f]{2})([\\da-f]{2})([\\da-f]{2})$/i);\n\t\t\t\treturn [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16)];\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'matchColor',\n\t\t\tvalue: function matchColor(data, compR, compG, compB, compA) {\n\t\t\t\treturn function (pixelPos) {\n\t\t\t\t\t//Pixel color equals comp color?\n\t\t\t\t\tvar r = data[pixelPos],\n\t\t\t\t\t g = data[pixelPos + 1],\n\t\t\t\t\t b = data[pixelPos + 2],\n\t\t\t\t\t a = data[pixelPos + 3];\n\t\n\t\t\t\t\treturn r === compR && g === compG && b === compB && a === compA;\n\t\t\t\t};\n\t\t\t}\n\t\t}, {\n\t\t\tkey: 'colorPixel',\n\t\t\tvalue: function colorPixel(data, fillR, fillG, fillB, startColor, alpha) {\n\t\t\t\tvar matchColor = Atrament.matchColor.apply(Atrament, [data].concat(_toConsumableArray(startColor)));\n\t\n\t\t\t\treturn function (pixelPos) {\n\t\t\t\t\t//Update fill color in matrix\n\t\t\t\t\tdata[pixelPos] = fillR;\n\t\t\t\t\tdata[pixelPos + 1] = fillG;\n\t\t\t\t\tdata[pixelPos + 2] = fillB;\n\t\t\t\t\tdata[pixelPos + 3] = alpha;\n\t\n\t\t\t\t\tif (!matchColor(pixelPos + 4)) {\n\t\t\t\t\t\tdata[pixelPos + 4] = data[pixelPos + 4] * 0.01 + fillR * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 1] = data[pixelPos + 4 + 1] * 0.01 + fillG * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 2] = data[pixelPos + 4 + 2] * 0.01 + fillB * 0.99;\n\t\t\t\t\t\tdata[pixelPos + 4 + 3] = data[pixelPos + 4 + 3] * 0.01 + alpha * 0.99;\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (!matchColor(pixelPos - 4)) {\n\t\t\t\t\t\tdata[pixelPos - 4] = data[pixelPos - 4] * 0.01 + fillR * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 1] = data[pixelPos - 4 + 1] * 0.01 + fillG * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 2] = data[pixelPos - 4 + 2] * 0.01 + fillB * 0.99;\n\t\t\t\t\t\tdata[pixelPos - 4 + 3] = data[pixelPos - 4 + 3] * 0.01 + alpha * 0.99;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t}]);\n\t\n\t\treturn Atrament;\n\t}();\n\t\n\t//for people who like functional programming\n\t\n\t\n\tfunction atrament(selector, width, height, color) {\n\t\treturn new Atrament(selector, width, height, color);\n\t}\n\t\n\tmodule.exports = atrament;\n\tmodule.exports.Atrament = Atrament;\n\n/***/ }\n/******/ ])\n});\n;\n\n\n// WEBPACK FOOTER //\n// atrament.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 3e2f0076246328c814ab","module.exports = require('./src/atrament.js');\n\n\n// WEBPACK FOOTER //\n// ./index.js","//make a class for Point\nclass Point {\n\tconstructor(x, y) {\n\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.');\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t}\n\n\tget x() {\n\t\treturn this._x;\n\t}\n\n\tget y() {\n\t\treturn this._y;\n\t}\n\n\tset x(x) {\n\t\tthis._x = x;\n\t}\n\n\tset y(y) {\n\t\tthis._y = y;\n\t}\n\n\tset(x, y) {\n\t\tif (arguments.length < 2) throw new Error('not enough coordinates for Point.set');\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t}\n}\n\n//make a class for the mouse data\nclass Mouse extends Point {\n\tconstructor() {\n\t\tsuper(0, 0);\n\t\tthis._down = false;\n\t\tthis._px = 0;\n\t\tthis._py = 0;\n\t}\n\n\tget down() {\n\t\treturn this._down;\n\t}\n\n\tset down(d) {\n\t\tthis._down = d;\n\t}\n\n\tget x() {\n\t\treturn this._x;\n\t}\n\n\tget y() {\n\t\treturn this._y;\n\t}\n\n\tset x(x) {\n\t\tthis._x = x;\n\t}\n\n\tset y(y) {\n\t\tthis._y = y;\n\t}\n\n\tget px() {\n\t\treturn this._px;\n\t}\n\n\tget py() {\n\t\treturn this._py;\n\t}\n\n\tset px(px) {\n\t\tthis._px = px;\n\t}\n\n\tset py(py) {\n\t\tthis._py = py;\n\t}\n\n}\n\n\nclass Atrament {\n\tconstructor(selector, width, height, color) {\n\t\tif (!document) throw new Error('no DOM found');\n\n\t\t//get canvas element\n\t\tif (selector instanceof Node && selector.tagName === 'CANVAS') this.canvas = selector;\n\t\telse if (typeof selector === 'string') this.canvas = document.querySelector(selector);\n\t\telse throw new Error(`can\\'t look for canvas based on \\'${selector}\\'`);\n\t\tif (!this.canvas) throw new Error('canvas not found');\n\n\t\t//set external canvas params\n\t\tthis.canvas.width = width ? width : 500;\n\t\tthis.canvas.height = height ? height : 500;\n\t\tthis.canvas.style.cursor = 'crosshair';\n\n\t\t//create a mouse object\n\t\tthis.mouse = new Mouse();\n\n\t\t//mousemove handler\n\t\tlet mouseMove = e => {\n\t\t\te.preventDefault();\n\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tconst position = e.changedTouches && e.changedTouches[0] || e;\n\t\t\tlet x = position.offsetX;\n\t\t\tlet y = position.offsetY;\n\n\t\t\tif (typeof x === 'undefined') {\n\t\t\t\tx = position.clientX + document.documentElement.scrollLeft - rect.left;\n\t\t\t}\n\t\t\tif (typeof y === 'undefined') {\n\t\t\t\ty = position.clientY + document.documentElement.scrollTop - rect.top;\n\t\t\t}\n\n\t\t\t//draw if we should draw\n\t\t\tif (this.mouse.down) {\n\t\t\t\tthis.draw(x, y);\n\t\t\t\tif (!this._dirty && (x !== this.mouse.x || y !== this.mouse.y)) {\n\t\t\t\t\tthis._dirty = true;\n\t\t\t\t\tthis.fireDirty();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.mouse.x = x;\n\t\t\t\tthis.mouse.y = y;\n\t\t\t}\n\t\t}\n\n\t\t//mousedown handler\n\t\tlet mouseDown = (mousePosition) => {\n\t\t\tmousePosition.preventDefault();\n\t\t\t//update position just in case\n\t\t\tmouseMove(mousePosition);\n\n\t\t\t//if we are filling - fill and return\n\t\t\tif(this._mode === 'fill'){\n\t\t\t\tthis.fill();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//remember it\n\t\t\tthis.mouse.px = this.mouse.x;\n\t\t\tthis.mouse.py = this.mouse.y;\n\t\t\t//begin drawing\n\t\t\tthis.mouse.down = true;\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.moveTo(this.mouse.px, this.mouse.py);\n\t\t}\n\t\tlet mouseUp = (mousePosition) => {\n\t\t\tthis.mouse.down = false;\n\t\t\t//stop drawing\n\t\t\tthis.context.closePath();\n\t\t}\n\n\t\t//attach listeners\n\t\tthis.canvas.addEventListener('mousemove', mouseMove);\n\t\tthis.canvas.addEventListener('mousedown', mouseDown);\n\t\tdocument.addEventListener('mouseup', mouseUp);\n\t\tthis.canvas.addEventListener('touchstart', mouseDown);\n\t\tthis.canvas.addEventListener('touchend', mouseUp);\n\t\tthis.canvas.addEventListener('touchmove', mouseMove);\n\n\t\t//helper for destroying Atrament (removing event listeners)\n\t\tthis.destroy = () => {\n\t\t\tthis.clear();\n\t\t\tthis.canvas.removeEventListener('mousemove', mouseMove);\n\t\t\tthis.canvas.removeEventListener('mousedown', mouseDown);\n\t\t\tdocument.removeEventListener('mouseup', mouseUp);\n\t\t\tthis.canvas.removeEventListener('touchstart', mouseDown);\n\t\t\tthis.canvas.removeEventListener('touchend', mouseUp);\n\t\t\tthis.canvas.removeEventListener('touchmove', mouseMove);\n\t\t};\n\n\t\t//set internal canvas params\n\t\tthis.context = this.canvas.getContext('2d');\n\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\tthis.context.globalAlpha = 1;\n\t\tthis.context.strokeStyle = color ? color : 'rgba(0,0,0,1)';\n\t\tthis.context.lineCap = 'round';\n\t\tthis.context.lineJoin = 'round';\n\t\tthis.context.translate(0.5, 0.5);\n\n\t\tthis._filling = false;\n\t\tthis._fillStack = [];\n\n\t\t//set drawing params\n\t\tthis.SMOOTHING_INIT = 0.85;\n\t\tthis.WEIGHT_SPREAD = 10;\n\t\tthis._smoothing = this.SMOOTHING_INIT;\n\t\tthis._maxWeight = 12;\n\t\tthis._thickness = 2;\n\t\tthis._targetThickness = 2;\n\t\tthis._weight = 2;\n\t\tthis._mode = 'draw';\n\t}\n\n\tstatic lineDistance(x1, y1, x2, y2) {\n\t\t//calculate euclidean distance between (x1, y1) and (x2, y2)\n\t let xs = Math.pow(x2 - x1, 2);\n\t\tlet ys = Math.pow(y2 - y1, 2);\n\t return Math.sqrt( xs + ys );\n\t}\n\n\tstatic hexToRgb(hexColor){\n\t\t//Since input type color provides hex and ImageData accepts RGB need to transform\n\t\tlet m = hexColor.match(/^#?([\\da-f]{2})([\\da-f]{2})([\\da-f]{2})$/i);\n\t\treturn [\n\t\t\tparseInt(m[1], 16),\n\t\t\tparseInt(m[2], 16),\n\t\t\tparseInt(m[3], 16)\n\t\t];\n\t}\n\n\tstatic matchColor(data, compR, compG, compB, compA) {\n\t\treturn (pixelPos)=>{\n\t\t\t//Pixel color equals comp color?\n\t\t\tlet r = data[pixelPos],\n\t\t\t\tg = data[pixelPos+1],\n\t\t\t\tb = data[pixelPos+2],\n\t\t\t\ta = data[pixelPos+3];\n\n\t\t\treturn (r === compR && g === compG && b === compB && a === compA);\n\t\t}\n\t}\n\n\tstatic colorPixel(data, fillR, fillG, fillB, startColor, alpha) {\n\t\tlet matchColor = Atrament.matchColor(data, ...startColor);\n\n\t\treturn (pixelPos)=>{\n\t\t\t//Update fill color in matrix\n\t\t\tdata[pixelPos] = fillR;\n\t\t\tdata[pixelPos+1] = fillG;\n\t\t\tdata[pixelPos+2] = fillB;\n\t\t\tdata[pixelPos+3] = alpha;\n\n\t\t\tif (!matchColor(pixelPos + 4)) {\n\t\t\t\tdata[pixelPos+4] = data[pixelPos+4] * 0.01 + fillR*0.99;\n\t\t\t\tdata[pixelPos+4+1] = data[pixelPos+4+1] * 0.01 + fillG*0.99;\n\t\t\t\tdata[pixelPos+4+2] = data[pixelPos+4+2] * 0.01 + fillB*0.99;\n\t\t\t\tdata[pixelPos+4+3] = data[pixelPos+4+3] * 0.01 + alpha*0.99;\n\t\t\t}\n\n\t\t\tif (!matchColor(pixelPos - 4)) {\n\t\t\t\tdata[pixelPos-4] = data[pixelPos-4] * 0.01 + fillR*0.99;\n\t\t\t\tdata[pixelPos-4+1] = data[pixelPos-4+1] * 0.01 + fillG*0.99;\n\t\t\t\tdata[pixelPos-4+2] = data[pixelPos-4+2] * 0.01 + fillB*0.99;\n\t\t\t\tdata[pixelPos-4+3] = data[pixelPos-4+3] * 0.01 + alpha*0.99;\n\t\t\t}\n\t\t}\n\n\t}\n\n\tdraw(mX, mY) {\n\t\tlet mouse = this.mouse;\n\t\tlet context = this.context;\n\n\t\t//calculate distance from previous point\n\t\tlet raw_dist = Atrament.lineDistance(mX, mY, mouse.px, mouse.py)\n\n\t\t//now, here we scale the initial smoothing factor by the raw distance\n\t\t//this means that when the mouse moves fast, there is more smoothing\n\t\t//and when we're drawing small detailed stuff, we have more control\n\t\t//also we hard clip at 1\n\t\tlet smoothingFactor = Math.min(0.87, this._smoothing + (raw_dist - 60) / 3000);\n\n\t\t//calculate smoothed coordinates\n\t\tmouse.x = mX - (mX - mouse.px) * smoothingFactor;\n\t\tmouse.y = mY - (mY - mouse.py) * smoothingFactor;\n\n\t\t//recalculate distance from previous point, this time relative to the smoothed coords\n\t\tlet dist = Atrament.lineDistance(mouse.x, mouse.y, mouse.px, mouse.py)\n\n\t\t//calculate target thickness based on the new distance\n\t\tthis._targetThickness = (dist - 1) / (50 - 1) * (this._maxWeight - this._weight) + this._weight;\n\t\t//approach the target gradually\n\t\tif (this._thickness > this._targetThickness) {\n\t\t\tthis._thickness -= 0.5;\n\t\t}\n\t\telse if (this._thickness < this._targetThickness) {\n\t\t\tthis._thickness += 0.5;\n\t\t}\n\t\t//set line width\n\t\tcontext.lineWidth = this._thickness;\n\n\t\t//draw using quad interpolation\n\t\tcontext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);\n\t\tcontext.stroke();\n\n\t\t//remember\n\t\tmouse.px = mouse.x;\n\t\tmouse.py = mouse.y;\n\t}\n\n\tget color() {\n\t\treturn this.context.strokeStyle;\n\t}\n\n\tset color(c) {\n\t\tif (typeof c !== 'string') throw new Error('wrong argument type');\n\t\tthis.context.strokeStyle = c;\n\t}\n\n\tget weight() {\n\t\treturn this._weight;\n\t}\n\n\tset weight(w) {\n\t\tif (typeof w !== 'number') throw new Error('wrong argument type');\n\t\tthis._weight = w;\n\t\tthis._thickness = w;\n\t\tthis._targetThickness = w;\n\t\tthis._maxWeight = w + this.WEIGHT_SPREAD;\n\t}\n\n\tget mode() {\n\t\treturn this._mode;\n\t}\n\n\tget dirty() {\n\t\treturn !!this._dirty;\n\t}\n\n\tset mode(m) {\n\t\tif (typeof m !== 'string') throw new Error('wrong argument type');\n\t\tswitch (m) {\n\t\t\tcase 'erase':\n\t\t\t\tthis._mode = 'erase';\n\t\t\t\tthis.context.globalCompositeOperation = 'destination-out';\n\t\t\t\tbreak;\n\t\t\tcase 'fill':\n\t\t\t\tthis._mode = 'fill';\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis._mode = 'draw';\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tget smoothing() {\n\t\treturn this._smoothing === this.SMOOTHING_INIT;\n\t}\n\n\tset smoothing(s) {\n\t\tif (typeof s !== 'boolean') throw new Error('wrong argument type');\n\t\tthis._smoothing = s ? this.SMOOTHING_INIT : 0;\n\t}\n\n\tset opacity(o) {\n\t\tif (typeof o !== 'number') throw new Error('wrong argument type');\n\t\t//now, we need to scale this, because our drawing method means we don't just get uniform transparency all over the drawn line.\n\t\t//so we scale it down a lot, meaning that it'll look nicely semi-transparent\n\t\t//unless opacity is 1, then we should go full on to 1\n\t\tif (o >= 1) this.context.globalAlpha = 1;\n\t\telse this.context.globalAlpha = o/10;\n\t}\n\n\tfireDirty() {\n\t\tconst event = document.createEvent('Event');\n\t\tevent.initEvent('dirty', true, true);\n\t\tthis.canvas.dispatchEvent(event);\n\t}\n\n\tclear() {\n\t\tif (!this.dirty) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._dirty = false;\n\t\tthis.fireDirty();\n\n\t\t//make sure we're in the right compositing mode, and erase everything\n\t\tif (this.context.globalCompositeOperation === 'destination-out') {\n\t\t\tthis.mode = 'draw';\n\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t\tthis.mode = 'erase';\n\t\t}\n\t\telse {\n\t\t\tthis.context.clearRect(-10, -10, this.canvas.width + 20, this.canvas.height + 20);\n\t\t}\n\t}\n\n\ttoImage() {\n\t\treturn this.canvas.toDataURL();\n\t}\n\n\tfill(){\n\t\tlet mouse = this.mouse;\n\t\tlet context = this.context;\n\t\tlet startColor = Array.prototype.slice.call(context.getImageData(mouse.x, mouse.y, 1, 1).data,0); //converting to Array because Safari 9\n\n\t\tif (!this._filling) {\n\t\t\tthis.canvas.style.cursor = 'progress';\n\t\t\tthis._filling = true;\n\n\t\t\tsetTimeout(() => { this._floodFill(mouse.x, mouse.y, startColor); }, 100);\n\t\t}\n\t\telse {\n\t\t\tthis._fillStack.push([\n\t\t\t\tmouse.x,\n\t\t\t\tmouse.y,\n\t\t\t\tstartColor\n\t\t\t]);\n\t\t}\n\t}\n\n\t_floodFill(startX, startY, startColor){\n\t\tlet context = this.context,\n\t\t\tcanvasWidth = context.canvas.width,\n\t\t\tcanvasHeight = context.canvas.height,\n\t\t\tpixelStack = [[startX, startY]],\n\t\t\t//hex needs to be trasformed to rgb since colorLayer accepts RGB\n\t\t\tfillColor = Atrament.hexToRgb(this.color),\n\t\t\t//Need to save current context with colors, we will update it\n\t\t\tcolorLayer = context.getImageData(0, 0, context.canvas.width, context.canvas.height),\n\t\t\talpha = Math.min(context.globalAlpha * 10 * 255, 255),\n\t\t\tcolorPixel = Atrament.colorPixel(colorLayer.data, ...fillColor, startColor, alpha),\n\t\t\tmatchColor = Atrament.matchColor(colorLayer.data, ...startColor);\n\n\t\tconst matchFillColor = Atrament.matchColor(colorLayer.data, ...[...fillColor, 255]);\n\t\t// check if we're trying to fill with the same colour, if so, stop\n\t\tif (matchFillColor((startY*context.canvas.width + startX) * 4)) {\n\t\t\tthis._filling = false;\n\t\t\tsetTimeout(() => { this.canvas.style.cursor = 'crosshair'; }, 100);\n\t\t\treturn;\n\t\t}\n\n\t\twhile(pixelStack.length) {\n\t\t\tlet newPos = pixelStack.pop();\n\t\t\tlet [x,y] = newPos;\n\n\t\t\tlet pixelPos = (y*canvasWidth + x) * 4;\n\n\t\t\twhile(y-- >= 0 && matchColor(pixelPos))\n\t\t\t{\n\t\t\t\tpixelPos -= canvasWidth * 4;\n\t\t\t}\n\t\t\tpixelPos += canvasWidth * 4;\n\n\t\t\t++y;\n\n\t\t\tlet reachLeft = false;\n\t\t\tlet reachRight = false;\n\n\t\t\twhile(y++ < canvasHeight-1 && matchColor(pixelPos))\n\t\t\t{\n\t\t\t\tcolorPixel(pixelPos);\n\n\t\t\t\tif(x > 0)\n\t\t\t\t{\n\t\t\t\t\tif(matchColor(pixelPos - 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!reachLeft){\n\t\t\t\t\t\t\tpixelStack.push([x - 1, y]);\n\t\t\t\t\t\t\treachLeft = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(reachLeft)\n\t\t\t\t\t{\n\t\t\t\t\t\treachLeft = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(x < canvasWidth-1)\n\t\t\t\t{\n\t\t\t\t\tif(matchColor(pixelPos + 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!reachRight)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpixelStack.push([x + 1, y]);\n\t\t\t\t\t\t\treachRight = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(reachRight)\n\t\t\t\t\t{\n\t\t\t\t\t\treachRight = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpixelPos += canvasWidth * 4;\n\t\t\t}\n\t\t}\n\n\t\t//Update context with filled bucket!\n\t\tcontext.putImageData(colorLayer, 0, 0);\n\n\t\tif (this._fillStack.length) {\n\t\t\tthis._floodFill(...this._fillStack.shift());\n\t\t}\n\t\telse {\n\t\t\tthis._filling = false;\n\t\t\tsetTimeout(() => { this.canvas.style.cursor = 'crosshair'; }, 100);\n\t\t}\n\n\t}\n\n}\n\n//for people who like functional programming\nfunction atrament(selector, width, height, color) {\n\treturn new Atrament(selector, width, height, color);\n}\n\nmodule.exports = atrament;\nmodule.exports.Atrament = Atrament;\n\n\n\n// WEBPACK FOOTER //\n// ./src/atrament.js"],"sourceRoot":""} \ No newline at end of file diff --git a/src/atrament.js b/src/atrament.js index 0a4acdb..98d305d 100755 --- a/src/atrament.js +++ b/src/atrament.js @@ -150,7 +150,6 @@ class Atrament { this.context.moveTo(this.mouse.px, this.mouse.py); } let mouseUp = (mousePosition) => { - mousePosition.preventDefault(); this.mouse.down = false; //stop drawing this.context.closePath();