Utilisation de Canvas dans Vue 3.2 pour compresser et manipuler des images locales

https://www.canvasapi.cn/

  1. Référencement de l'élément canvas

Nous utilisons la directive ref pour référencer notre élément canvas, ce qui nous permet d'appeler directement ses méthodes.

<template>
  <canvas ref="canvasRef" :width="489" :height="34" style="width: 489px;height: 34px;background-color: pink">
  </canvas>
</template>
// Obtenir la référence de l'élément canvas
const canvasRef = ref(null)
  1. Sélection d'une image locale

Lorsqu'une image est sélectionnée, nous appelons immédiatement notre fonction de traitement canvas. Il est crucial d'atetndre le chargement complet de l'image avant de la traiter, d'où l'utilisation de l'événement onload.

<label class="btn" for="fileInput">Sélectionner un fichier image</label>
<input
    type="file"
    id="fileInput"
    ref="fileInputRef"
    style="position: absolute; clip: rect(0 0 0 0)"
    accept="image/png, image/jpeg, image/gif, image/jpg"
    @change="handleImageSelection($event)"
/>

Dans notre setup, nous définissons les options nécessaires :

const imageOptions = reactive({
  source: '',    // URL de l'image source
})
// Gestion de la sélection d'image
const handleImageSelection = function(event) {
  if(!event.target.files.length) return;
  
  // Validation du type de fichier
  if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(event.target.value)) {
    alert('Types d\'image acceptés : jpeg, jpg, png');
    return false;
  }
  
  const file = event.target.files[0];
  const fileNameParts = file.name.split('.');
  const selectedImageType = fileNameParts[fileNameParts.length-1];
  
  const reader = new FileReader();
  
  reader.onload = (e) => {
    let imageData;
    if (typeof e.target.result === 'object') {
      imageData = window.URL.createObjectURL(new Blob([e.target.result]));
    } else {
      imageData = e.target.result;
    }
    
    imageOptions.source = imageData;
    
    // Appel du traitement canvas
    processCanvasImage();
  };
  
  // Conversion en base64
  reader.readAsDataURL(file);
}
  1. Traitement Canvas : compression, positionnement et préparation au téléversement

Voici comment nous utilisons Canvas pour compresser et positionner notre image :

const processCanvasImage = () => {
  // Récupération du contexte canvas
  const context = canvasRef.value.getContext("2d");
  
  // S'il y a déjà une image traitée, on efface le canvas
  if(processedImageData.value) {
    context.clearRect(0, 0, 489, 34);
    processedImageData.value = "";
  }
  
  // Création de l'objet image
  const image = new Image();
  image.src = imageOptions.source;
  
  // Traitement après chargement de l'image
  image.onload = () => {
    // Dimensions originales
    const originalWidth = image.width;
    const originalHeight = image.height;
    
    // Calcul des nouvelles dimensions (hauteur fixe à 34px)
    const scaledWidth = 34 * originalWidth / originalHeight;
    const scaledHeight = 34;
    
    // Calcul de la position horizontale pour centrer l'image
    const horizontalOffset = (489 - scaledWidth) / 2;
    
    // Dessin de l'image sur le canvas
    context.drawImage(image, horizontalOffset, 0, scaledWidth, scaledHeight);
    
    // Conversion en base64
    processedImageData.value = canvasRef.value.toDataURL();
  };
}
  1. Convresion en Blob et téléversement

Une fois l'image traitée, nous la convertissosn en Blob pour la téléverser :

const uploadProcessedImage = () => {
  canvasRef.value.toBlob(async (blobData) => {
    const formData = new FormData();
    formData.append('imageFile', blobData, `LOGO.${selectedImageType.value}`);
    formData.append('hospitalId', hospitalData.value.id);
    
    // Indicateur de chargement
    isUploading.value = true;
    
    // Appel API de téléversement
    uploadImage(formData).then(response => {
      if (response.code === 200) {
        showNotification("Image téléversée avec succès", 'success');
        refreshHospitalData();
        isUploading.value = false;
      } else {
        showNotification(response.msg || "Erreur lors du téléversement", 'error');
        isUploading.value = false;
      }
    }).catch(error => {
      showNotification("Erreur réseau", 'error');
      isUploading.value = false;
    });
  });
}

Fonction utilitaire pour les notifications :

const showNotification = (message, type) => {
  ElMessage({
    message: message,
    type: type,
    showClose: true,
    duration: 2000,
  });
};

Étiquettes: Vue.js Canvas JavaScript traitement d'images Téléversement de fichiers

Publié le 3 juin à 17h09