Como criar uma ferramenta de compressor de imagem em javascript

As imagens podem afetar o desempenho do seu site se não forem otimizadas adequadamente. Uma das maneiras de resolver esse problema é garantir que as imagens sejam otimizadas reduzindo o tamanho do arquivo.

As imagens adequadamente otimizadas carregam mais rápido e também fornecem uma melhor experiência do usuário. Construir o nosso também será um ótimo exercício para aprender JavaScript. Então, vamos construir um!

Resultado final

Aqui está o que estamos construindo:

Construindo a interface

Teremos uma interface HTML simples como esta:

1
 class="container">
2
  

Image Compressor

3
  Resize images to a smaller size without losing quality.

4

5
   for="file-input">Choose an image
6
  
7
    type="file"
8
    id="file-input"
9
    style="display: none"
10
    accept="image/*"
11
  />
12

13
 class="preview">
14
   class="preview-image" src="" alt="" />
15
   id="fileName">

16
   class="compress-button">Compress and Download image
17

Em nosso HTML, temos um campo para fazer upload da imagem, uma área de visualização para exibir a imagem carregada e um Compressa e Download botão para comprimir e baixar a imagem final

Modelando a ferramenta de compressor de imagem

Hora de alguns CSs. Vamos começar estilizando o corpo e o contêiner de visualização:

1
@import url("https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap");
2

3
body {
4
  display: flex;
5
  justify-content: center;
6
  align-items: center;
7
  flex-direction: column;
8
  height: 100vh;
9
  margin: 0;
10
  background-color: #ffffff;
11
  text-align: center;
12
  font-family: "DM Mono", monospace;
13
}
14
.container, .preview {
15
  width: 80%;
16
  max-width: 500px;
17
  margin: 0 auto;
18
  text-align: center;
19
  background-color: #ffffff;
20
  padding: 30px;
21
  border-radius: 8px;
22
  border: #f3ecec solid 1px;
23
}

Por padrão, escondemos o contêiner de visualização usando display: none;. Isso garantirá que ele se torne visível quando um usuário enviar uma imagem. Adicione os seguintes estilos aos elementos de visualização.

1
.preview {
2
  display: none;
3
}
4

5
.preview-image {
6
  max-width: 100%;
7
  max-height: 200px;
8
  margin-top: 20px;
9
}

Finalmente, vamos estilizar o rótulo e o botão de compressão para uma melhor interatividade do usuário.

1
label{
2
  display: inline-block;
3
}
4

5
label,
6
.compress-button {
7
  padding: 12px 24px;
8
  background-color: #3498db;
9
  color: white;
10
  cursor: pointer;
11
  border-radius: 6px;
12
  transition: all 0.3s ease;
13
  font-weight: bold;
14
  text-transform: uppercase;
15
  font-size: 0.9rem;
16
  border: none;
17
  margin-top: 20px;
18
}

Implementando recursos de compactação de imagem e download

Com a interface pronta, é hora de adicionar os recursos de compactação de imagem e baixar com JavaScript. Primeiro, vamos obter todos os elementos que precisam de manipulação.

1
const fileInput = document.getElementById("file-input");
2
const previewImage = document.querySelector(".preview-image");
3
const compressBtn = document.querySelector(".compress-button");
4
const container = document.querySelector(".container");
5
const fileName = document.getElementById("fileName");
6
const preview = document.querySelector(".preview");

Upload de imagem

Para lidar com uploads de imagem, usaremos o JavaScript FileReader API. Esta API nos permite ler o conteúdo dos arquivos selecionados pelo usuário, tornando -o perfeito para nossas necessidades. O primeiro passo é adicionar um ouvinte de evento ao elemento de entrada do arquivo e ouvir o change evento.

1
fileInput.addEventListener("change", (e) => {
2
  const file = e.target.files[0];
3
  console.log(file);
4
  if (file) {
5
    const reader = new FileReader();
6
    reader.onload = (e) => {
7
     // preview image code
8
    };
9
    reader.readAsDataURL(file);
10
  } else {
11
    alert("no file selected");
12
  }
13
});

Quando um arquivo é selecionado, o change o evento será acionado e o arquivo recuperado usando e.target.files[0]. O FileReader API fornece vários métodos, mas aqui usaremos o onload Evento que é disparado automaticamente quando o arquivo é lido com sucesso.

O FileReader.readAsDataURL O método lê o conteúdo do arquivo de imagem e produz um URL representando os dados da imagem. Este URL de dados é armazenado no atributo resultado do objeto de evento. A partir do atributo de resultado, podemos atribuir o URL de dados da imagem ao src propriedade de um elemento de imagem para visualização.

Atualize o código da seguinte forma.

1
fileInput.addEventListener("change", (e) => {
2
  const file = e.target.files[0];
3
  console.log(file);
4
  if (file) {
5
    const reader = new FileReader();
6
    reader.onload = (e) => {
7
      previewImage.src = e.target.result;
8
      previewImage.style.display = "inline-block";
9
      fileName.textContent = file.name;
10
      preview.style.display = "block";
11
      container.style.display = "none";
12
    };
13
    reader.readAsDataURL(file);
14
  } else {
15
    alert("no file selected");
16
  }
17
});

Agora, quando você envia uma imagem, pode ver uma visualização da imagem antes da compactação.

Compressa e baixe a imagem

O último recurso é a capacidade de comprimir e baixar a imagem compactada. Para fazer isso, faremos o seguinte:

  • Crie um novo Image objeto e carregue a imagem a ser compactada
  • Usar Para redimensionar a imagem
  • Converta o conteúdo da tela em uma bolha.
  • Baixe a nova imagem compactada

Adicione um evento de clique no botão de compactação.

1
compressBtn.addEventListener("click", () => {
2

3
});

Em seguida, crie um objeto de imagem e defina seu src atributo à fonte da imagem de visualização; Isso garante que a imagem carregada seja a que está sendo redimensionada e compactada. Então defina seu onload Evento para garantir que a imagem esteja totalmente carregada antes de executar quaisquer operações. Em seguida, crie um elemento de tela e defina as dimensões para 50% das imagens height e width .

Usando o drawImage() Método, desenhe a imagem redimensionada na tela.

1
compressBtn.addEventListener("click", () => {
2
  const img = new Image();
3
  img.src = previewImage.src;
4

5
  img.onload = () => {
6
    const canvas = document.createElement("canvas");
7
    const ctx = canvas.getContext("2d");
8
    const width = img.width * 0.5;
9
    const height = img.height * 0.5;
10
    canvas.width = width;
11
    canvas.height = height;
12
    ctx.drawImage(img, 0, 0, width, height);
13
  };
14
 
15
});

Nossa imagem já foi redimensionada. O próximo passo é aplicar compressão.

Compressa a imagem redimensionada

A última etapa é exportar os dados do Canvas como um arquivo de imagem em um formato JPEG e executar compactação. Para fazer isso, usaremos o canvas.toBlob() Método que gera uma representação do BLOB do conteúdo da tela. O .toBlob() aceita uma função de retorno de chamada e dois argumentos opcionais: o MIME Tipo (ou seja image/jpeg ou image/png) e um parâmetro de qualidade opcional (0,7 aqui) para controlar o nível de compressão.

No nosso caso, o código será assim.

1
compressBtn.addEventListener("click", () => {
2
  const img = new Image();
3

4
  img.onload = () => {
5
    const canvas = document.createElement("canvas");
6
    const ctx = canvas.getContext("2d");
7
    const width = img.width * 0.5;
8
    const height = img.height * 0.5;
9
    canvas.width = width;
10
    canvas.height = height;
11
    ctx.drawImage(img, 0, 0, width, height);
12

13
  
14
    canvas.toBlob(
15
      (blob) => {
16
       
17
        const url = URL.createObjectURL(blob);
18
        const a = document.createElement("a");
19
        a.href = url;
20
        a.download = "compressed_" + fileName.textContent;
21
        document.body.appendChild(a);
22
        a.click();
23
        document.body.removeChild(a);
24
        URL.revokeObjectURL(url);
25
      },
26
      "image/jpeg",
27
      0.7
28
    ); 
29
  };
30
  img.src = previewImage.src;
31
});

Para baixar a imagem, seguimos estas etapas:

Aqui está a demonstração final como um lembrete:

Conclusão

Para demonstrar, peguei uma imagem do Unsplash e a compactei com a nossa ferramenta. Com as configurações atuais, carrego o original (3,3 MB) e baixei uma versão compactada (314KB). É verdade que a imagem resultante é metade das dimensões do pixel (6.000 x 3.000px vs. 3.000 x 1.500px), mas as duas imagens são indistinguíveis ao olho humano.

gato de unsplashgato de unsplashgato de unsplash

Alterar o parâmetro de qualidade para apenas 0,2 nos fornece outra imagem indistinguível, mas desta vez 76kb. Claramente, haverá diferenças de qualidade, por isso é uma questão de você encontrar o equilíbrio certo. Você pode até fazer um controle na interface do usuário para especificar a quantidade de compactação.

Então, lá vamos nós – utilizando JavaScript e o elemento Canvas, vimos como podemos facilmente comprimir imagens sem comprometer a qualidade. Felizmente, isso oferecerá uma solução confiável quando você precisar otimizar as imagens para a Web.

Deixe uma resposta