Files
consumocuidado/components/FormInputImage.vue
2025-08-21 11:55:20 +02:00

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>