├── .babelrc
├── .gitignore
├── LICENSE
├── README.md
├── dist
├── build.js
└── build.js.map
├── index.html
├── package.json
├── src
├── App.vue
└── main.js
├── webpack.config.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Alessio Maffeis
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # picture-input-example
2 |
3 | This is a simple example project demonstrating the usage of vue-picture-input, a mobile-friendly picture file input Vue.js component with image preview, drag and drop, and EXIF orientation.
4 |
5 | See it in action: https://alessiomaffeis.github.io/vue-picture-input-example/
6 |
7 | vue-picture-input repository: https://github.com/alessiomaffeis/vue-picture-input
8 |
9 | ## Build Setup
10 |
11 | ``` bash
12 | # install dependencies
13 | npm install
14 |
15 | # serve with hot reload at localhost:8080
16 | npm run dev
17 |
18 | # build for production with minification
19 | npm run build
20 | ```
21 |
22 | For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader).
23 |
--------------------------------------------------------------------------------
/dist/build.js:
--------------------------------------------------------------------------------
1 | !function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/dist/",t(t.s=8)}([function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t
Photo successfully selected!
",fileSize:"The file size exceeds the limit",fileType:"This file type is not supported."}}},mounted:function(){var e=this;if(this.updateStrings(),this.prefill&&this.preloadImage(this.prefill,this.prefillOptions),this.$nextTick(function(){window.addEventListener("resize",e.onResize),e.onResize()}),this.supportsPreview){this.pixelRatio=Math.round(window.devicePixelRatio||window.screen.deviceXDPI/window.screen.logicalXDPI);var t=this.$refs.previewCanvas;t.getContext&&(this.context=t.getContext("2d"),this.context.scale(this.pixelRatio,this.pixelRatio))}"image/*"!==this.accept&&(this.fileTypes=this.accept.split(","),this.fileTypes=this.fileTypes.map(function(e){return e.trim()})),this.canvasWidth=this.width,this.canvasHeight=this.height,this.width!=Number.MAX_SAFE_INTEGER&&this.height!=Number.MAX_SAFE_INTEGER&&(this.previewWidth=this.width,this.previewHeight=this.height),this.$on("error",this.onError)},beforeDestroy:function(){window.removeEventListener("resize",this.onResize),this.$off("error",this.onError)},methods:{updateStrings:function(){for(var e in this.customStrings)e in this.strings&&"string"==typeof this.customStrings[e]&&(this.strings[e]=this.customStrings[e])},onClick:function(){if(!this.imageSelected)return void this.selectImage();this.changeOnClick&&this.selectImage(),this.$emit("click")},onResize:function(){this.resizeCanvas()&&this.imageObject&&this.drawImage(this.imageObject)},onDragEnter:function(){this.supportsDragAndDrop&&(this.draggingOver=!0)},onDragLeave:function(){this.supportsDragAndDrop&&(this.draggingOver=!1)},onFileDrop:function(e){this.onDragLeave(),this.onFileChange(e)},onFileChange:function(e,t){var n=e.target.files||e.dataTransfer.files;if(n.length){if(n[0].size<=0||n[0].size>1024*this.size*1024)return void this.$emit("error",{type:"fileSize",fileSize:n[0].size,fileType:n[0].type,fileName:n[0].name,message:this.strings.fileSize+" ("+this.size+"MB)"});if(n[0].name!==this.fileName||n[0].size!==this.fileSize||this.fileModified!==n[0].lastModified){if(this.file=n[0],this.fileName=n[0].name,this.fileSize=n[0].size,this.fileModified=n[0].lastModified,this.fileType=n[0].type,"image/*"===this.accept){if("image/"!==n[0].type.substr(0,6))return}else if(-1===this.fileTypes.indexOf(n[0].type))return void this.$emit("error",{type:"fileType",fileSize:n[0].size,fileType:n[0].type,fileName:n[0].name,message:this.strings.fileType});this.imageSelected=!0,this.image="",this.supportsPreview?this.loadImage(n[0],t||!1):t?this.$emit("prefill"):this.$emit("change",this.image)}}},onError:function(e){this.alertOnError&&alert(e.message)},loadImage:function(e,t){var n=this;this.getEXIFOrientation(e,function(r){n.setOrientation(r);var i=new FileReader;i.onload=function(e){n.image=e.target.result,t?n.$emit("prefill"):n.$emit("change",n.image),n.imageObject=new Image,n.imageObject.onload=function(){if(n.autoToggleAspectRatio){n.getOrientation(n.canvasWidth,n.canvasHeight)!==n.getOrientation(n.imageObject.width,n.imageObject.height)&&n.rotateCanvas()}n.drawImage(n.imageObject)},n.imageObject.src=n.image},i.readAsDataURL(e)})},drawImage:function(e){this.imageWidth=e.width,this.imageHeight=e.height,this.imageRatio=e.width/e.height;var t=0,n=0,r=this.previewWidth,i=this.previewHeight,o=this.previewWidth/this.previewHeight;this.crop?this.imageRatio>=o?(r=i*this.imageRatio,t=(this.previewWidth-r)/2):(i=r/this.imageRatio,n=(this.previewHeight-i)/2):this.imageRatio>=o?(i=r/this.imageRatio,n=(this.previewHeight-i)/2):(r=i*this.imageRatio,t=(this.previewWidth-r)/2);var a=this.$refs.previewCanvas;a.style.background="none",a.width=this.previewWidth*this.pixelRatio,a.height=this.previewHeight*this.pixelRatio,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,a.width,a.height),this.rotate&&void 0===this.imageObject.style.imageOrientation&&(this.context.translate(t*this.pixelRatio,n*this.pixelRatio),this.context.translate(r/2*this.pixelRatio,i/2*this.pixelRatio),this.context.rotate(this.rotate),t=-r/2,n=-i/2),this.context.drawImage(e,t*this.pixelRatio,n*this.pixelRatio,r*this.pixelRatio,i*this.pixelRatio)},selectImage:function(){this.$refs.fileInput.click()},removeImage:function(){this.$refs.fileInput.value="",this.$refs.fileInput.type="",this.$refs.fileInput.type="file",this.fileName="",this.fileType="",this.fileSize=0,this.fileModified=0,this.imageSelected=!1,this.image="",this.file=null,this.imageObject=null,this.$refs.previewCanvas.style.backgroundColor="rgba(200,200,200,.25)",this.$refs.previewCanvas.width=this.previewWidth*this.pixelRatio,this.$emit("remove")},rotateImage:function(){this.rotateCanvas(),this.imageObject&&this.drawImage(this.imageObject);var e=this.getOrientation(this.canvasWidth,this.canvasHeight);this.$emit("aspectratiochange",e)},resizeCanvas:function(){var e=this.canvasWidth/this.canvasHeight,t=this.$refs.container.clientWidth;return!!t&&(!(!this.toggleAspectRatio&&t===this.containerWidth)&&(this.containerWidth=t,this.previewWidth=Math.min(this.containerWidth-2*this.margin,this.canvasWidth),this.previewHeight=this.previewWidth/e,!0))},getOrientation:function(e,t){var n="square";return e>t?n="landscape":e