mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
234 lines
5.3 KiB
Vue
234 lines
5.3 KiB
Vue
<template>
|
|
<vue-dropzone
|
|
:options="dropzoneOptions"
|
|
ref="el"
|
|
id="postdropzone"
|
|
class="ds-card-image"
|
|
:use-custom-slot="true"
|
|
@vdropzone-error="verror"
|
|
@vdropzone-thumbnail="transformImage"
|
|
>
|
|
<div class="crop-overlay" ref="cropperOverlay" v-show="showCropper">
|
|
<ds-button @click="cropImage" class="crop-confirm" primary>
|
|
{{ $t('contribution.teaserImage.cropperConfirm') }}
|
|
</ds-button>
|
|
<ds-button @click="cancelCrop" class="crop-cancel" icon="close"></ds-button>
|
|
</div>
|
|
<div
|
|
:class="{
|
|
'hc-attachments-upload-area-post': true,
|
|
'hc-attachments-upload-area-update-post': contribution,
|
|
}"
|
|
>
|
|
<slot></slot>
|
|
<div
|
|
:class="{
|
|
'hc-drag-marker-post': true,
|
|
'hc-drag-marker-update-post': contribution,
|
|
}"
|
|
>
|
|
<base-icon name="image" />
|
|
</div>
|
|
</div>
|
|
</vue-dropzone>
|
|
</template>
|
|
|
|
<script>
|
|
import vueDropzone from 'nuxt-dropzone'
|
|
import Cropper from 'cropperjs'
|
|
import 'cropperjs/dist/cropper.css'
|
|
|
|
export default {
|
|
components: {
|
|
vueDropzone,
|
|
},
|
|
props: {
|
|
contribution: { type: Object, default: () => {} },
|
|
},
|
|
data() {
|
|
return {
|
|
dropzoneOptions: {
|
|
url: () => '',
|
|
maxFilesize: 5.0,
|
|
previewTemplate: this.template(),
|
|
},
|
|
image: null,
|
|
file: null,
|
|
editor: null,
|
|
cropper: null,
|
|
thumbnailElement: null,
|
|
oldImage: null,
|
|
error: false,
|
|
showCropper: false,
|
|
}
|
|
},
|
|
watch: {
|
|
error() {
|
|
const that = this
|
|
setTimeout(function() {
|
|
that.error = false
|
|
}, 2000)
|
|
},
|
|
},
|
|
methods: {
|
|
template() {
|
|
return `<div class="dz-preview dz-file-preview">
|
|
<div class="dz-image">
|
|
<div data-dz-thumbnail-bg></div>
|
|
</div>
|
|
</div>
|
|
`
|
|
},
|
|
verror(file, message) {
|
|
this.error = true
|
|
this.$toast.error(file.status, message)
|
|
},
|
|
transformImage(file) {
|
|
this.file = file
|
|
this.showCropper = true
|
|
this.initEditor()
|
|
this.initCropper()
|
|
},
|
|
initEditor() {
|
|
this.editor = this.$refs.cropperOverlay
|
|
this.clearImages()
|
|
this.thumbnailElement.appendChild(this.editor)
|
|
},
|
|
clearImages() {
|
|
this.thumbnailElement = document.querySelectorAll('#postdropzone')[0]
|
|
const thumbnailPreview = document.querySelectorAll('.thumbnail-preview')[0]
|
|
if (thumbnailPreview) thumbnailPreview.remove()
|
|
const contributionImage = document.querySelectorAll('.contribution-image')[0]
|
|
this.oldImage = contributionImage
|
|
if (contributionImage) contributionImage.remove()
|
|
},
|
|
initCropper() {
|
|
this.image = new Image()
|
|
this.image.src = URL.createObjectURL(this.file)
|
|
this.editor.appendChild(this.image)
|
|
this.cropper = new Cropper(this.image, { zoomable: false, autoCropArea: 0.9 })
|
|
},
|
|
cropImage() {
|
|
this.showCropper = false
|
|
const canvas = this.cropper.getCroppedCanvas()
|
|
canvas.toBlob(blob => {
|
|
this.setupPreview(canvas)
|
|
this.removeCropper()
|
|
const croppedImageFile = new File([blob], this.file.name, { type: 'image/jpeg' })
|
|
this.$emit('addTeaserImage', croppedImageFile)
|
|
}, 'image/jpeg')
|
|
},
|
|
setupPreview(canvas) {
|
|
this.image = new Image()
|
|
this.image.src = canvas.toDataURL()
|
|
this.image.classList.add('thumbnail-preview')
|
|
this.thumbnailElement.appendChild(this.image)
|
|
},
|
|
cancelCrop() {
|
|
this.showCropper = false
|
|
if (this.oldImage) this.thumbnailElement.appendChild(this.oldImage)
|
|
this.removeCropper()
|
|
},
|
|
removeCropper() {
|
|
this.editor.removeChild(document.querySelectorAll('.cropper-container')[0])
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
<style lang="scss">
|
|
#postdropzone {
|
|
width: 100%;
|
|
min-height: 500px;
|
|
background-color: $background-color-softest;
|
|
}
|
|
|
|
.hc-attachments-upload-area-post {
|
|
position: relative;
|
|
display: flex;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.hc-attachments-upload-area-update-post img {
|
|
object-fit: cover;
|
|
object-position: center;
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
|
|
.hc-attachments-upload-area-update-post:hover {
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.hc-drag-marker-post {
|
|
position: absolute;
|
|
width: 122px;
|
|
height: 122px;
|
|
border-radius: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 180px 5px;
|
|
color: hsl(0, 0%, 25%);
|
|
transition: all 0.2s ease-out;
|
|
font-size: 60px;
|
|
background-color: $background-color-softest;
|
|
opacity: 0.65;
|
|
|
|
&:before {
|
|
position: absolute;
|
|
content: '';
|
|
top: 0;
|
|
left: 0;
|
|
bottom: 0;
|
|
right: 0;
|
|
border-radius: 100%;
|
|
border: 20px solid $text-color-base;
|
|
visibility: hidden;
|
|
}
|
|
|
|
&:after {
|
|
position: absolute;
|
|
content: '';
|
|
top: 10px;
|
|
left: 10px;
|
|
bottom: 10px;
|
|
right: 10px;
|
|
border-radius: 100%;
|
|
border: $border-size-base dashed $text-color-base;
|
|
}
|
|
|
|
.hc-attachments-upload-area-post:hover & {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.hc-drag-marker-update-post {
|
|
opacity: 0;
|
|
}
|
|
|
|
.contribution-form-footer {
|
|
border-top: $border-size-base solid $border-color-softest;
|
|
}
|
|
|
|
.crop-overlay {
|
|
max-height: 2000px;
|
|
position: relative;
|
|
width: 100%;
|
|
background-color: #000;
|
|
}
|
|
|
|
.crop-confirm {
|
|
position: absolute;
|
|
left: 10px;
|
|
top: 10px;
|
|
z-index: 1;
|
|
}
|
|
.crop-cancel {
|
|
position: absolute;
|
|
right: 10px;
|
|
top: 10px;
|
|
z-index: 1;
|
|
}
|
|
</style>
|