Gerenciando pontos de interrupção de imagem com Angular
Publicados: 2022-03-10Como desenvolvedores da Web, muitas vezes somos obrigados a criar aplicativos que sejam responsivos e ricos em mídia. Ter esses requisitos em vigor significa que precisamos trabalhar com pontos de interrupção de imagem, bem como consultas de mídia, pois queremos fornecer a melhor experiência aos usuários finais. Adicionando à lista de requisitos, podemos precisar usar uma estrutura de front-end como o Angular, que é ótimo para criar SPAs e outros tipos de aplicativos.
Neste artigo, veremos os pontos de interrupção da imagem, seus casos de uso e um exemplo prático; vamos implementá-los em um aplicativo Angular usando o próprio BreakPoint Observer do Angular. Ao usar essa abordagem, também destacaremos por que essa estrutura popular nos ajuda a trabalhar com as técnicas mencionadas de maneira integrada.
Pontos de interrupção de imagem e imagens responsivas
Na era dos layouts responsivos (onde capturamos pontos de interrupção com base no tamanho da janela de visualização e com base no ponto de interrupção alteramos o layout da página), também precisamos garantir que as imagens possam ser exibidas com as dimensões corretas - mesmo após um layout mudança. Selecionar a imagem certa é bastante desafiador para sites responsivos modernos.
Vamos discutir duas opções que os desenvolvedores podem utilizar no momento.
srcset
srcset
nos permite definir uma lista de imagens entre as quais o navegador alterna com base no tamanho <img>
renderizado e na densidade da exibição.
Vejamos um exemplo:
<img src="tuscany.jpg" />
No exemplo acima, especificamos 3 imagens, com o w
indicando a largura do pixel para a imagem. Ao usar o acima com srcset
, também precisamos especificar o atributo de sizes
(isso é necessário porque a especificação exige que, se usarmos srcset
e w
, devemos ter um atributo de tamanhos também). Qual é o propósito deste atributo? Os navegadores precisam escolher qual recurso carregar de um conjunto de fontes antes de fazer o layout da página (antes de saberem o tamanho da imagem). Podemos pensar nos sizes
como uma dica para o navegador de que, após o layout, a imagem ocupará 100% da largura da janela de visualização (é a isso que vw
se refere). O navegador sabe a largura real da janela de visualização (assim como o DPR da imagem) no momento do carregamento, para que possa fazer as contas para descobrir o tamanho do recurso necessário e escolher um do conjunto de origem.
As combinações de elementos <picture>
e <source media="">
nos permitem alternar recursos de imagem em resposta a consultas de mídia, como aquelas em pontos de interrupção de layout.
Vejamos também um exemplo disso:
<picture> <source media="(min-width: 1440px)"> <source media="(min-width: 900px)"> <source media="(min-width: 600px)"> <img src="../assets/images/tuscany-sm.jpg" /> </picture>
Altere o código acima localmente com uma imagem de sua escolha que tenha tamanho pequeno, médio e grande. Observe como, ao redimensionar o navegador, você obtém uma imagem diferente.
A principal conclusão de todos os itens acima é que, se quisermos trocar imagens em pontos de interrupção específicos, podemos usar o elemento <picture>
para colocar consultas de mídia diretamente na marcação.
Nota : Se você estiver interessado em explorar as diferenças entre <picture>
e srcset
+ sizes
, recomendo a leitura do ótimo artigo de Eric Portis: srcset
and sizes
.
Até agora, discutimos como usar pontos de interrupção de imagem junto com consultas de mídia em um ambiente HTML puro. Não seria muito melhor ter uma maneira conveniente e quase semiautomática de gerar pontos de interrupção de imagem, bem como as imagens correspondentes para os pontos de interrupção, mesmo sem precisar especificar consultas de mídia? Felizmente para nós, o Angular tem um mecanismo embutido para nos ajudar e também vamos dar uma olhada na geração das imagens apropriadas dinamicamente com base em certas condições usando um serviço de terceiros.
Módulo de Layout Angular
O Angular vem com um Módulo de Layout que reside no conjunto de ferramentas CDK (Component Dev Kit). O Angular CDK contém ferramentas bem testadas para auxiliar no desenvolvimento de componentes. Uma parte do CDK é o Módulo de Layout que contém um BreakpointObserver
. Esse auxiliar dá acesso a pontos de interrupção de consulta de mídia, o que significa que os componentes (e seus conteúdos) podem se adaptar às alterações quando o tamanho do navegador (tamanho da tela) é alterado intuitivamente.
Leitura recomendada : Módulo de Layout
Agora que temos a teoria fora do caminho, vamos direto ao assunto e criar um aplicativo que implementará pontos de interrupção de imagem responsivos. Nesta primeira iteração, criaremos o shell do aplicativo por meio da CLI Angular: ng new bpo
e selecionaremos as opções necessárias.
Para usar o BreakpointObserver
também precisamos instalar o CDK Layout Module do Angular, que podemos fazer via npm: npm i @angular/cdk
.
Após a instalação, poderemos adicionar as instruções de importação necessárias a qualquer componente que desejarmos:
// app.component.ts import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
Usando o BreakpointObserver
, podemos assinar alterações na largura da janela de visualização e o Angular nos fornece acessores convenientes, o que significa que não precisamos usar consultas de mídia! Vamos em frente e tente isso:
// app.component.ts constructor(public breakpointObserver: BreakpointObserver) { } ngOnInit() { this.breakpointObserver.observe([ Breakpoints.XSmall, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge ]).subscribe(result => { if (result.breakpoints[Breakpoints.XSmall]) { // handle XSmall breakpoint } if (result.breakpoints[Breakpoints.Small]) { // handle Small breakpoint } if (result.breakpoints[Breakpoints.Medium]) { // handle Medium breakpoint } if (result.breakpoints[Breakpoints.Large]) { // handle Large breakpoint } if (result.breakpoints[Breakpoints.XLarge]) { // handle XLarge breakpoint } }); }
Conforme mencionado antes, as propriedades do acessador acima refletem as consultas de mídia da seguinte maneira:
-
Breakpoints.XSmall
: largura máxima = 599,99px - Pontos de
Breakpoints.Small
: largura mínima = 600px e largura máxima = 959,99px - Pontos de
Breakpoints.Medium
: largura mínima = 960px e largura máxima = 1279,99px - Pontos de
Breakpoints.Large
: min-width = 1280px e max-width = 1919,99px -
Breakpoints.XLarge
: min-width = 1920px
Agora temos tudo no lugar, o que significa que podemos começar a gerar as imagens apropriadas.
Pontos de interrupção responsivos para imagens
Temos algumas opções para gerar imagens responsivas:
- Gerador de pontos de interrupção de imagem responsiva
Usando esta ferramenta, podemos fazer upload de qualquer imagem, configurar várias opções, por exemplo, o número de imagens que desejamos gerar. Após executar a ferramenta, teremos uma representação visual das imagens geradas, e podemos baixá-las como um arquivo zip junto com algum código gerado que utiliza o elemento<picture>
mencionado anteriormente. - Outra solução seria criar uma etapa de compilação para nosso projeto para gerar pontos de interrupção por meio de alguns pacotes disponíveis no repositório NPM, como
gulp-responsive
ougrunt-responsive-images
. Ambos dependem de bibliotecas adicionais que precisamos instalar para nosso sistema operacional. (Por favor, verifique os repositórios apropriados para obter informações adicionais.) - Ainda outra solução seria usar um serviço como o Cloudinary para armazenar as imagens e servi-las em um tamanho e formato que precisamos apenas modificando a URL do recurso solicitado. Esta será a nossa abordagem, uma vez que nos dá mais flexibilidade.
Leitura recomendada : Automatizando a direção de arte com o gerador de pontos de interrupção de imagem responsiva por Eric Portis
Fiz o upload da imagem original para minha conta Cloudinary, o que significa que posso acessar essa imagem por meio do seguinte URL:
https://res.cloudinary.com/tamas-demo/image/upload/breakpoints-article/tuscany.jpg
Esta é a imagem em tamanho real, bruta, original e inalterada com a qual trabalharemos.
Podemos modificar a URL da imagem para gerar uma versão muito menor. Por exemplo, se quisermos ter uma imagem com uma largura de 600 pixels, podemos atualizar o URL Cloudinary* para o seguinte:
https://res.cloudinary.com/tamas-demo/image/upload/w_600/breakpoints-article/tuscany.jpg
* Observe o w_600
adicionado ao URL.
Espero que, a essa altura, você veja onde tudo isso está indo. Com base na abordagem acima, podemos começar a gerar rapidamente a imagem certa para o ponto de interrupção certo.
Usar o Cloudinary significa que não precisamos criar, armazenar e gerenciar várias versões da mesma imagem — isso é feito para nós pelo Cloudinary on-the-fly.
Vamos atualizar nosso código:
<!-- app.component.html --> <div> <h1>Current breakpoint: {{ breakpoint }}</h1> <img [src]="imagePath"> </div>
// app.component.ts import { Component, OnInit } from '@angular/core'; // ... export class AppComponent implements OnInit { imagePath; constructor(public breakpointObserver: BreakpointObserver) { } ngOnInit() { this.breakpointObserver.observe([ ... } }
Podemos escolher qualquer número de pontos de interrupção para observar na lista mencionada anteriormente e, como temos um Observador, podemos assinar as alterações e agir sobre elas:
this.breakpointObserver.observe([ Breakpoints.XSmall, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge ]).subscribe(result => { if (result.breakpoints[Breakpoints.XSmall]) { // handle this case } });
Para lidar com as opções para as diferentes imagens no Cloudinary, utilizaremos uma abordagem que será muito fácil de seguir. Para cada caso, criaremos uma variável de opções e atualizaremos a URL final do Cloudinary.
Adicione o seguinte na parte superior da definição do componente:
// app.component.ts imagePath; breakpoint; cloudinaryOptions; baseURL = 'https://res.cloudinary.com/tamas-demo/image/upload/breakpoints-article/tuscany.jpg';
E adicione o seguinte também à primeira instrução if
:
// app.component.ts let url = this.baseURL.split('/'); let insertIndex = url.indexOf('upload'); const options = 'c_thumb,g_auto,f_auto,q_auto,w_400'; url.splice(insertIndex + 1, 0, options); this.imagePath = url.join('/'); this.breakpoint = Breakpoints.XSmall;
O resultado será um URL Cloudinary atualizado:
https://res.cloudinary.com/tamas-demo/image/upload/c_thumb,g_auto,f_auto,q_auto,w_400/breakpoints-article/tuscany.jpg
Quais são as opções que estamos definindo aqui?
-
c_thumb
(gera uma miniatura da imagem); -
g_auto
(foca na parte mais interessante; vemos a catedral na miniatura); -
f_auto
(serve o formato mais apropriado para um determinado navegador, ou seja, WebP para Chrome); -
q_auto
(reduz a qualidade — e, portanto, o tamanho geral — da imagem sem afetar o visual); -
w_400
(define a largura da imagem para 400px).
Por curiosidade, vamos comparar o tamanho da imagem original com esta imagem recém-gerada: 2,28 MBs vs 29,08 KBs!
Agora temos um trabalho simples: precisamos criar opções diferentes para diferentes pontos de interrupção. Eu criei um aplicativo de exemplo no StackBlitz para que você possa testá-lo imediatamente (você também pode ver uma prévia aqui).
Conclusão
A variedade de desktops e dispositivos móveis e a quantidade de mídia usada na web atual atingiram um número impressionante. Como desenvolvedores da Web, devemos estar na vanguarda da criação de aplicativos da Web que funcionem em qualquer dispositivo e não afetem a experiência visual.
Há um bom número de métodos que garantem que a imagem certa seja carregada no dispositivo certo (ou mesmo ao redimensionar um dispositivo). Neste artigo, revisamos uma abordagem que utiliza um recurso Angular integrado chamado BreakPoint Observer, que nos fornece uma interface poderosa para lidar com imagens responsivas. Além disso, também demos uma olhada em um serviço que nos permite servir, transformar e gerenciar imagens na nuvem. Com ferramentas tão atraentes em nossas mãos, ainda podemos criar experiências visuais na web imersivas, sem perder visitantes.