126 lines
3.8 KiB
JavaScript
126 lines
3.8 KiB
JavaScript
import { Controller } from '@hotwired/stimulus'
|
|
import { Dropzone } from 'dropzone'
|
|
import Cropper from 'cropperjs'
|
|
|
|
export default class extends Controller {
|
|
static values = {
|
|
avatarImage: String,
|
|
userId: Number
|
|
}
|
|
|
|
connect() {
|
|
let avatarDropzone = new Dropzone('#avatarDropzone', {
|
|
url: `/user/upload/avatar/${this.userIdValue}`,
|
|
avatarUrl: this.avatarImageValue,
|
|
acceptedFiles: '.jpg, .jpeg, .png, gif',
|
|
maxFiles: 1,
|
|
dictDefaultMessage: '',
|
|
init() {
|
|
avatarDropzone = this
|
|
// If the thumbnail is already in the right size on your server:
|
|
const mockFile = { name: 'Filename', size: 12345 }
|
|
const callback = null // Optional callback when it's done
|
|
const crossOrigin = null // Added to the `img` tag for crossOrigin handling
|
|
const resizeThumbnail = false // Tells Dropzone whether it should resize the image first
|
|
avatarDropzone.displayExistingFile(
|
|
mockFile,
|
|
avatarDropzone.options.avatarUrl,
|
|
callback,
|
|
crossOrigin,
|
|
resizeThumbnail
|
|
)
|
|
avatarDropzone.files.push(mockFile) // line missing in official docs
|
|
},
|
|
transformFile(file, done) {
|
|
// Create the image editor overlay
|
|
const editor = document.createElement('div')
|
|
editor.style.position = 'fixed'
|
|
editor.style.left = '25px'
|
|
editor.style.right = '25px'
|
|
editor.style.top = '25px'
|
|
editor.style.bottom = '25px'
|
|
editor.style.zIndex = '9999'
|
|
editor.style.borderRadius = '15px;'
|
|
editor.style.borderColor = '#FF8844'
|
|
editor.style.backgroundColor = '#000'
|
|
document.body.appendChild(editor)
|
|
|
|
// Create an image node for Cropper.js
|
|
const image = new Image()
|
|
image.src = URL.createObjectURL(file)
|
|
editor.appendChild(image)
|
|
|
|
// Create Cropper.js
|
|
const cropper = new Cropper(image, { aspectRatio: 1 })
|
|
|
|
// Create confirm button at the top left of the viewport
|
|
const buttonCrop = document.createElement('button')
|
|
buttonCrop.style.position = 'absolute'
|
|
buttonCrop.style.right = '10px'
|
|
buttonCrop.style.bottom = '50px'
|
|
buttonCrop.style.zIndex = '9999'
|
|
buttonCrop.textContent = 'Crop'
|
|
buttonCrop.className = 'btn btn-secondary'
|
|
editor.appendChild(buttonCrop)
|
|
buttonCrop.addEventListener('click', () => {
|
|
// clear preview
|
|
//formElement.style.backgroundImage = ''
|
|
|
|
const canvas = cropper.getCroppedCanvas({
|
|
width: 256,
|
|
height: 256
|
|
})
|
|
canvas.toBlob((blob) => {
|
|
avatarDropzone.createThumbnail(
|
|
blob,
|
|
avatarDropzone.options.thumbnailWidth,
|
|
avatarDropzone.options.thumbnailHeight,
|
|
avatarDropzone.options.thumbnailMethod,
|
|
false,
|
|
(dataURL) => {
|
|
avatarDropzone.emit('thumbnail', file, dataURL)
|
|
done(blob)
|
|
}
|
|
)
|
|
})
|
|
|
|
// Remove the editor from the view
|
|
document.body.removeChild(editor)
|
|
})
|
|
|
|
// Create keep original button
|
|
const buttonKeep = document.createElement('button')
|
|
buttonKeep.style.position = 'absolute'
|
|
buttonKeep.style.right = '100px'
|
|
buttonKeep.style.bottom = '50px'
|
|
buttonKeep.style.zIndex = '9999'
|
|
buttonKeep.textContent = 'Keep Original'
|
|
buttonKeep.className = 'btn btn-primary'
|
|
buttonKeep.focus()
|
|
editor.appendChild(buttonKeep)
|
|
buttonKeep.addEventListener('click', () => {
|
|
//formElement.style.backgroundImage = ''
|
|
|
|
// Remove the editor from the view
|
|
this.removeAllFiles()
|
|
|
|
done(file)
|
|
document.body.removeChild(editor)
|
|
})
|
|
|
|
// info text
|
|
const infoText = document.createElement('span')
|
|
infoText.style.position = 'absolute'
|
|
infoText.style.opacity = '0.5'
|
|
infoText.style.left = '100px'
|
|
infoText.style.bottom = '50px'
|
|
infoText.style.display = 'inline:block'
|
|
infoText.style.zIndex = '9999'
|
|
infoText.textContent = 'Use mouse wheel/touchpad to adapt size'
|
|
infoText.className = 'btn btn-secondary'
|
|
editor.appendChild(infoText)
|
|
}
|
|
})
|
|
}
|
|
}
|