diff options
| author | taehoon <th.dev91@gmail.com> | 2019-02-07 03:05:59 -0500 |
|---|---|---|
| committer | taehoon <th.dev91@gmail.com> | 2019-02-15 13:34:33 -0500 |
| commit | 13725f040bca346a7b35b832f36f4e86c5da11e4 (patch) | |
| tree | aafd73aa352b6f2e52b968d1e2e79cb225cdc0d6 /src/components/image_cropper | |
| parent | 4f95371081fd54291e3d81d7e254e9cfa1bd5b82 (diff) | |
Add avatar crop popup
Diffstat (limited to 'src/components/image_cropper')
| -rw-r--r-- | src/components/image_cropper/image_cropper.js | 88 | ||||
| -rw-r--r-- | src/components/image_cropper/image_cropper.vue | 39 |
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> |
