Comparing version 1.1.2 to 1.2.2
/*! | ||
instacam – Instant canvas video | ||
Xavier Foucrier @xavierfoucrier 2018 MIT | ||
1.1.2 | ||
1.2.2 | ||
*/ | ||
@@ -124,3 +124,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
"use strict"; | ||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Instacam\", function() { return Instacam; });\n/* harmony import */ var _defaults_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./defaults.js */ \"./src/defaults.js\");\n/* harmony import */ var _support_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./support.js */ \"./src/support.js\");\n\n\n\n\n\nclass Instacam {\n\n /**\n Class constructor\n @param {Object} viewport - selector or canvas element from the DOM\n @param {Object} options - custom options of the class\n */\n constructor(viewport, options) {\n\n // assigns custom user options to defaults\n this.options = Object.assign({}, _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"], options);\n\n // checks for browser support\n if (!_support_js__WEBPACK_IMPORTED_MODULE_1__[\"requirement\"]) {\n if (typeof this.options.unsupported === 'function') {\n this.options.unsupported();\n }\n\n return;\n }\n\n // rewrites the viewport element if the user passed a selector to the constructor\n if (typeof viewport === 'string') {\n viewport = document.querySelector(viewport);\n }\n\n // checks the viewport element\n if (typeof viewport === 'undefined' || viewport === null || viewport.nodeName.toLowerCase() !== 'canvas') {\n throw new Error('Invalid viewport, you need to pass a valid selector or HTML5 canvas element');\n }\n\n // initializes the viewport\n this.viewport = viewport;\n this.viewport.width = this.options.width;\n this.viewport.height = this.options.height;\n\n // creates the media element\n this.media = document.createElement('video');\n\n // sets some media element properties\n this.media.style.display = 'none';\n this.media.autoplay = true;\n this.media.width = this.options.width;\n this.media.height = this.options.height;\n\n // attaches the media element to the DOM\n this.viewport.parentNode.insertBefore(this.media, this.viewport.nextSibling);\n\n // applies the css mirror mode on the viewport\n this.mirror = this.options.mirror;\n\n // computes the css filter options\n this._compute();\n\n // captures the webcam stream\n this._capture();\n }\n\n /**\n Captures the media stream to the viewport through getUserMedia API\n */\n _capture() {\n\n // prevents from streaming errors\n try {\n\n // captures the media stream\n navigator.mediaDevices.getUserMedia({\n audio: this.options.sound,\n video: (() => {\n if (this.options.camera === false) {\n return false;\n }\n\n return {\n frameRate: this.options.framerate,\n aspectRatio: this.options.ratio\n };\n })()\n }).then((stream) => {\n\n // captures the blob stream\n this.media.srcObject = stream;\n\n // sets the volume at start\n this.volume = this.options.volume;\n\n // animation loop used to properly render the viewport\n const loop = () => {\n\n // renders the viewport with or without custom filter\n if (typeof this.options.filter !== 'function') {\n this.viewport.getContext('2d').drawImage(this.media, 0, 0, this.options.width, this.options.height);\n } else {\n\n // uses a buffer when applying a custom filter to prevent the viewport from blinkings or flashes\n if (typeof this._buffer === 'undefined') {\n this._buffer = document.createElement('canvas');\n this._buffer.style.display = 'none';\n this._buffer.width = this.options.width;\n this._buffer.height = this.options.height;\n this.viewport.parentNode.insertBefore(this._buffer, this.viewport.nextSibling);\n }\n\n this._buffer.getContext('2d').drawImage(this.media, 0, 0, this.options.width, this.options.height);\n this.viewport.getContext('2d').putImageData(this._filter(this._buffer.getContext('2d').getImageData(0, 0, this.options.width, this.options.height)), 0, 0);\n }\n\n // makes this function run at 60fps\n requestAnimationFrame(loop);\n };\n\n // renders the first frame\n requestAnimationFrame(loop);\n\n if (typeof this.options.done === 'function') {\n this.options.done();\n }\n }).catch((exception) => {\n if (typeof this.options.fail === 'function') {\n this.options.fail(exception);\n }\n });\n } catch(exception) {\n if (typeof this.options.fail === 'function') {\n this.options.fail(exception);\n }\n }\n }\n\n /**\n Computes and applies the css filter effects to the viewport\n */\n _compute() {\n\n // builds the css layer depending on the options\n this._style = this.options.opacity !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].opacity ? `opacity(${this.options.opacity}) ` : '';\n this._style += this.options.brightness !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].brightness ? `brightness(${this.options.brightness}) ` : '';\n this._style += this.options.contrast !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].contrast ? `contrast(${this.options.contrast}) ` : '';\n this._style += this.options.saturation !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].saturation ? `saturate(${this.options.saturation}) ` : '';\n this._style += this.options.hue !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].hue ? `hue-rotate(${this.options.hue}deg) ` : '';\n this._style += this.options.invert !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].invert ? `invert(${this.options.invert}) ` : '';\n this._style += this.options.grayscale !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].grayscale ? `grayscale(${this.options.grayscale}) ` : '';\n this._style += this.options.sepia !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].sepia ? `sepia(${this.options.sepia}) ` : '';\n this._style += this.options.blur !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].blur ? `blur(${this.options.blur}px) ` : '';\n this._style += this.options.url !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].url ? `url(${this.options.url}) ` : '';\n\n // applies the css filter effects to the viewport\n this.viewport.style.filter = this._style;\n }\n\n /**\n Applies a custom filter to the viewport\n @param {Object} image - image object from the canvas element\n @returns {Object} image data object containing pixels informations\n */\n _filter(image) {\n\n // gets the image data\n let data = image.data;\n\n // prevents from filtering errors\n try {\n\n // loops through all pixels and applies the filter\n for (let y = 0; y < this.options.height; y++) {\n for (let x = 0; x < this.options.width; x++) {\n\n // detects the pixel offset\n const offset = ((this.options.width * y) + x) * 4;\n\n // calls the filter\n const filter = this.options.filter({\n 'offset': offset,\n 'x': x,\n 'y': y,\n 'red': data[offset],\n 'green': data[offset + 1],\n 'blue': data[offset + 2],\n 'alpha': data[offset + 3]\n });\n\n // applies the filter\n data[offset] = filter[0];\n data[offset + 1] = filter[1];\n data[offset + 2] = filter[2];\n data[offset + 3] = filter[3];\n }\n }\n\n return image;\n } catch(exception) {\n throw new Error('Invalid filter, you need to return a valid [red, green, blue, alpha] pixel array');\n }\n }\n\n /**\n Snaps and crops the viewport to return image data\n @param {Number} left - left position of the snapping area\n @param {Number} top - top position of the snapping area\n @param {Number} width - width of the snapping area\n @param {Number} height - height of the snapping area\n @returns {Object} image data object containing pixels informations\n */\n snap(left = 0, top = 0, width = this.options.width, height = this.options.height) {\n\n // checks the snap size area\n if (width <= 0 || height <= 0) {\n throw new Error('Invalid snap area, you need to specify a positive width and height for your image capture');\n }\n\n return this.viewport.getContext('2d').getImageData(left, top, width, height);\n }\n\n /**\n Saves the viewport to a specific image file format\n @param {String} format - png|jpeg|webp image file format\n @param {Number} quality - [0..1] image quality\n @returns {String} UTF-16 data image URI (DOMString)\n */\n save(format = 'png', quality = 1) {\n return this.viewport.toDataURL('image/' + format, quality);\n }\n\n /**\n Gets the camera volume\n @returns {Number} [0..100] volume of the camera audio stream\n */\n get volume() {\n return this.options.volume;\n }\n\n /**\n Sets the camera volume\n @param {Number} volume - [0..100] volume of the camera audio stream\n */\n set volume(volume) {\n if (typeof volume !== 'number' || volume < 0 || volume > 100) {\n throw new Error('Invalid volume, you need to give a number between 0 and 100');\n }\n\n this.media.volume = this.options.volume = volume / 100;\n }\n\n /**\n Gets the camera mirror mode\n @returns {Boolean} true|false, mirror mode of the viewport (css transform)\n */\n get mirror() {\n return this.options.mirror;\n }\n\n /**\n Sets the camera mirror mode\n @param {Boolean} mirror - true|false, mirror mode of the viewport (css transform)\n */\n set mirror(mirror) {\n if (typeof mirror !== 'boolean') {\n throw new Error('Invalid mirror mode, you need to give a boolean to enable or disable the mirror mode');\n }\n\n let transform = getComputedStyle(this.viewport).getPropertyValue('transform');\n transform = transform !== 'none' ? transform : '';\n\n this.viewport.style.transform = mirror === true ? `${transform} scale(-1, 1)` : '';\n this.options.mirror = mirror;\n }\n\n /**\n Gets the viewport opacity\n @returns {Number} [0..1] opacity of the viewport (css)\n */\n get opacity() {\n return this.options.opacity;\n }\n\n /**\n Sets the viewport opacity\n @param {Number} opacity - [0..1] opacity of the viewport (css)\n */\n set opacity(opacity) {\n if (typeof opacity !== 'number' || opacity < 0 || opacity > 1) {\n throw new Error('Invalid opacity, you need to give a number between 0 and 1');\n }\n\n this.options.opacity = opacity;\n this._compute();\n }\n\n /**\n Gets the viewport brightness\n @returns {Number} [0..*] brightness of the viewport (css filter)\n */\n get brightness() {\n return this.options.brightness;\n }\n\n /**\n Sets the viewport brightness\n @param {Number} brightness - [0..*] brightness of the viewport (css filter)\n */\n set brightness(brightness) {\n if (typeof brightness !== 'number' || brightness < 0) {\n throw new Error('Invalid brightness, you need to give a number above 0');\n }\n\n this.options.brightness = brightness;\n this._compute();\n }\n\n /**\n Gets the viewport contrast\n @returns {Number} [0..*] contrast of the viewport (css filter)\n */\n get contrast() {\n return this.options.contrast;\n }\n\n /**\n Sets the viewport contrast\n @param {Number} contrast - [0..*] contrast of the viewport (css filter)\n */\n set contrast(contrast) {\n if (typeof contrast !== 'number' || contrast < 0) {\n throw new Error('Invalid contrast, you need to give a number above 0');\n }\n\n this.options.contrast = contrast;\n this._compute();\n }\n\n /**\n Gets the viewport saturation\n @returns {Number} [0..*] saturation of the viewport (css filter)\n */\n get saturation() {\n return this.options.saturation;\n }\n\n /**\n Sets the viewport saturation\n @param {Number} saturation - [0..*] saturation of the viewport (css filter)\n */\n set saturation(saturation) {\n if (typeof saturation !== 'number' || saturation < 0) {\n throw new Error('Invalid saturation, you need to give a number above 0');\n }\n\n this.options.saturation = saturation;\n this._compute();\n }\n\n /**\n Gets the viewport hue\n @returns {Number} [0..360] hue of the viewport (css filter)\n */\n get hue() {\n return this.options.hue;\n }\n\n /**\n Sets the viewport hue\n @param {Number} hue - [0..360] hue of the viewport (css filter)\n */\n set hue(hue) {\n if (typeof hue !== 'number' || hue < 0 || hue > 360) {\n throw new Error('Invalid hue, you need to give a number between 0 and 360');\n }\n\n this.options.hue = hue;\n this._compute();\n }\n\n /**\n Gets the viewport color inversion\n @returns {Number} [0..1] inverts the color of the viewport (css filter)\n */\n get invert() {\n return this.options.invert;\n }\n\n /**\n Sets the viewport color inversion\n @param {Number} invert - [0..1] inverts the color of the viewport (css filter)\n */\n set invert(invert) {\n if (typeof invert !== 'number' || invert < 0 || invert > 1) {\n throw new Error('Invalid invert, you need to give a number between 0 and 1');\n }\n\n this.options.invert = invert;\n this._compute();\n }\n\n /**\n Gets the viewport grayscale\n @returns {Number} [0..1] grayscale of the viewport (css filter)\n */\n get grayscale() {\n return this.options.grayscale;\n }\n\n /**\n Sets the viewport grayscale\n @param {Number} grayscale - [0..1] grayscale of the viewport (css filter)\n */\n set grayscale(grayscale) {\n if (typeof grayscale !== 'number' || grayscale < 0 || grayscale > 1) {\n throw new Error('Invalid grayscale, you need to give a number between 0 and 1');\n }\n\n this.options.grayscale = grayscale;\n this._compute();\n }\n\n /**\n Gets the viewport sepia\n @returns {Number} [0..1] sepia of the viewport (css filter)\n */\n get sepia() {\n return this.options.sepia;\n }\n\n /**\n Sets the viewport sepia\n @param {Number} sepia - [0..1] sepia of the viewport (css filter)\n */\n set sepia(sepia) {\n if (typeof sepia !== 'number' || sepia < 0 || sepia > 1) {\n throw new Error('Invalid sepia, you need to give a number between 0 and 1');\n }\n\n this.options.sepia = sepia;\n this._compute();\n }\n\n /**\n Gets the viewport blur\n @returns {Number} [0..*] blur of the viewport (css filter)\n */\n get blur() {\n return this.options.blur;\n }\n\n /**\n Sets the viewport blur\n @param {Number} blur - [0..*] blur of the viewport (css filter)\n */\n set blur(blur) {\n if (typeof blur !== 'number' || blur < 0) {\n throw new Error('Invalid blur, you need to give a number above 0');\n }\n\n this.options.blur = blur;\n this._compute();\n }\n\n /**\n Gets the viewport svg filtering\n @returns {String} svg filtering of the viewport (css filter)\n */\n get url() {\n return this.options.url;\n }\n\n /**\n Sets the viewport svg filtering\n @param {String} url - svg filtering of the viewport (css filter)\n */\n set url(url) {\n if (typeof url !== 'string') {\n throw new Error('Invalid url, you need to give a string');\n }\n\n this.options.url = url;\n this._compute();\n }\n\n /**\n Gets the custom filter\n @returns {Function} custom filter of the viewport\n */\n get filter() {\n return this.options.filter;\n }\n\n /**\n Sets the custom filter\n @param {Function} filter - custom filter applied to the viewport\n */\n set filter(filter) {\n if (filter !== null && typeof filter !== 'function') {\n throw new Error('Invalid filter, you need to give a function or null to disable the custom filtering');\n }\n\n this.options.filter = filter;\n }\n}\n\n\n//# sourceURL=webpack://Instacam/./src/instacam.js?"); | ||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Instacam\", function() { return Instacam; });\n/* harmony import */ var _defaults_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./defaults.js */ \"./src/defaults.js\");\n/* harmony import */ var _support_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./support.js */ \"./src/support.js\");\n\n\n\n\n\nclass Instacam {\n\n /**\n Class constructor\n @param {Object} viewport - selector or canvas element from the DOM\n @param {Object} options - custom options of the class\n */\n constructor(viewport, options) {\n\n // assigns custom user options to defaults\n this._options = Object.assign({}, _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"], options);\n\n // checks for browser support\n if (!_support_js__WEBPACK_IMPORTED_MODULE_1__[\"requirement\"]) {\n if (typeof this._options.unsupported === 'function') {\n this._options.unsupported();\n }\n\n return;\n }\n\n // rewrites the viewport element if the user passed a selector to the constructor\n if (typeof viewport === 'string') {\n viewport = document.querySelector(viewport);\n }\n\n // checks the viewport element\n if (typeof viewport === 'undefined' || viewport === null || viewport.nodeName.toLowerCase() !== 'canvas') {\n throw new Error('Invalid viewport, you need to pass a valid selector or HTML5 canvas element');\n }\n\n // initializes the viewport\n this.viewport = viewport;\n this.viewport.width = this._options.width;\n this.viewport.height = this._options.height;\n\n // creates the media element\n this.media = document.createElement('video');\n\n // sets some media element properties\n this.media.style.display = 'none';\n this.media.autoplay = true;\n this.media.width = this._options.width;\n this.media.height = this._options.height;\n\n // attaches the media element to the DOM\n this.viewport.parentNode.insertBefore(this.media, this.viewport.nextSibling);\n\n // applies the css mirror mode on the viewport\n this.mirror = this._options.mirror;\n\n // computes the css filter options\n this._compute();\n\n // captures the webcam stream\n this._capture();\n }\n\n /**\n Captures the media stream to the viewport through getUserMedia API\n */\n _capture() {\n\n // prevents from streaming errors\n try {\n\n // captures the media stream\n navigator.mediaDevices.getUserMedia({\n audio: this._options.sound,\n video: (() => {\n if (this._options.camera === false) {\n return false;\n }\n\n return {\n frameRate: this._options.framerate,\n aspectRatio: this._options.ratio\n };\n })()\n }).then((stream) => {\n\n // captures the blob stream\n this.media.srcObject = stream;\n\n // sets the volume at start\n this.volume = this._options.volume;\n\n // animation loop used to properly render the viewport\n const loop = () => {\n\n // renders the viewport with or without custom filter\n if (typeof this._options.filter !== 'function') {\n this.viewport.getContext('2d').drawImage(this.media, 0, 0, this._options.width, this._options.height);\n } else {\n\n // uses a buffer when applying a custom filter to prevent the viewport from blinkings or flashes\n if (typeof this._buffer === 'undefined') {\n this._buffer = document.createElement('canvas');\n this._buffer.style.display = 'none';\n this._buffer.width = this._options.width;\n this._buffer.height = this._options.height;\n this.viewport.parentNode.insertBefore(this._buffer, this.viewport.nextSibling);\n }\n\n this._buffer.getContext('2d').drawImage(this.media, 0, 0, this._options.width, this._options.height);\n this.viewport.getContext('2d').putImageData(this._filter(this._buffer.getContext('2d').getImageData(0, 0, this._options.width, this._options.height)), 0, 0);\n }\n\n // makes this function run at 60fps\n requestAnimationFrame(loop);\n };\n\n // renders the first frame\n requestAnimationFrame(loop);\n\n if (typeof this._options.done === 'function') {\n this._options.done();\n }\n }).catch((exception) => {\n if (typeof this._options.fail === 'function') {\n this._options.fail(exception);\n }\n });\n } catch(exception) {\n if (typeof this._options.fail === 'function') {\n this._options.fail(exception);\n }\n }\n }\n\n /**\n Computes and applies the css filter effects to the viewport\n */\n _compute() {\n\n // builds the css layer depending on the options\n this._style = this._options.opacity !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].opacity ? `opacity(${this._options.opacity}) ` : '';\n this._style += this._options.brightness !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].brightness ? `brightness(${this._options.brightness}) ` : '';\n this._style += this._options.contrast !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].contrast ? `contrast(${this._options.contrast}) ` : '';\n this._style += this._options.saturation !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].saturation ? `saturate(${this._options.saturation}) ` : '';\n this._style += this._options.hue !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].hue ? `hue-rotate(${this._options.hue}deg) ` : '';\n this._style += this._options.invert !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].invert ? `invert(${this._options.invert}) ` : '';\n this._style += this._options.grayscale !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].grayscale ? `grayscale(${this._options.grayscale}) ` : '';\n this._style += this._options.sepia !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].sepia ? `sepia(${this._options.sepia}) ` : '';\n this._style += this._options.blur !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].blur ? `blur(${this._options.blur}px) ` : '';\n this._style += this._options.url !== _defaults_js__WEBPACK_IMPORTED_MODULE_0__[\"defaults\"].url ? `url(${this._options.url}) ` : '';\n\n // applies the css filter effects to the viewport\n this.viewport.style.filter = this._style;\n }\n\n /**\n Applies a custom filter to the viewport\n @param {Object} image - image object from the canvas element\n @returns {Object} image data object containing pixels informations\n */\n _filter(image) {\n\n // gets the image data\n let data = image.data;\n\n // prevents from filtering errors\n try {\n\n // loops through all pixels and applies the filter\n for (let y = 0; y < this._options.height; y++) {\n for (let x = 0; x < this._options.width; x++) {\n\n // detects the pixel offset\n const offset = ((this._options.width * y) + x) * 4;\n\n // calls the filter\n const filter = this._options.filter({\n 'offset': offset,\n 'x': x,\n 'y': y,\n 'red': data[offset],\n 'green': data[offset + 1],\n 'blue': data[offset + 2],\n 'alpha': data[offset + 3]\n });\n\n // applies the filter\n data[offset] = filter[0];\n data[offset + 1] = filter[1];\n data[offset + 2] = filter[2];\n data[offset + 3] = filter[3];\n }\n }\n\n return image;\n } catch(exception) {\n throw new Error('Invalid filter, you need to return a valid [red, green, blue, alpha] pixel array');\n }\n }\n\n /**\n Snaps and crops the viewport to return image data\n @param {Number} left - left position of the snapping area\n @param {Number} top - top position of the snapping area\n @param {Number} width - width of the snapping area\n @param {Number} height - height of the snapping area\n @returns {Object} image data object containing pixels informations\n */\n snap(left = 0, top = 0, width = this._options.width, height = this._options.height) {\n\n // checks the snap size area\n if (width <= 0 || height <= 0) {\n throw new Error('Invalid snap area, you need to specify a positive width and height for your image capture');\n }\n\n return this.viewport.getContext('2d').getImageData(left, top, width, height);\n }\n\n /**\n Saves the viewport to a specific image file format\n @param {String} format - png|jpeg|webp image file format\n @param {Number} quality - [0..1] image quality\n @returns {String} UTF-16 data image URI (DOMString)\n */\n save(format = 'png', quality = 1) {\n return this.viewport.toDataURL('image/' + format, quality);\n }\n\n /**\n Gets the camera volume\n @returns {Number} [0..100] volume of the camera audio stream\n */\n get volume() {\n return this._options.volume;\n }\n\n /**\n Sets the camera volume\n @param {Number} volume - [0..100] volume of the camera audio stream\n */\n set volume(volume) {\n if (typeof volume !== 'number' || volume < 0 || volume > 100) {\n throw new Error('Invalid volume, you need to give a number between 0 and 100');\n }\n\n this.media.volume = this._options.volume = volume / 100;\n }\n\n /**\n Gets the camera mirror mode\n @returns {Boolean} true|false, mirror mode of the viewport (css transform)\n */\n get mirror() {\n return this._options.mirror;\n }\n\n /**\n Sets the camera mirror mode\n @param {Boolean} mirror - true|false, mirror mode of the viewport (css transform)\n */\n set mirror(mirror) {\n if (typeof mirror !== 'boolean') {\n throw new Error('Invalid mirror mode, you need to give a boolean to enable or disable the mirror mode');\n }\n\n let transform = getComputedStyle(this.viewport).getPropertyValue('transform');\n transform = transform !== 'none' ? transform : '';\n\n this.viewport.style.transform = mirror === true ? `${transform} scale(-1, 1)` : '';\n this._options.mirror = mirror;\n }\n\n /**\n Gets the viewport opacity\n @returns {Number} [0..1] opacity of the viewport (css)\n */\n get opacity() {\n return this._options.opacity;\n }\n\n /**\n Sets the viewport opacity\n @param {Number} opacity - [0..1] opacity of the viewport (css)\n */\n set opacity(opacity) {\n if (typeof opacity !== 'number' || opacity < 0 || opacity > 1) {\n throw new Error('Invalid opacity, you need to give a number between 0 and 1');\n }\n\n this._options.opacity = opacity;\n this._compute();\n }\n\n /**\n Gets the viewport brightness\n @returns {Number} [0..*] brightness of the viewport (css filter)\n */\n get brightness() {\n return this._options.brightness;\n }\n\n /**\n Sets the viewport brightness\n @param {Number} brightness - [0..*] brightness of the viewport (css filter)\n */\n set brightness(brightness) {\n if (typeof brightness !== 'number' || brightness < 0) {\n throw new Error('Invalid brightness, you need to give a number above 0');\n }\n\n this._options.brightness = brightness;\n this._compute();\n }\n\n /**\n Gets the viewport contrast\n @returns {Number} [0..*] contrast of the viewport (css filter)\n */\n get contrast() {\n return this._options.contrast;\n }\n\n /**\n Sets the viewport contrast\n @param {Number} contrast - [0..*] contrast of the viewport (css filter)\n */\n set contrast(contrast) {\n if (typeof contrast !== 'number' || contrast < 0) {\n throw new Error('Invalid contrast, you need to give a number above 0');\n }\n\n this._options.contrast = contrast;\n this._compute();\n }\n\n /**\n Gets the viewport saturation\n @returns {Number} [0..*] saturation of the viewport (css filter)\n */\n get saturation() {\n return this._options.saturation;\n }\n\n /**\n Sets the viewport saturation\n @param {Number} saturation - [0..*] saturation of the viewport (css filter)\n */\n set saturation(saturation) {\n if (typeof saturation !== 'number' || saturation < 0) {\n throw new Error('Invalid saturation, you need to give a number above 0');\n }\n\n this._options.saturation = saturation;\n this._compute();\n }\n\n /**\n Gets the viewport hue\n @returns {Number} [0..360] hue of the viewport (css filter)\n */\n get hue() {\n return this._options.hue;\n }\n\n /**\n Sets the viewport hue\n @param {Number} hue - [0..360] hue of the viewport (css filter)\n */\n set hue(hue) {\n if (typeof hue !== 'number' || hue < 0 || hue > 360) {\n throw new Error('Invalid hue, you need to give a number between 0 and 360');\n }\n\n this._options.hue = hue;\n this._compute();\n }\n\n /**\n Gets the viewport color inversion\n @returns {Number} [0..1] inverts the color of the viewport (css filter)\n */\n get invert() {\n return this._options.invert;\n }\n\n /**\n Sets the viewport color inversion\n @param {Number} invert - [0..1] inverts the color of the viewport (css filter)\n */\n set invert(invert) {\n if (typeof invert !== 'number' || invert < 0 || invert > 1) {\n throw new Error('Invalid invert, you need to give a number between 0 and 1');\n }\n\n this._options.invert = invert;\n this._compute();\n }\n\n /**\n Gets the viewport grayscale\n @returns {Number} [0..1] grayscale of the viewport (css filter)\n */\n get grayscale() {\n return this._options.grayscale;\n }\n\n /**\n Sets the viewport grayscale\n @param {Number} grayscale - [0..1] grayscale of the viewport (css filter)\n */\n set grayscale(grayscale) {\n if (typeof grayscale !== 'number' || grayscale < 0 || grayscale > 1) {\n throw new Error('Invalid grayscale, you need to give a number between 0 and 1');\n }\n\n this._options.grayscale = grayscale;\n this._compute();\n }\n\n /**\n Gets the viewport sepia\n @returns {Number} [0..1] sepia of the viewport (css filter)\n */\n get sepia() {\n return this._options.sepia;\n }\n\n /**\n Sets the viewport sepia\n @param {Number} sepia - [0..1] sepia of the viewport (css filter)\n */\n set sepia(sepia) {\n if (typeof sepia !== 'number' || sepia < 0 || sepia > 1) {\n throw new Error('Invalid sepia, you need to give a number between 0 and 1');\n }\n\n this._options.sepia = sepia;\n this._compute();\n }\n\n /**\n Gets the viewport blur\n @returns {Number} [0..*] blur of the viewport (css filter)\n */\n get blur() {\n return this._options.blur;\n }\n\n /**\n Sets the viewport blur\n @param {Number} blur - [0..*] blur of the viewport (css filter)\n */\n set blur(blur) {\n if (typeof blur !== 'number' || blur < 0) {\n throw new Error('Invalid blur, you need to give a number above 0');\n }\n\n this._options.blur = blur;\n this._compute();\n }\n\n /**\n Gets the viewport svg filtering\n @returns {String} svg filtering of the viewport (css filter)\n */\n get url() {\n return this._options.url;\n }\n\n /**\n Sets the viewport svg filtering\n @param {String} url - svg filtering of the viewport (css filter)\n */\n set url(url) {\n if (typeof url !== 'string') {\n throw new Error('Invalid url, you need to give a string');\n }\n\n this._options.url = url;\n this._compute();\n }\n\n /**\n Gets the custom filter\n @returns {Function} custom filter of the viewport\n */\n get filter() {\n return this._options.filter;\n }\n\n /**\n Sets the custom filter\n @param {Function} filter - custom filter applied to the viewport\n */\n set filter(filter) {\n if (filter !== null && typeof filter !== 'function') {\n throw new Error('Invalid filter, you need to give a function or null to disable the custom filtering');\n }\n\n this._options.filter = filter;\n }\n}\n\n\n//# sourceURL=webpack://Instacam/./src/instacam.js?"); | ||
@@ -127,0 +127,0 @@ /***/ }), |
/*! | ||
instacam – Instant canvas video | ||
Xavier Foucrier @xavierfoucrier 2018 MIT | ||
1.1.2 | ||
1.2.2 | ||
*/ | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("Instacam",[],e):"object"==typeof exports?exports.Instacam=e():t.Instacam=e()}(window,function(){return function(t){var e={};function i(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=e,i.d=function(t,e,o){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)i.d(o,r,function(e){return t[e]}.bind(null,r));return o},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,i){"use strict";i.r(e);let o={width:400,height:300,camera:!0,framerate:30,ratio:4/3,sound:!1,volume:100,mirror:!1,opacity:1,brightness:1,contrast:1,saturation:1,hue:0,invert:0,grayscale:0,sepia:0,blur:0,url:"",filter:null,done:null,fail:null,unsupported:null},r="requestAnimationFrame"in window&&"mediaDevices"in navigator&&"Promise"in window;i.d(e,"Instacam",function(){return n});class n{constructor(t,e){if(this.options=Object.assign({},o,e),r){if("string"==typeof t&&(t=document.querySelector(t)),void 0===t||null===t||"canvas"!==t.nodeName.toLowerCase())throw new Error("Invalid viewport, you need to pass a valid selector or HTML5 canvas element");this.viewport=t,this.viewport.width=this.options.width,this.viewport.height=this.options.height,this.media=document.createElement("video"),this.media.style.display="none",this.media.autoplay=!0,this.media.width=this.options.width,this.media.height=this.options.height,this.viewport.parentNode.insertBefore(this.media,this.viewport.nextSibling),this.mirror=this.options.mirror,this._compute(),this._capture()}else"function"==typeof this.options.unsupported&&this.options.unsupported()}_capture(){try{navigator.mediaDevices.getUserMedia({audio:this.options.sound,video:(()=>!1!==this.options.camera&&{frameRate:this.options.framerate,aspectRatio:this.options.ratio})()}).then(t=>{this.media.srcObject=t,this.volume=this.options.volume;const e=()=>{"function"!=typeof this.options.filter?this.viewport.getContext("2d").drawImage(this.media,0,0,this.options.width,this.options.height):(void 0===this._buffer&&(this._buffer=document.createElement("canvas"),this._buffer.style.display="none",this._buffer.width=this.options.width,this._buffer.height=this.options.height,this.viewport.parentNode.insertBefore(this._buffer,this.viewport.nextSibling)),this._buffer.getContext("2d").drawImage(this.media,0,0,this.options.width,this.options.height),this.viewport.getContext("2d").putImageData(this._filter(this._buffer.getContext("2d").getImageData(0,0,this.options.width,this.options.height)),0,0)),requestAnimationFrame(e)};requestAnimationFrame(e),"function"==typeof this.options.done&&this.options.done()}).catch(t=>{"function"==typeof this.options.fail&&this.options.fail(t)})}catch(t){"function"==typeof this.options.fail&&this.options.fail(t)}}_compute(){this._style=this.options.opacity!==o.opacity?`opacity(${this.options.opacity}) `:"",this._style+=this.options.brightness!==o.brightness?`brightness(${this.options.brightness}) `:"",this._style+=this.options.contrast!==o.contrast?`contrast(${this.options.contrast}) `:"",this._style+=this.options.saturation!==o.saturation?`saturate(${this.options.saturation}) `:"",this._style+=this.options.hue!==o.hue?`hue-rotate(${this.options.hue}deg) `:"",this._style+=this.options.invert!==o.invert?`invert(${this.options.invert}) `:"",this._style+=this.options.grayscale!==o.grayscale?`grayscale(${this.options.grayscale}) `:"",this._style+=this.options.sepia!==o.sepia?`sepia(${this.options.sepia}) `:"",this._style+=this.options.blur!==o.blur?`blur(${this.options.blur}px) `:"",this._style+=this.options.url!==o.url?`url(${this.options.url}) `:"",this.viewport.style.filter=this._style}_filter(t){let e=t.data;try{for(let t=0;t<this.options.height;t++)for(let i=0;i<this.options.width;i++){const o=4*(this.options.width*t+i),r=this.options.filter({offset:o,x:i,y:t,red:e[o],green:e[o+1],blue:e[o+2],alpha:e[o+3]});e[o]=r[0],e[o+1]=r[1],e[o+2]=r[2],e[o+3]=r[3]}return t}catch(t){throw new Error("Invalid filter, you need to return a valid [red, green, blue, alpha] pixel array")}}snap(t=0,e=0,i=this.options.width,o=this.options.height){if(i<=0||o<=0)throw new Error("Invalid snap area, you need to specify a positive width and height for your image capture");return this.viewport.getContext("2d").getImageData(t,e,i,o)}save(t="png",e=1){return this.viewport.toDataURL("image/"+t,e)}get volume(){return this.options.volume}set volume(t){if("number"!=typeof t||t<0||t>100)throw new Error("Invalid volume, you need to give a number between 0 and 100");this.media.volume=this.options.volume=t/100}get mirror(){return this.options.mirror}set mirror(t){if("boolean"!=typeof t)throw new Error("Invalid mirror mode, you need to give a boolean to enable or disable the mirror mode");let e=getComputedStyle(this.viewport).getPropertyValue("transform");e="none"!==e?e:"",this.viewport.style.transform=!0===t?`${e} scale(-1, 1)`:"",this.options.mirror=t}get opacity(){return this.options.opacity}set opacity(t){if("number"!=typeof t||t<0||t>1)throw new Error("Invalid opacity, you need to give a number between 0 and 1");this.options.opacity=t,this._compute()}get brightness(){return this.options.brightness}set brightness(t){if("number"!=typeof t||t<0)throw new Error("Invalid brightness, you need to give a number above 0");this.options.brightness=t,this._compute()}get contrast(){return this.options.contrast}set contrast(t){if("number"!=typeof t||t<0)throw new Error("Invalid contrast, you need to give a number above 0");this.options.contrast=t,this._compute()}get saturation(){return this.options.saturation}set saturation(t){if("number"!=typeof t||t<0)throw new Error("Invalid saturation, you need to give a number above 0");this.options.saturation=t,this._compute()}get hue(){return this.options.hue}set hue(t){if("number"!=typeof t||t<0||t>360)throw new Error("Invalid hue, you need to give a number between 0 and 360");this.options.hue=t,this._compute()}get invert(){return this.options.invert}set invert(t){if("number"!=typeof t||t<0||t>1)throw new Error("Invalid invert, you need to give a number between 0 and 1");this.options.invert=t,this._compute()}get grayscale(){return this.options.grayscale}set grayscale(t){if("number"!=typeof t||t<0||t>1)throw new Error("Invalid grayscale, you need to give a number between 0 and 1");this.options.grayscale=t,this._compute()}get sepia(){return this.options.sepia}set sepia(t){if("number"!=typeof t||t<0||t>1)throw new Error("Invalid sepia, you need to give a number between 0 and 1");this.options.sepia=t,this._compute()}get blur(){return this.options.blur}set blur(t){if("number"!=typeof t||t<0)throw new Error("Invalid blur, you need to give a number above 0");this.options.blur=t,this._compute()}get url(){return this.options.url}set url(t){if("string"!=typeof t)throw new Error("Invalid url, you need to give a string");this.options.url=t,this._compute()}get filter(){return this.options.filter}set filter(t){if(null!==t&&"function"!=typeof t)throw new Error("Invalid filter, you need to give a function or null to disable the custom filtering");this.options.filter=t}}}]).Instacam}); | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("Instacam",[],e):"object"==typeof exports?exports.Instacam=e():t.Instacam=e()}(window,function(){return function(t){var e={};function i(r){if(e[r])return e[r].exports;var n=e[r]={i:r,l:!1,exports:{}};return t[r].call(n.exports,n,n.exports,i),n.l=!0,n.exports}return i.m=t,i.c=e,i.d=function(t,e,r){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.e)return t;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)i.d(r,n,function(e){return t[e]}.bind(null,n));return r},i.n=function(t){var e=t&&t.e?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,i){"use strict";i.r(e);let r={width:400,height:300,camera:!0,framerate:30,ratio:4/3,sound:!1,volume:100,mirror:!1,opacity:1,brightness:1,contrast:1,saturation:1,hue:0,invert:0,grayscale:0,sepia:0,blur:0,url:"",filter:null,done:null,fail:null,unsupported:null},n="requestAnimationFrame"in window&&"mediaDevices"in navigator&&"Promise"in window;i.d(e,"Instacam",function(){return s});class s{constructor(t,e){if(this.h=Object.assign({},r,e),n){if("string"==typeof t&&(t=document.querySelector(t)),void 0===t||null===t||"canvas"!==t.nodeName.toLowerCase())throw new Error("Invalid viewport, you need to pass a valid selector or HTML5 canvas element");this.viewport=t,this.viewport.width=this.h.width,this.viewport.height=this.h.height,this.media=document.createElement("video"),this.media.style.display="none",this.media.autoplay=!0,this.media.width=this.h.width,this.media.height=this.h.height,this.viewport.parentNode.insertBefore(this.media,this.viewport.nextSibling),this.mirror=this.h.mirror,this.u(),this.a()}else"function"==typeof this.h.unsupported&&this.h.unsupported()}a(){try{navigator.mediaDevices.getUserMedia({audio:this.h.sound,video:(()=>!1!==this.h.camera&&{frameRate:this.h.framerate,aspectRatio:this.h.ratio})()}).then(t=>{this.media.srcObject=t,this.volume=this.h.volume;const e=()=>{"function"!=typeof this.h.filter?this.viewport.getContext("2d").drawImage(this.media,0,0,this.h.width,this.h.height):(void 0===this.f&&(this.f=document.createElement("canvas"),this.f.style.display="none",this.f.width=this.h.width,this.f.height=this.h.height,this.viewport.parentNode.insertBefore(this.f,this.viewport.nextSibling)),this.f.getContext("2d").drawImage(this.media,0,0,this.h.width,this.h.height),this.viewport.getContext("2d").putImageData(this.v(this.f.getContext("2d").getImageData(0,0,this.h.width,this.h.height)),0,0)),requestAnimationFrame(e)};requestAnimationFrame(e),"function"==typeof this.h.done&&this.h.done()}).catch(t=>{"function"==typeof this.h.fail&&this.h.fail(t)})}catch(t){"function"==typeof this.h.fail&&this.h.fail(t)}}u(){this.b=this.h.opacity!==r.opacity?`opacity(${this.h.opacity}) `:"",this.b+=this.h.brightness!==r.brightness?`brightness(${this.h.brightness}) `:"",this.b+=this.h.contrast!==r.contrast?`contrast(${this.h.contrast}) `:"",this.b+=this.h.saturation!==r.saturation?`saturate(${this.h.saturation}) `:"",this.b+=this.h.hue!==r.hue?`hue-rotate(${this.h.hue}deg) `:"",this.b+=this.h.invert!==r.invert?`invert(${this.h.invert}) `:"",this.b+=this.h.grayscale!==r.grayscale?`grayscale(${this.h.grayscale}) `:"",this.b+=this.h.sepia!==r.sepia?`sepia(${this.h.sepia}) `:"",this.b+=this.h.blur!==r.blur?`blur(${this.h.blur}px) `:"",this.b+=this.h.url!==r.url?`url(${this.h.url}) `:"",this.viewport.style.filter=this.b}v(t){let e=t.data;try{for(let t=0;t<this.h.height;t++)for(let i=0;i<this.h.width;i++){const r=4*(this.h.width*t+i),n=this.h.filter({offset:r,x:i,y:t,red:e[r],green:e[r+1],blue:e[r+2],alpha:e[r+3]});e[r]=n[0],e[r+1]=n[1],e[r+2]=n[2],e[r+3]=n[3]}return t}catch(t){throw new Error("Invalid filter, you need to return a valid [red, green, blue, alpha] pixel array")}}snap(t=0,e=0,i=this.h.width,r=this.h.height){if(i<=0||r<=0)throw new Error("Invalid snap area, you need to specify a positive width and height for your image capture");return this.viewport.getContext("2d").getImageData(t,e,i,r)}save(t="png",e=1){return this.viewport.toDataURL("image/"+t,e)}get volume(){return this.h.volume}set volume(t){if("number"!=typeof t||t<0||t>100)throw new Error("Invalid volume, you need to give a number between 0 and 100");this.media.volume=this.h.volume=t/100}get mirror(){return this.h.mirror}set mirror(t){if("boolean"!=typeof t)throw new Error("Invalid mirror mode, you need to give a boolean to enable or disable the mirror mode");let e=getComputedStyle(this.viewport).getPropertyValue("transform");e="none"!==e?e:"",this.viewport.style.transform=!0===t?`${e} scale(-1, 1)`:"",this.h.mirror=t}get opacity(){return this.h.opacity}set opacity(t){if("number"!=typeof t||t<0||t>1)throw new Error("Invalid opacity, you need to give a number between 0 and 1");this.h.opacity=t,this.u()}get brightness(){return this.h.brightness}set brightness(t){if("number"!=typeof t||t<0)throw new Error("Invalid brightness, you need to give a number above 0");this.h.brightness=t,this.u()}get contrast(){return this.h.contrast}set contrast(t){if("number"!=typeof t||t<0)throw new Error("Invalid contrast, you need to give a number above 0");this.h.contrast=t,this.u()}get saturation(){return this.h.saturation}set saturation(t){if("number"!=typeof t||t<0)throw new Error("Invalid saturation, you need to give a number above 0");this.h.saturation=t,this.u()}get hue(){return this.h.hue}set hue(t){if("number"!=typeof t||t<0||t>360)throw new Error("Invalid hue, you need to give a number between 0 and 360");this.h.hue=t,this.u()}get invert(){return this.h.invert}set invert(t){if("number"!=typeof t||t<0||t>1)throw new Error("Invalid invert, you need to give a number between 0 and 1");this.h.invert=t,this.u()}get grayscale(){return this.h.grayscale}set grayscale(t){if("number"!=typeof t||t<0||t>1)throw new Error("Invalid grayscale, you need to give a number between 0 and 1");this.h.grayscale=t,this.u()}get sepia(){return this.h.sepia}set sepia(t){if("number"!=typeof t||t<0||t>1)throw new Error("Invalid sepia, you need to give a number between 0 and 1");this.h.sepia=t,this.u()}get blur(){return this.h.blur}set blur(t){if("number"!=typeof t||t<0)throw new Error("Invalid blur, you need to give a number above 0");this.h.blur=t,this.u()}get url(){return this.h.url}set url(t){if("string"!=typeof t)throw new Error("Invalid url, you need to give a string");this.h.url=t,this.u()}get filter(){return this.h.filter}set filter(t){if(null!==t&&"function"!=typeof t)throw new Error("Invalid filter, you need to give a function or null to disable the custom filtering");this.h.filter=t}}}]).Instacam}); |
@@ -278,4 +278,25 @@ # Instacam documentation | ||
The filter option allows you to applies a **custom filter** to the viewport, that is different than applying a CSS filter. The custom filter brings you the ability to edit each pixels of the media stream before they are drawn to the canvas. This option takes a `Function` with one parameter called `pixel` that corresponds to the current pixel parsed by the **class filtering loop**. On that pixel, you can get some informations like the `offset` *(index of the pixel)*, the `x` and `y` positions, the `red`, `green` and `blue` color components and finally the `alpha` layer. With this informations, you can **edit the pixel properties** and then return the edited informations. The return type of the function must be a pixel, represented by an `Array` with the red, green, blue components and the alpha layer: these new values will erase the previous informations of the pixel and will be drawn to the canvas. You can also **combine several CSS filters with a custom filter** to obtain pretty effects. If omitted, the custom filter won't be applied. **[Take a look at the demo](#demo)** to see how it works. | ||
The filter option allows you to applies a **custom filter** to the viewport, that is different than applying a CSS filter. The custom filter brings you the ability to edit each pixels of the media stream before they are drawn to the canvas. This option takes a `Function` with one parameter called `pixel` that corresponds to the current pixel parsed by the **class filtering loop**. On that pixel, you can get some informations like the `offset` *(index of the pixel)*, the `x` and `y` positions, the `red`, `green` and `blue` color components and finally the `alpha` layer. With this informations, you can **edit the pixel properties** and then return the edited informations. The return type of the function must be a pixel, represented by an `Array` with the red, green, blue components and the alpha layer: these new values will erase the previous informations of the pixel and will be drawn to the canvas. You can also **combine several CSS filters with a custom filter** to obtain pretty effects. If omitted, the custom filter won't be applied. | ||
Build a custom filter is very easy, because you can code **your own logic** inside the function, for example: | ||
```js | ||
// grayscale | ||
filter: function(pixel) { | ||
let g = 0.2126 * pixel.red + 0.7152 * pixel.green + 0.0722 * pixel.blue; | ||
return [g, g, g, pixel.alpha]; | ||
} | ||
// invert | ||
filter: function(pixel) { | ||
return [255 - pixel.red, 255 - pixel.green, 255 - pixel.blue, pixel.alpha]; | ||
} | ||
// threshold | ||
filter: function(pixel) { | ||
return (0.2126 * pixel.red + 0.7152 * pixel.green + 0.0722 * pixel.blue >= 100) ? [255, 255, 255, 255] : [0, 0, 0, 255]; | ||
} | ||
``` | ||
If you want to contribute and share cool filters, you can send me your code or create a **pull request** on the `gh-pages` branch, and it will be added to the **[Instacam demo site](#demo)**. Thanks for contributing! :tada: :+1: | ||
#### done | ||
@@ -312,4 +333,4 @@ Type: `Function` | ||
top: 0, | ||
width: this.options.width, | ||
height: this.options.height | ||
width: this._options.width, | ||
height: this._options.height | ||
); | ||
@@ -316,0 +337,0 @@ ``` |
{ | ||
"name": "instacam", | ||
"version": "1.1.2", | ||
"version": "1.2.2", | ||
"description": "Instant canvas video", | ||
@@ -5,0 +5,0 @@ "main": "src/instacam.js", |
@@ -16,8 +16,8 @@ 'use strict'; | ||
// assigns custom user options to defaults | ||
this.options = Object.assign({}, defaults, options); | ||
this._options = Object.assign({}, defaults, options); | ||
// checks for browser support | ||
if (!requirement) { | ||
if (typeof this.options.unsupported === 'function') { | ||
this.options.unsupported(); | ||
if (typeof this._options.unsupported === 'function') { | ||
this._options.unsupported(); | ||
} | ||
@@ -40,4 +40,4 @@ | ||
this.viewport = viewport; | ||
this.viewport.width = this.options.width; | ||
this.viewport.height = this.options.height; | ||
this.viewport.width = this._options.width; | ||
this.viewport.height = this._options.height; | ||
@@ -50,4 +50,4 @@ // creates the media element | ||
this.media.autoplay = true; | ||
this.media.width = this.options.width; | ||
this.media.height = this.options.height; | ||
this.media.width = this._options.width; | ||
this.media.height = this._options.height; | ||
@@ -58,3 +58,3 @@ // attaches the media element to the DOM | ||
// applies the css mirror mode on the viewport | ||
this.mirror = this.options.mirror; | ||
this.mirror = this._options.mirror; | ||
@@ -78,5 +78,5 @@ // computes the css filter options | ||
navigator.mediaDevices.getUserMedia({ | ||
audio: this.options.sound, | ||
audio: this._options.sound, | ||
video: (() => { | ||
if (this.options.camera === false) { | ||
if (this._options.camera === false) { | ||
return false; | ||
@@ -86,4 +86,4 @@ } | ||
return { | ||
frameRate: this.options.framerate, | ||
aspectRatio: this.options.ratio | ||
frameRate: this._options.framerate, | ||
aspectRatio: this._options.ratio | ||
}; | ||
@@ -97,3 +97,3 @@ })() | ||
// sets the volume at start | ||
this.volume = this.options.volume; | ||
this.volume = this._options.volume; | ||
@@ -104,4 +104,4 @@ // animation loop used to properly render the viewport | ||
// renders the viewport with or without custom filter | ||
if (typeof this.options.filter !== 'function') { | ||
this.viewport.getContext('2d').drawImage(this.media, 0, 0, this.options.width, this.options.height); | ||
if (typeof this._options.filter !== 'function') { | ||
this.viewport.getContext('2d').drawImage(this.media, 0, 0, this._options.width, this._options.height); | ||
} else { | ||
@@ -113,9 +113,9 @@ | ||
this._buffer.style.display = 'none'; | ||
this._buffer.width = this.options.width; | ||
this._buffer.height = this.options.height; | ||
this._buffer.width = this._options.width; | ||
this._buffer.height = this._options.height; | ||
this.viewport.parentNode.insertBefore(this._buffer, this.viewport.nextSibling); | ||
} | ||
this._buffer.getContext('2d').drawImage(this.media, 0, 0, this.options.width, this.options.height); | ||
this.viewport.getContext('2d').putImageData(this._filter(this._buffer.getContext('2d').getImageData(0, 0, this.options.width, this.options.height)), 0, 0); | ||
this._buffer.getContext('2d').drawImage(this.media, 0, 0, this._options.width, this._options.height); | ||
this.viewport.getContext('2d').putImageData(this._filter(this._buffer.getContext('2d').getImageData(0, 0, this._options.width, this._options.height)), 0, 0); | ||
} | ||
@@ -130,13 +130,13 @@ | ||
if (typeof this.options.done === 'function') { | ||
this.options.done(); | ||
if (typeof this._options.done === 'function') { | ||
this._options.done(); | ||
} | ||
}).catch((exception) => { | ||
if (typeof this.options.fail === 'function') { | ||
this.options.fail(exception); | ||
if (typeof this._options.fail === 'function') { | ||
this._options.fail(exception); | ||
} | ||
}); | ||
} catch(exception) { | ||
if (typeof this.options.fail === 'function') { | ||
this.options.fail(exception); | ||
if (typeof this._options.fail === 'function') { | ||
this._options.fail(exception); | ||
} | ||
@@ -152,12 +152,12 @@ } | ||
// builds the css layer depending on the options | ||
this._style = this.options.opacity !== defaults.opacity ? `opacity(${this.options.opacity}) ` : ''; | ||
this._style += this.options.brightness !== defaults.brightness ? `brightness(${this.options.brightness}) ` : ''; | ||
this._style += this.options.contrast !== defaults.contrast ? `contrast(${this.options.contrast}) ` : ''; | ||
this._style += this.options.saturation !== defaults.saturation ? `saturate(${this.options.saturation}) ` : ''; | ||
this._style += this.options.hue !== defaults.hue ? `hue-rotate(${this.options.hue}deg) ` : ''; | ||
this._style += this.options.invert !== defaults.invert ? `invert(${this.options.invert}) ` : ''; | ||
this._style += this.options.grayscale !== defaults.grayscale ? `grayscale(${this.options.grayscale}) ` : ''; | ||
this._style += this.options.sepia !== defaults.sepia ? `sepia(${this.options.sepia}) ` : ''; | ||
this._style += this.options.blur !== defaults.blur ? `blur(${this.options.blur}px) ` : ''; | ||
this._style += this.options.url !== defaults.url ? `url(${this.options.url}) ` : ''; | ||
this._style = this._options.opacity !== defaults.opacity ? `opacity(${this._options.opacity}) ` : ''; | ||
this._style += this._options.brightness !== defaults.brightness ? `brightness(${this._options.brightness}) ` : ''; | ||
this._style += this._options.contrast !== defaults.contrast ? `contrast(${this._options.contrast}) ` : ''; | ||
this._style += this._options.saturation !== defaults.saturation ? `saturate(${this._options.saturation}) ` : ''; | ||
this._style += this._options.hue !== defaults.hue ? `hue-rotate(${this._options.hue}deg) ` : ''; | ||
this._style += this._options.invert !== defaults.invert ? `invert(${this._options.invert}) ` : ''; | ||
this._style += this._options.grayscale !== defaults.grayscale ? `grayscale(${this._options.grayscale}) ` : ''; | ||
this._style += this._options.sepia !== defaults.sepia ? `sepia(${this._options.sepia}) ` : ''; | ||
this._style += this._options.blur !== defaults.blur ? `blur(${this._options.blur}px) ` : ''; | ||
this._style += this._options.url !== defaults.url ? `url(${this._options.url}) ` : ''; | ||
@@ -182,10 +182,10 @@ // applies the css filter effects to the viewport | ||
// loops through all pixels and applies the filter | ||
for (let y = 0; y < this.options.height; y++) { | ||
for (let x = 0; x < this.options.width; x++) { | ||
for (let y = 0; y < this._options.height; y++) { | ||
for (let x = 0; x < this._options.width; x++) { | ||
// detects the pixel offset | ||
const offset = ((this.options.width * y) + x) * 4; | ||
const offset = ((this._options.width * y) + x) * 4; | ||
// calls the filter | ||
const filter = this.options.filter({ | ||
const filter = this._options.filter({ | ||
'offset': offset, | ||
@@ -222,3 +222,3 @@ 'x': x, | ||
*/ | ||
snap(left = 0, top = 0, width = this.options.width, height = this.options.height) { | ||
snap(left = 0, top = 0, width = this._options.width, height = this._options.height) { | ||
@@ -248,3 +248,3 @@ // checks the snap size area | ||
get volume() { | ||
return this.options.volume; | ||
return this._options.volume; | ||
} | ||
@@ -261,3 +261,3 @@ | ||
this.media.volume = this.options.volume = volume / 100; | ||
this.media.volume = this._options.volume = volume / 100; | ||
} | ||
@@ -270,3 +270,3 @@ | ||
get mirror() { | ||
return this.options.mirror; | ||
return this._options.mirror; | ||
} | ||
@@ -287,3 +287,3 @@ | ||
this.viewport.style.transform = mirror === true ? `${transform} scale(-1, 1)` : ''; | ||
this.options.mirror = mirror; | ||
this._options.mirror = mirror; | ||
} | ||
@@ -296,3 +296,3 @@ | ||
get opacity() { | ||
return this.options.opacity; | ||
return this._options.opacity; | ||
} | ||
@@ -309,3 +309,3 @@ | ||
this.options.opacity = opacity; | ||
this._options.opacity = opacity; | ||
this._compute(); | ||
@@ -319,3 +319,3 @@ } | ||
get brightness() { | ||
return this.options.brightness; | ||
return this._options.brightness; | ||
} | ||
@@ -332,3 +332,3 @@ | ||
this.options.brightness = brightness; | ||
this._options.brightness = brightness; | ||
this._compute(); | ||
@@ -342,3 +342,3 @@ } | ||
get contrast() { | ||
return this.options.contrast; | ||
return this._options.contrast; | ||
} | ||
@@ -355,3 +355,3 @@ | ||
this.options.contrast = contrast; | ||
this._options.contrast = contrast; | ||
this._compute(); | ||
@@ -365,3 +365,3 @@ } | ||
get saturation() { | ||
return this.options.saturation; | ||
return this._options.saturation; | ||
} | ||
@@ -378,3 +378,3 @@ | ||
this.options.saturation = saturation; | ||
this._options.saturation = saturation; | ||
this._compute(); | ||
@@ -388,3 +388,3 @@ } | ||
get hue() { | ||
return this.options.hue; | ||
return this._options.hue; | ||
} | ||
@@ -401,3 +401,3 @@ | ||
this.options.hue = hue; | ||
this._options.hue = hue; | ||
this._compute(); | ||
@@ -411,3 +411,3 @@ } | ||
get invert() { | ||
return this.options.invert; | ||
return this._options.invert; | ||
} | ||
@@ -424,3 +424,3 @@ | ||
this.options.invert = invert; | ||
this._options.invert = invert; | ||
this._compute(); | ||
@@ -434,3 +434,3 @@ } | ||
get grayscale() { | ||
return this.options.grayscale; | ||
return this._options.grayscale; | ||
} | ||
@@ -447,3 +447,3 @@ | ||
this.options.grayscale = grayscale; | ||
this._options.grayscale = grayscale; | ||
this._compute(); | ||
@@ -457,3 +457,3 @@ } | ||
get sepia() { | ||
return this.options.sepia; | ||
return this._options.sepia; | ||
} | ||
@@ -470,3 +470,3 @@ | ||
this.options.sepia = sepia; | ||
this._options.sepia = sepia; | ||
this._compute(); | ||
@@ -480,3 +480,3 @@ } | ||
get blur() { | ||
return this.options.blur; | ||
return this._options.blur; | ||
} | ||
@@ -493,3 +493,3 @@ | ||
this.options.blur = blur; | ||
this._options.blur = blur; | ||
this._compute(); | ||
@@ -503,3 +503,3 @@ } | ||
get url() { | ||
return this.options.url; | ||
return this._options.url; | ||
} | ||
@@ -516,3 +516,3 @@ | ||
this.options.url = url; | ||
this._options.url = url; | ||
this._compute(); | ||
@@ -526,3 +526,3 @@ } | ||
get filter() { | ||
return this.options.filter; | ||
return this._options.filter; | ||
} | ||
@@ -539,4 +539,4 @@ | ||
this.options.filter = filter; | ||
this._options.filter = filter; | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
363561