aboutsummaryrefslogtreecommitdiff
path: root/src/components/image_cropper
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/image_cropper')
-rw-r--r--src/components/image_cropper/image_cropper.js88
-rw-r--r--src/components/image_cropper/image_cropper.vue39
2 files changed, 127 insertions, 0 deletions
diff --git a/src/components/image_cropper/image_cropper.js b/src/components/image_cropper/image_cropper.js
new file mode 100644
index 00000000..e4bf5ea2
--- /dev/null
+++ b/src/components/image_cropper/image_cropper.js
@@ -0,0 +1,88 @@
+import Cropper from 'cropperjs'
+import Modal from '../modal/modal.vue'
+import 'cropperjs/dist/cropper.css'
+
+const ImageCropper = {
+ props: {
+ trigger: {
+ type: [String, Element],
+ required: true
+ },
+ cropperOptions: {
+ type: Object,
+ default () {
+ return {
+ aspectRatio: 1,
+ autoCropArea: 1,
+ viewMode: 1,
+ movable: false,
+ zoomable: false,
+ guides: false
+ }
+ }
+ },
+ mimes: {
+ type: String,
+ default: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon'
+ },
+ title: {
+ type: String,
+ default: 'Crop picture'
+ },
+ saveButtonLabel: {
+ type: String,
+ default: 'Save'
+ }
+ },
+ data () {
+ return {
+ cropper: undefined,
+ dataUrl: undefined,
+ filename: undefined
+ }
+ },
+ components: {
+ Modal
+ },
+ methods: {
+ destroy () {
+ this.cropper.destroy()
+ this.$refs.input.value = ''
+ this.dataUrl = undefined
+ },
+ submit () {
+ this.$emit('submit', this.cropper, this.filename)
+ this.destroy()
+ },
+ pickImage () {
+ this.$refs.input.click()
+ },
+ createCropper () {
+ this.cropper = new Cropper(this.$refs.img, this.cropperOptions)
+ }
+ },
+ mounted () {
+ // listen for click event on trigger
+ let trigger = typeof this.trigger === 'object' ? this.trigger : document.querySelector(this.trigger)
+ if (!trigger) {
+ this.$emit('error', 'No image make trigger found.', 'user')
+ } else {
+ trigger.addEventListener('click', this.pickImage)
+ }
+ // listen for input file changes
+ let fileInput = this.$refs.input
+ fileInput.addEventListener('change', () => {
+ if (fileInput.files != null && fileInput.files[0] != null) {
+ let reader = new FileReader()
+ reader.onload = (e) => {
+ this.dataUrl = e.target.result
+ }
+ reader.readAsDataURL(fileInput.files[0])
+ this.filename = fileInput.files[0].name || 'unknown'
+ this.$emit('changed', fileInput.files[0], reader)
+ }
+ })
+ }
+}
+
+export default ImageCropper
diff --git a/src/components/image_cropper/image_cropper.vue b/src/components/image_cropper/image_cropper.vue
new file mode 100644
index 00000000..1c52842c
--- /dev/null
+++ b/src/components/image_cropper/image_cropper.vue
@@ -0,0 +1,39 @@
+<template>
+ <div class="image-cropper">
+ <modal :show="dataUrl" :title="title" @close="destroy">
+ <div class="modal-body">
+ <div class="image-cropper-image-container">
+ <img ref="img" :src="dataUrl" alt="" @load.stop="createCropper" />
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button class="btn image-cropper-btn" type="button" @click="submit" v-text="saveButtonLabel"></button>
+ </div>
+ </modal>
+ <input ref="input" type="file" class="image-cropper-img-input" :accept="mimes">
+ </div>
+</template>
+
+<script src="./image_cropper.js"></script>
+
+<style lang="scss">
+.image-cropper {
+ &-img-input {
+ display: none;
+ }
+
+ &-image-container {
+ position: relative;
+
+ img {
+ display: block;
+ max-width: 100%;
+ }
+ }
+
+ &-btn {
+ display: block;
+ width: 100%;
+ }
+}
+</style>