first commit

This commit is contained in:
Vincent Gabriel
2017-06-26 11:17:57 -07:00
commit bab588f3d0
15 changed files with 376 additions and 0 deletions

5
.babelrc Normal file
View File

@@ -0,0 +1,5 @@
{
"presets": ["es2015", "stage-2"],
"plugins": ["transform-runtime"],
"comments": false
}

9
.editorconfig Normal file
View File

@@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
.DS_Store
node_modules/
dist/
npm-debug.log

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Vincent Gabriel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# vue-web-cam
> Webcam component for Vuejs applications

40
build/utils.js Normal file
View File

@@ -0,0 +1,40 @@
var path = require('path')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
// generate loader string to be used with extract text plugin
function generateLoaders (loaders) {
var sourceLoader = loaders.map(function (loader) {
var extraParamChar
if (/\?/.test(loader)) {
loader = loader.replace(/\?/, '-loader?')
extraParamChar = '&'
} else {
loader = loader + '-loader'
extraParamChar = '?'
}
return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
}).join('!')
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
} else {
return ['vue-style-loader', sourceLoader].join('!')
}
}
// http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
return {
css: generateLoaders(['css'])
}
}

View File

@@ -0,0 +1,34 @@
var path = require('path');
var projectRoot = path.resolve(__dirname, '../');
module.exports = {
entry: {
app: './src/index.js'
},
output: {
path: path.resolve(__dirname, '../dist'),
publicPath: '/',
filename: '[name].js'
},
resolve: {
extensions: ['', '.js', '.vue'],
fallback: [path.join(__dirname, '../node_modules')],
alias: {
'src': path.resolve(__dirname, '../src')
}
},
resolveLoader: {
fallback: [path.join(__dirname, '../node_modules')]
},
module: {
loaders: [{
test: /\.vue$/,
loader: 'vue'
}, {
test: /\.js$/,
loader: 'babel',
include: projectRoot,
exclude: /node_modules/
}]
}
}

30
build/webpack.dev.conf.js Normal file
View File

@@ -0,0 +1,30 @@
var path = require('path');
var webpack = require('webpack');
var merge = require('webpack-merge');
var baseWebpackConfig = require('./webpack.base.conf');
var HtmlWebpackPlugin = require('html-webpack-plugin');
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]);
})
module.exports = merge(baseWebpackConfig, {
entry: {
app: './src/dev.js'
},
devtool: '#eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': "'development'"
}),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
})
]
});

View File

@@ -0,0 +1,39 @@
var path = require('path');
var webpack = require('webpack');
var merge = require('webpack-merge');
var baseWebpackConfig = require('./webpack.base.conf');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var utils = require('./utils');
var distDir = path.resolve(__dirname, '../dist');
var webpackConfig = merge(baseWebpackConfig, {
devtool: '#source-map',
output: {
filename: 'js/[name].[chunkhash].js',
chunkFilename: 'js/[id].[chunkhash].js'
},
vue: {
loaders: utils.cssLoaders({
sourceMap: true,
extract: true
})
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': "'production'"
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.optimize.OccurenceOrderPlugin(),
// extract css into its own file
new ExtractTextPlugin('css/[name].[contenthash].css')
]
});
module.exports = webpackConfig;

11
index.html Normal file
View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vue-web-cam</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

50
package.json Normal file
View File

@@ -0,0 +1,50 @@
{
"name": "vue-web-cam",
"version": "1.0.0",
"description": "Webcam component for Vuejs applications",
"author": {
"name": "Mohammad Shoriful Islam Ronju",
"email": "smronju@gmail.com",
"url": "https://github.com/smronju"
},
"contributors": [
{
"name": "Vincent Gabriel",
"email": "vadimg88@gmail.com",
"url": "https://github.com/vinceg"
}
],
"scripts": {
"build": "webpack -p --config build/webpack.prod.conf.js",
"dev": "webpack-dev-server --inline --hot --config build/webpack.dev.conf.js"
},
"dependencies": {
"vue": "^2.0.1"
},
"repository": {
"type": "git",
"url": "https://github.com/vinceg/vue-web-cam"
},
"license": "MIT",
"devDependencies": {
"babel-core": "^6.0.0",
"babel-loader": "^6.0.0",
"babel-plugin-transform-runtime": "^6.0.0",
"babel-preset-es2015": "^6.0.0",
"babel-preset-stage-2": "^6.0.0",
"babel-register": "^6.0.0",
"babel-runtime": "^6.0.0",
"css-loader": "^0.25.0",
"extract-text-webpack-plugin": "^1.0.1",
"function-bind": "^1.0.2",
"html-webpack-plugin": "^2.8.1",
"vue-loader": "^9.4.0",
"vue-style-loader": "^1.0.0",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.16.2",
"webpack-merge": "^0.14.1"
},
"engines": {
"node": ">= 4.0.0"
}
}

7
src/dev.js Normal file
View File

@@ -0,0 +1,7 @@
import Vue from 'vue'
import Main from './main'
new Vue({
el: '#app',
...Main
})

10
src/index.js Normal file
View File

@@ -0,0 +1,10 @@
import Main from './main'
if (typeof window !== 'undefined') {
window.Main = Main
}
export {
Main
}

28
src/main.vue Normal file
View File

@@ -0,0 +1,28 @@
<template>
<div id="app" class="component">
<webcam ref="webcam"></webcam>
<img :src="this.img" style="width:500px;height:500px;" />
<button type="button" @click="photo">Capture Photo</button>
</div>
</template>
<script>
import Webcam from './Webcam'
export default {
name: 'app',
data() {
return {
img: null
};
},
methods: {
photo() {
this.img = this.$refs.webcam.capture();
}
},
components: {
Webcam
}
}
</script>

85
src/webcam.vue Normal file
View File

@@ -0,0 +1,85 @@
<template>
<video ref="video" :width="this.width" :height="this.height" :src="this.source" :autoplay="this.true"></video>
</template>
<script>
export default {
data () {
return {
stream: '',
source: '',
canvas: null
};
},
props: {
width: {
type: Number,
default: 500
},
height: {
type: Number,
default: 500
},
autoplay: {
type: Boolean,
default: false
},
screenshotFormat: {
type: String,
default: 'image/jpeg'
}
},
mounted() {
if (!this.hasMedia()) {
this.$emit('notsupported');
return;
}
this.requestMedia();
if (navigator.getUserMedia) {
navigator.getUserMedia({ video: true }, stream => {
this.source = window.URL.createObjectURL(stream);
this.stream = stream;
this.$emit('started', stream);
}, error => {
this.$emit('error', error);
});
}
},
methods: {
hasMedia() {
return !!this.getMedia();
},
getMedia() {
return (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia);
},
requestMedia() {
navigator.getUserMedia = this.getMedia();
},
capture() {
if (!this.hasMedia()) {
this.$emit('notsupported');
return null;
}
return this.getCanvas().toDataURL(this.screenshotFormat);
},
getCanvas() {
let video = this.$refs.video;
if (!this.ctx) {
let canvas = document.createElement('canvas');
canvas.height = video.clientHeight;
canvas.width = video.clientWidth;
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
}
const { ctx, canvas } = this;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
return canvas;
}
}
}
</script>