116 lines
2.4 KiB
Vue
116 lines
2.4 KiB
Vue
<template>
|
|
<div class="form-container">
|
|
<input class="input" type="file" @change="loadImage" />
|
|
|
|
<!-- Editor -->
|
|
<div v-show="edit">
|
|
<cropper
|
|
ref="cropperRef"
|
|
class="cropper"
|
|
:src="croppieImage"
|
|
:stencil-props="{ aspectRatio: 1 }"
|
|
/>
|
|
<div class="buttons">
|
|
<button class="filter-button" @click.prevent="crop">Aplicar</button>
|
|
<button @click.prevent="cancel">Cancelar</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Result -->
|
|
<div v-show="cropped && !edit">
|
|
<img :src="cropped" @click.prevent="editImage" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { Cropper } from "vue-advanced-cropper";
|
|
import "vue-advanced-cropper/dist/style.css";
|
|
|
|
export default {
|
|
components: { Cropper },
|
|
props: {
|
|
imageUrl: {
|
|
type: [String, Object],
|
|
default: null,
|
|
},
|
|
},
|
|
emits: ["change"],
|
|
data() {
|
|
return {
|
|
croppieImage: "",
|
|
cropped: null,
|
|
edit: false,
|
|
};
|
|
},
|
|
mounted() {
|
|
if (typeof this.imageUrl === "string") {
|
|
this.croppieImage = this.imageUrl;
|
|
this.cropped = this.imageUrl;
|
|
}
|
|
},
|
|
methods: {
|
|
editImage() {
|
|
this.edit = true;
|
|
},
|
|
cancel() {
|
|
this.edit = false;
|
|
},
|
|
loadImage(e) {
|
|
const file = e.target.files?.[0];
|
|
if (!file) return;
|
|
|
|
const reader = new FileReader();
|
|
reader.onload = (evt) => {
|
|
this.croppieImage = evt.target.result;
|
|
this.edit = true;
|
|
};
|
|
reader.readAsDataURL(file);
|
|
},
|
|
crop() {
|
|
const canvas = this.$refs.cropperRef.getResult().canvas;
|
|
if (canvas) {
|
|
const base64 = canvas.toDataURL("image/png");
|
|
this.cropped = base64;
|
|
|
|
// Emitir como File
|
|
canvas.toBlob((blob) => {
|
|
if (blob) {
|
|
const fileName =
|
|
Math.random().toString(36).substring(2, 15) + ".png";
|
|
const file = new File([blob], fileName, { type: "image/png" });
|
|
this.$emit("change", file);
|
|
}
|
|
}, "image/png");
|
|
}
|
|
this.edit = false;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.form-container {
|
|
width: 100%;
|
|
}
|
|
.cropper {
|
|
width: 500px;
|
|
height: 500px;
|
|
}
|
|
.filter-button {
|
|
background-color: $color-navy;
|
|
color: $color-light;
|
|
font-size: $xs;
|
|
padding: 0.5em 0.8em;
|
|
border-radius: 5px;
|
|
}
|
|
.input {
|
|
max-width: 100%;
|
|
margin-bottom: 1em;
|
|
}
|
|
|
|
.buttons {
|
|
margin-top: 1em;
|
|
}
|
|
</style>
|