You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.3 KiB

2 years ago
  1. <template>
  2. <v-dialog @click:outside="cancelCropImage" content-class="mb-15" scrollable width="70%" v-model="isCropImageDialogActive" style="z-index:500">
  3. <v-card class="border-radius-20 pt-12 cropper-card-height">
  4. <v-spacer class="d-flex justify-end">
  5. <v-btn icon @click="cancelCropImage" class="me-15 mb-9">
  6. <v-icon>
  7. mdi-close
  8. </v-icon>
  9. </v-btn>
  10. </v-spacer>
  11. <v-spacer class="d-flex justify-center pb-15">
  12. <cropper
  13. class="cropper"
  14. ref="cropper"
  15. :src="cropImagePreview"
  16. :stencil-component="$options.components.CircleStencil"
  17. />
  18. </v-spacer>
  19. <v-spacer class="d-flex justify-center justify-sm-end mb-11">
  20. <v-btn class="me-3" width="110px" @click="cancelCropImage" text color="primary">
  21. {{ $t("userProfile.cropReset") }}
  22. </v-btn>
  23. <v-btn class="me-15 border-radius-16" width="110px" @click="cropImage" color="primary">
  24. {{ $t("userProfile.crop") }}
  25. </v-btn>
  26. </v-spacer>
  27. </v-card>
  28. </v-dialog>
  29. </template>
  30. <script>
  31. import { CircleStencil, Cropper } from 'vue-advanced-cropper';
  32. import 'vue-advanced-cropper/dist/style.css';
  33. export default {
  34. name: "cropImageDialog",
  35. components: {
  36. CircleStencil, Cropper
  37. },
  38. props: {
  39. isCropImageDialogActive: {
  40. type: Boolean,
  41. required: true,
  42. default: false,
  43. },
  44. cropImagePreview: {
  45. type: String,
  46. required: true,
  47. default: '',
  48. },
  49. },
  50. methods: {
  51. cancelCropImage() {
  52. const deleteFile = this.cropImagePreview.split('/')
  53. const filename = deleteFile.pop()
  54. this.$axios.delete(`/users/images?filename=${filename}`)
  55. .then(response => {})
  56. .catch(error => console.log(error))
  57. this.$emit('close-crop-dialog')
  58. },
  59. cropImage() {
  60. const result = this.$refs.cropper.getResult()
  61. const resultSplit = result.image.src.split('/')
  62. const fileDetails = resultSplit[resultSplit.length-1].split('.')
  63. const fileURL = result.canvas.toDataURL('image/'+fileDetails[1])
  64. const file = this.dataURLtoFile(fileURL,fileDetails[0]+'.'+fileDetails[1])
  65. const payload = new FormData()
  66. payload.append('file',file)
  67. this.$axios.post('/users/images',payload)
  68. .then(response => {
  69. const pictureURL = response.data.image.url
  70. this.$emit('upload-image-success',pictureURL)
  71. })
  72. .catch(error => console.log(error))
  73. },
  74. dataURLtoFile(dataurl, filename) {
  75. let arr = dataurl.split(','),
  76. mime = arr[0].match(/:(.*?);/)[1],
  77. bstr = atob(arr[1]),
  78. n = bstr.length,
  79. u8arr = new Uint8Array(n);
  80. while(n--){
  81. u8arr[n] = bstr.charCodeAt(n);
  82. }
  83. return new File([u8arr], filename, {type:mime});
  84. },
  85. },
  86. }
  87. </script>
  88. <style lang="scss" scoped>
  89. .cropper {
  90. width: 85%;
  91. @media screen and (max-width: 600px) {
  92. min-height: 164px;
  93. }
  94. @media screen and (min-width: 600px) and (max-width: 960px) {
  95. min-height: 303px;
  96. }
  97. @media screen and (min-width: 961px) {
  98. min-height: 538px;
  99. }
  100. }
  101. .cropper-card-height {
  102. @media screen and (max-width: 600px) {
  103. min-height: 515px;
  104. }
  105. @media screen and (min-width: 600px) and (max-width: 960px) {
  106. min-height: 717px;
  107. }
  108. @media screen and (min-width: 961px) {
  109. min-height: 1000px;
  110. }
  111. }
  112. </style>