Spookie/assets/controllers/upload-avatar_controller.js

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)
}
})
}
}