W3docs

Imagens no Canvas

Aprenda a desenhar imagens em um canvas HTML: obtenha uma fonte de imagem, use as três formas do drawImage(), lide com CORS e evite um canvas contaminado.

Um dos recursos do elemento <canvas> é a possibilidade de usar imagens. Elas podem ser usadas para diferentes fins. Você pode usar imagens externas em qualquer formato suportado pelo navegador (por exemplo, PNG, GIF ou JPEG). Como fonte, também é possível usar a imagem criada por outros elementos canvas.

Este capítulo se baseia na introdução ao Canvas e nos conceitos básicos de desenho no Canvas. Aqui você aprenderá como obter uma fonte de imagem, como usar as três formas do método drawImage() e como evitar o problema de "canvas contaminado" ao carregar imagens de outros domínios.

Importar imagens para um canvas é um processo de duas etapas:

  1. Obter uma referência a outro elemento canvas ou a um objeto HTMLImageElement como fonte.
  2. Desenhar uma imagem no canvas com a função drawImage().

Como fonte de imagem, a API canvas pode usar qualquer um dos seguintes tipos de dados:

Tipo de DadoDescrição
HTMLImageElementSão imagens criadas com o construtor Image() ou qualquer elemento <img>.
SVGImageElementSão imagens incorporadas com o elemento <image>.
HTMLVideoElementUm elemento HTML <video> como fonte de imagem captura o quadro atual do vídeo e o usa como imagem.
HTMLCanvasElementComo fonte de imagem, é possível usar outro elemento <canvas>.

Esses tipos em conjunto são referenciados pelo tipo CanvasImageSource.

Há muitas formas de obter imagens para usar no canvas.

Usando imagens da mesma página

Você pode obter uma referência a imagens na mesma página que o canvas de uma das seguintes formas:

  • A coleção document.images
  • O método document.getElementsByTagName()
  • O método document.getElementById(), se você souber o ID da imagem que deseja usar

Por exemplo, para capturar um elemento <img> existente pelo seu ID e desenhá-lo assim que a página carregar:

<img id="photo" src="myImage.png" alt="My image" />
<canvas id="exampleCanvas" width="240" height="225"></canvas>
<script>
  window.onload = function () {
    const canvas = document.getElementById("exampleCanvas");
    const ctx = canvas.getContext("2d");
    const img = document.getElementById("photo");
    ctx.drawImage(img, 0, 0);
  };
</script>

Como o <img> já está no documento, o navegador geralmente termina de carregá-lo antes que o window.onload seja disparado, portanto é seguro desenhar imediatamente.

Usando imagens de outros domínios

Usando o elemento <img> com o atributo crossorigin="anonymous", você pode solicitar permissão para carregar uma imagem de outro domínio. Se o domínio hospedeiro permitir acesso entre domínios via cabeçalhos CORS, você poderá usar a imagem no seu canvas sem contaminá-lo.

<img id="remote" src="https://example.com/photo.jpg" crossorigin="anonymous" alt="Remote image" />

Quando você define crossorigin="anonymous", o navegador envia a requisição sem credenciais (cookies). A imagem só é permitida em um canvas limpo se o servidor responder com o cabeçalho:

Access-Control-Allow-Origin: *

(ou um valor que inclua sua origem). Se você criar a imagem em JavaScript, defina a propriedade antes do src:

const img = new Image();
img.crossOrigin = "anonymous";
img.onload = function () {
  ctx.drawImage(img, 0, 0);
};
img.src = "https://example.com/photo.jpg";

Nota Se você desenhar uma imagem de origem cruzada sem a configuração CORS adequada, o canvas se torna "contaminado". Um canvas contaminado bloqueia o acesso aos seus dados de pixel por razões de segurança — chamar toDataURL(), toBlob() ou getImageData() lançará um SecurityError. A correção está no servidor: ele deve enviar o cabeçalho Access-Control-Allow-Origin. Não há como ler pixels de um canvas contaminado no lado do cliente.

Usando outros elementos canvas

Outros elementos canvas podem ser acessados usando o método document.getElementById() ou document.getElementsByTagName().

Incorporando uma imagem via data: URL

Data URLs permitem especificar uma imagem como uma string de caracteres codificada em Base64 diretamente no código. A vantagem da data URL é que a imagem resultante fica disponível imediatamente. Também é possível reunir todo o seu CSS, HTML, JavaScript e imagens em um único arquivo.

No entanto, há também uma desvantagem: a imagem não é armazenada em cache, e a URL codificada pode ser muito longa para imagens maiores.

Para usar uma data URL, atribua-a ao src de uma imagem e desenhe-a assim que ela carregar:

const img = new Image();
img.onload = function () {
  ctx.drawImage(img, 0, 0);
};
img.src =
  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==";

A string após base64, é a imagem codificada. Como ela faz parte do script, nenhuma requisição de rede adicional é feita — a imagem está pronta assim que é decodificada.

Criando uma imagem do zero

Você também pode criar um novo objeto HTMLImageElement no seu script. Para isso, use o construtor Image():

Criando uma imagem do zero

const img = new Image();
img.onload = function () {
  ctx.drawImage(img, 0, 0);
};
img.src = "myImage.png";

A imagem começa a carregar no momento em que o src é definido, e o carregamento é assíncrono. Se você chamar drawImage() antes de a imagem terminar de carregar, nada será desenhado. Para garantir que drawImage() seja executado somente após a imagem estar pronta, anexe o manipulador de evento onload antes de definir o src.

A função drawImage()

Uma vez que uma referência à imagem de origem esteja disponível, você pode usar o método drawImage(). Ele possui três formas, cada uma aceitando mais parâmetros que a anterior:

1. Somente posição

ctx.drawImage(image, dx, dy);

Desenha a imagem inteira em seu tamanho natural, posicionando seu canto superior esquerdo no ponto (dx, dy) no canvas.

2. Posição e tamanho (escalonamento)

ctx.drawImage(image, dx, dy, dWidth, dHeight);

Desenha a imagem inteira, escalonada para caber em uma caixa de dWidth × dHeight pixels com o canto superior esquerdo em (dx, dy).

3. Recorte (retângulo de origem para retângulo de destino)

ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

Recorta uma fatia retangular da imagem de origem e a desenha em um retângulo de destino no canvas. Esta é a forma mais flexível — usada para sprite sheets, recorte e zoom.

Os parâmetros se dividem em dois grupos:

ParâmetroGrupoSignificado
sx, syOrigemCanto superior esquerdo do recorte feito na imagem de origem.
sWidth, sHeightOrigemLargura e altura desse recorte.
dx, dyDestinoOnde o recorte é posicionado no canvas.
dWidth, dHeightDestinoTamanho em que o recorte é desenhado no canvas (é escalonado se diferente de sWidth/sHeight).

Os valores s* (origem) são medidos em pixels da imagem original; os valores d* (destino) são medidos em pixels do canvas. A forma básica, drawImage(image, dx, dy), é apenas a primeira dessas três.

No exemplo a seguir, usamos o método document.getElementById() para obter uma referência à imagem e, em seguida, usamos a função drawImage() para desenhá-la.

Exemplo de desenho de uma imagem com a função drawImage():

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <h2>Image</h2>
    <img id="photo" src="/uploads/media/default/0001/01/25acddb3da54207bc6beb5838f65f022feaa81d7.jpeg" alt="Aleq" width="200" height="185" />
    <h2>Image with canvas:</h2>
    <canvas id="exampleCanvas" width="240" height="225" style="border:2px solid #cccccc;">
      Your browser doesn't support the canvas tag.
    </canvas>
    <script>
      window.onload = function() {
        const canvas = document.getElementById("exampleCanvas");
        const ctx = canvas.getContext("2d");
        const img = document.getElementById("photo");
        ctx.drawImage(img, 20, 20);
      };
    </script>
  </body>
</html>
Perigo

Imagens SVG devem definir a largura e a altura no elemento raiz <svg>.

Usando quadros de um vídeo

Também é possível usar quadros de um vídeo apresentado por um elemento <video>, mesmo quando o vídeo não está visível. Por exemplo, se você tiver um elemento <video> com o ID "videoCanvas", faça o seguinte:

Exemplo de desenho de vídeo com canvas:

Imagens no Canvas

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <h2>Video</h2>
    <video id="videoCanvas" controls width="350" autoplay>
      <source src="/build/videos/arcnet.io(7-sec).mp4" type="video/mp4" />
    </video>
    <h2>Canvas  draws the current video:</h2>
    <canvas id="exampleCanvas" width="310" height="190" style="border:1px solid #d3d3d3;">
      Your browser doesn't support the canvas tag.
    </canvas>
    <script>
      const v = document.getElementById("videoCanvas");
      const c = document.getElementById("exampleCanvas");
      const ctx = c.getContext("2d");
      let animId;
      function drawFrame() {
        ctx.drawImage(v, 5, 5, 300, 180);
        animId = requestAnimationFrame(drawFrame);
      }
      v.addEventListener("play", function() {
        animId = requestAnimationFrame(drawFrame);
      }, false);
      v.addEventListener("pause", function() {
        cancelAnimationFrame(animId);
      }, false);
      v.addEventListener("ended", function() {
        cancelAnimationFrame(animId);
      }, false);
    </script>
  </body>
</html>

Prática

Prática
Ao criar uma imagem em JavaScript para desenhar no canvas, qual é a ordem correta das etapas?
Ao criar uma imagem em JavaScript para desenhar no canvas, qual é a ordem correta das etapas?
Was this page helpful?