Descripción general
En los mini-programas de WeChat, una funcionalidad común es permitir a los usuarios seleccinoar una imagen de su galería o cámara, recortarla en un formato específico (generalmente cuadrado para fotos de perfil) y enviarla al servidor. Este artículo detalla la implementación utilizando la librería WeCropper.
Configuración del componente de recorte
El primer paso es configurar las opciones del recortador de imágenes en el archivo de lógica de la página. Se obtienen las dimensiones del dispositivo para crear un área de trabajo proporcional.
// Obtención de información del dispositivo
const infoDispositivo = wx.getSystemInfoSync();
const anchoCanvas = infoDispositivo.windowWidth;
const altoCanvas = infoDispositivo.windowHeight - 150;
// Configuración de opciones del recortador
data: {
fotoPerfil: "",
opcionesRecortador: {
id: 'lienzoRecorte',
idDestino: 'lienzoDestino',
pixelRatio: infoDispositivo.pixelRatio,
width: anchoCanvas,
height: altoCanvas,
imagenOrigen: '',
escalaMaxima: 2.5,
factorZoom: 8,
areaRecorte: {
x: (anchoCanvas - 140) / 2,
y: (anchoCanvas - 140) / 2,
ancho: 140,
alto: 140
}
}
}
Inicialización del recortador
En el evento onLoad, se inicializa el componente WeCropper y se configura la imagen inicial si existe previamente.
onLoad: function(opciones) {
const { opcionesRecortador } = this.data;
// Cargar imagen previa si existe
if (app.datosGlobales.fotoPerfil) {
opcionesRecortador.imagenOrigen = app.datosGlobales.fotoPerfil;
} else {
opcionesRecortador.imagenOrigen = 'imagen_predeterminada';
}
if (opcionesRecortador.imagenOrigen) {
this.recortador = new WeCropper(opcionesRecortador)
.on('ready', (contexto) => {
console.log('Recortador inicializado correctamente');
})
.on('antesCarga', (contexto) => {
wx.showToast({
titulo: 'Cargando imagen',
icono: 'loading',
duracion: 3000
});
})
.on('imagenCargada', (contexto) => {
wx.hideToast();
});
}
}
Manejo de eventos táctiles
El插件 recibe eventos táctiles para permitir al usuario manipular la imagen dentro del área de recorte mediante gestos de arrastre y zoom.
// Eventos táctiles para el recortador
iniciarTocar(evento) {
this.recortador.iniciarTocar(evento);
},
moverTocar(evento) {
this.recortador.moverTocar(evento);
},
finalizarTocar(evento) {
this.recortador.finalizarTocar(evento);
}
Selección de imagen
Esta función permite al usuario elegir una nueva imagen desde la galería o la cámara del dispositivo.
seleccionarImagen() {
const referencia = this;
wx.elegirImagen({
cantidad: 1,
tipoTamano: ['comprimido'],
origen: ['album', 'camara'],
exito(resultado) {
const rutaOrigen = resultado.tempFilePaths[0];
referencia.recortador.insertarOrigen(rutaOrigen);
setTimeout(() => {
referencia.generarImagenRecortada();
}, 2000);
}
});
}
Generación y envío de imagen
Una vez que el usuario ha ajustado el recorte, se genera la imagen procesada y se envía al servidor mediante uploadFile.
generarImagenRecortada() {
var aqui = this;
this.recortador.obtenerImagenRecortada((rutaTemporal) => {
if (rutaTemporal) {
console.log('Imagen procesada:', rutaTemporal);
wx.showToast({
titulo: 'Enviando...',
icono: 'loading',
mascara: true,
duracion: 10000
});
let token = wx.obtenerStorageSync("cookie");
wx.subirArchivo({
url: app.datosGlobales.host + '/api/cliente/info/recopilar/subirFoto',
rutaArchivo: rutaTemporal,
nombre: 'archivo',
header: {
"Content-type": "multipart/form-data",
"cookie": token
},
exito: function(respuesta) {
if (respuesta.statusCode == 200) {
console.log(JSON.parse(respuesta.data).data);
}
aqui.setData({
fotoPerfil: JSON.parse(respuesta.data).data
});
app.datosGlobales.fotoPerfil = JSON.parse(respuesta.data).data;
aqui.guardarDatos(3);
},
fallo: function(respuesta) {
wx.hideToast();
wx.showModal({
titulo: 'Error',
contenido: 'Error al subir la imagen',
mostrarCancelar: false
});
}
});
} else {
console.log('Error al obtener la imagen procesada');
}
});
}
Guardado de información
Finalmente, se guardan los datos del perfil del usuario, incluyendo la URL de la imagen procesada.
async guardarDatos(tipo) {
let parametros = {};
if (tipo == '3') {
parametros.fotoPerfil = this.data.fotoPerfil;
app.datosGlobales.fotoPerfil = this.data.fotoPerfil;
}
let respuesta = await Util.peticion('/endpoint/actualizar', parametros, true);
if (respuesta) {
wx.showToast({
titulo: 'Guardado exitosamente',
mascara: true
});
setTimeout(() => {
this.obtenerInfoUsuario();
}, 1500);
}
}
Estructura WXML
La plantilla WXML integra el componente del recortador y el área de visualización de la foto de perfil.
<import src="./we/we-cropper.wxml"/>
<view class="contenedor-recortador">
<template is="we-cropper" data="{{...opcionesRecortador}}"/>
</view>
<view class="seccion-perfil">
<view class="contenedor-foto" bindtap='seleccionarImagen'>
<view class="cuadro-foto">
<view class="imagen-foto">
<image src="{{fotoPerfil}}" class="imagen-deslizable" mode="widthFix" />
</view>
<view class="icono-camara">
<image src="https://ejemplo.com/icono-camara.png" class="imagen-deslizable" mode="widthFix" />
</view>
</view>
</view>
</view>
Plantilla del componente
El archivo WXML del插件 define dos elementos canvas: uno para la interación del usuario y otro para generar la imagen resultado.
<template name="we-cropper">
<canvas
class="recortador"
disable-scroll="true"
bindtouchstart="iniciarTocar"
bindtouchmove="moverTocar"
bindtouchend="finalizarTocar"
style="width:{{ancho}}px;height:{{alto}}px;background-color: rgba(0, 0, 0, 0.8)"
canvas-id="{{id}}">
</canvas>
<canvas
class="recortador"
disable-scroll="true"
style="position: fixed; top: -{{ancho * pixelRatio}}px; left: -{{alto * pixelRatio}}px; width:{{ancho * pixelRatio}}px;height:{{alto * pixelRatio}}px;"
canvas-id="{{idDestino}}">
</canvas>
</template>
Consideraciones importantes
- El插件 requiere la inclusión de los archivos JavaScript y WXML en el proyecto
- Es necesario ajustar las dimensiones del área de recorte según los requisitos de la aplicación
- El tiempo de espera de 2 segundos después de seleccionar la imagen garantiza que el recortador esté listo antes de generar el resultado
- La imagen se envía como multipart/form-data al endpoint correspondiente del servidor