├── .npmignore ├── .gitignore ├── example ├── .gitignore ├── .babelrc ├── style.css ├── src │ ├── main.js │ └── App.vue ├── README.md ├── index.html ├── package.json └── webpack.config.js ├── README.md ├── package.json ├── LICENSE └── VueWebcam.js /.npmignore: -------------------------------------------------------------------------------- 1 | example/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["es2015", { "modules": false }] 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /example/style.css: -------------------------------------------------------------------------------- 1 | #app { 2 | position: absolute; 3 | top: 50%; 4 | left: 50%; 5 | transform: translate(-50%, -50%); 6 | } 7 | -------------------------------------------------------------------------------- /example/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | new Vue({ 5 | el: '#app', 6 | render: h => h(App) 7 | }); 8 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # vue-webcam-example 2 | 3 | > Example project for vue-webcam package 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm start 13 | ``` 14 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vue Webcam Example 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # If you found any issues please make PR as I'm not maintaining this anymore! 2 | 3 | # vue-webcam 4 | A Vue component for capturing image from webcam. 5 | 6 | ## Installation 7 | ```shell 8 | npm install --save vue-webcam 9 | ``` 10 | 11 | ## Usage 12 | See the [example](https://github.com/smronju/vue-webcam/tree/master/example) files 13 | 14 | ## Options 15 | 16 | ### width 17 | * Type: `Number` 18 | * Required: `false` 19 | 20 | ### height 21 | * Type: `Number` 22 | * Required: `false` 23 | 24 | ### Resources 25 | 26 | See more about taking photos from webcam [documentation](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Taking_still_photos) 27 | 28 | ## License 29 | MIT 30 | -------------------------------------------------------------------------------- /example/src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 29 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-webcam-example", 3 | "description": "Example project for vue-webcam package", 4 | "author": { 5 | "name": "Mohammad Shoriful Islam Ronju", 6 | "email": "smronju@gmail.com", 7 | "url": "https://github.com/smronju" 8 | }, 9 | "scripts": { 10 | "start": "webpack-dev-server --open --inline --hot" 11 | }, 12 | "dependencies": { 13 | "vue": "^2.0.1", 14 | "vue-webcam": "^2.0.2" 15 | }, 16 | "devDependencies": { 17 | "babel-core": "^6.0.0", 18 | "babel-loader": "^6.0.0", 19 | "babel-preset-es2015": "^6.0.0", 20 | "cross-env": "^3.0.0", 21 | "css-loader": "^0.25.0", 22 | "file-loader": "^0.9.0", 23 | "style-loader": "^0.13.1", 24 | "vue-loader": "^9.4.0", 25 | "webpack": "2.1.0-beta.22", 26 | "webpack-dev-server": "^2.1.0-beta.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-webcam", 3 | "version": "2.0.6", 4 | "description": "A Vue component for capturing image from webcam.", 5 | "main": "VueWebcam.js", 6 | "keywords": [ 7 | "vue", 8 | "vuejs", 9 | "webcam", 10 | "stream", 11 | "component" 12 | ], 13 | "script": { 14 | "build": "./node_modules/.bin/microbundle -i ./VueWebcam.js" 15 | }, 16 | "author": { 17 | "name": "Mohammad Shoriful Islam Ronju", 18 | "email": "smronju@gmail.com", 19 | "url": "https://github.com/smronju" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/smronju/vue-webcam" 24 | }, 25 | "license": "MIT", 26 | "peerDependencies": { 27 | "vue": ">=2.0.0" 28 | }, 29 | "devDependencies": { 30 | "microbundle": "^0.2.4" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Mohammad Shoriful Islam Ronju 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: './src/main.js', 6 | output: { 7 | path: path.resolve(__dirname, './dist'), 8 | publicPath: '/dist/', 9 | filename: 'build.js' 10 | }, 11 | resolveLoader: { 12 | root: path.join(__dirname, 'node_modules'), 13 | }, 14 | module: { 15 | loaders: [ 16 | { 17 | test: /\.vue$/, 18 | loader: 'vue' 19 | }, 20 | { 21 | test: /\.js$/, 22 | loader: 'babel', 23 | exclude: /node_modules/ 24 | }, 25 | { 26 | test: /\.css$/, 27 | loader: 'style-loader!css-loader' 28 | }, 29 | { 30 | test: /\.(png|jpg|gif|svg)$/, 31 | loader: 'file', 32 | query: { 33 | limit: 10000, 34 | name: '[name].[ext]?[hash]' 35 | } 36 | } 37 | ] 38 | }, 39 | devServer: { 40 | historyApiFallback: true, 41 | noInfo: true 42 | }, 43 | devtool: '#eval-source-map' 44 | } 45 | 46 | if (process.env.NODE_ENV === 'production') { 47 | module.exports.devtool = '#source-map' 48 | // http://vue-loader.vuejs.org/en/workflow/production.html 49 | module.exports.plugins = (module.exports.plugins || []).concat([ 50 | new webpack.DefinePlugin({ 51 | 'process.env': { 52 | NODE_ENV: '"production"' 53 | } 54 | }), 55 | new webpack.optimize.UglifyJsPlugin({ 56 | compress: { 57 | warnings: false 58 | } 59 | }), 60 | new webpack.optimize.OccurenceOrderPlugin() 61 | ]) 62 | } 63 | -------------------------------------------------------------------------------- /VueWebcam.js: -------------------------------------------------------------------------------- 1 | // TODO: 2 | // 1. Enable mirror option 3 | // 2. Improve options handling 4 | // 3. Error handling 5 | 6 | const Vue = require('vue').default; 7 | 8 | const WebcamComponent = Vue.extend({ 9 | props: { 10 | autoplay: { 11 | type: Boolean, 12 | default: true 13 | }, 14 | width: { 15 | type: Number, 16 | default: 400 17 | }, 18 | height: { 19 | type: Number, 20 | default: 300 21 | }, 22 | mirror: { 23 | type: Boolean, 24 | default: true 25 | }, 26 | screenshotFormat: { 27 | type: String, 28 | default: 'image/jpeg' 29 | } 30 | }, 31 | data() { 32 | return { 33 | video: '', 34 | src: '', 35 | stream: '', 36 | hasUserMedia: false, 37 | styleObject: { 38 | transform: 'scale(-1, 1)', 39 | filter: 'FlipH' 40 | } 41 | }; 42 | }, 43 | 44 | mounted() { 45 | this.video = this.$refs.video; 46 | navigator.getUserMedia = 47 | navigator.getUserMedia || 48 | navigator.webkitGetUserMedia || 49 | navigator.mozGetUserMedia || 50 | navigator.msGetUserMedia || 51 | navigator.oGetUserMedia; 52 | 53 | // new api for video and audio called navigator.mediadevices 54 | // for new browsers video can directly consume MediaStream using srcObject 55 | // 56 | if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { 57 | navigator.mediaDevices 58 | .getUserMedia({ video: true }) 59 | .then(stream => { 60 | this.video = this.$refs.video; // reInitializing as it doesn't work sometime. 61 | this.video.srcObject = stream; 62 | this.stream = stream; 63 | this.hasUserMedia = true; 64 | }) 65 | .catch(error => { 66 | console.log(error); 67 | }); 68 | } else if (navigator.getUserMedia) { 69 | // if new api not there, use the old one 70 | navigator.getUserMedia( 71 | { video: true }, 72 | stream => { 73 | this.video = this.$refs.video; 74 | // below line won't work on new browser because of this 75 | // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL#Using_object_URLs_for_media_streams 76 | // this.src = window.URL.createObjectURL(stream); 77 | this.video.srcObject = stream; 78 | this.stream = stream; 79 | this.hasUserMedia = true; 80 | }, 81 | error => { 82 | console.log(error); 83 | } 84 | ); 85 | } 86 | }, 87 | methods: { 88 | getPhoto() { 89 | if (!this.hasUserMedia) return null; 90 | 91 | const canvas = this.getCanvas(); 92 | return canvas.toDataURL(this.screenshotFormat); 93 | }, 94 | getCanvas() { 95 | if (!this.hasUserMedia) return null; 96 | 97 | const video = this.$refs.video; 98 | if (!this.ctx) { 99 | const canvas = document.createElement('canvas'); 100 | canvas.height = video.clientHeight; 101 | canvas.width = video.clientWidth; 102 | this.canvas = canvas; 103 | 104 | this.ctx = canvas.getContext('2d'); 105 | 106 | /*if (this.mirror) { 107 | const context = canvas.getContext('2d'); 108 | context.translate(canvas.width, 0); 109 | context.scale(-1, 1); 110 | this.ctx = context; 111 | } else { 112 | this.ctx = canvas.getContext('2d'); 113 | }*/ 114 | } 115 | 116 | const { ctx, canvas } = this; 117 | ctx.drawImage(video, 0, 0, canvas.width, canvas.height); 118 | 119 | return canvas; 120 | } 121 | }, 122 | 123 | beforeDestroy: function() { 124 | this.video.pause(); 125 | this.src = ''; 126 | this.stream && 127 | this.stream.getTracks()[0] && 128 | this.stream.getTracks()[0].stop(); 129 | }, 130 | 131 | destroyed: function() { 132 | console.log('Destroyed'); 133 | }, 134 | render: function(h) { 135 | return h('video', { 136 | ref: 'video', 137 | attrs: { 138 | width: this.width, 139 | height: this.height, 140 | src: this.src, 141 | autoplay: this.autoplay 142 | } 143 | }); 144 | } 145 | }); 146 | 147 | const VueWebcam = Vue.component('vue-webcam', WebcamComponent); 148 | export default VueWebcam; 149 | --------------------------------------------------------------------------------