Canvas tem uma API muito poderosa chamada drawImage() (w3c):
Sua principal função é desenhar fotos, vídeos e até outras telas.
pergunta:Ele chegou lá admirado, mas errou o alvo. Quando abaixou a cabeça, viu um grande buraco no chão.
A coisa é assim, depois de ler a introdução do w3c e a demonstração muito convincente e didática, decidi tentar com base na ideia de praticar para obter o verdadeiro conhecimento. experimente ~
Estabeleci as seguintes tarefas básicas de acordo com o projeto da linha de montagem:
1. tag de tela + id
<canvas id=canvas1></canvas>
2. Obtenha a tela + defina largura e altura
var cav1 = document.getElementById('canvas1'), wWidth = 800, wHeight = 600;3. getContext('2d') prepara a tela
var ctx1 = cav1.getContext('2d');4. Crie um novo objeto Image() e atribua a ele os atributos das imagens que eu gosto... (não pense muito)
var bgImg = new Image();bgImg.src = 'images/background.jpg';
5. Finalmente chegou a hora de desenhar. Eu escrevi este código com entusiasmo:
ctx1.drawImage(bgImg,0,0,wLargura,wAltura);
Aturdido, pressionei F5 no navegador.
Depois houve um silêncio mortal...
Achei que o código estava escrito errado, então voltei e verifiquei com cuidado e estava correto.
Copie os nomes dos atributos principais e métodos do w3c e verifique novamente.
Quando a foto é impressa, aparece também essa foto (de uma pessoa)!
Mais tarde, quando observei o caso do W3C, a diferença do meu código é que suas imagens estão em HTML.
Aí aprendi a inserir imagens em html,
<img src=./images/background.jpg id=imgs style=display:none></img>
E use getElementById para obter este elemento,
var bgImg = document.getElementById('imgs')Executar o desenho funcionou novamente.
Ele realmente pode!
Eu acho que, infelizmente, tem que ser físico? Não é colocado apenas na frente da tag canvas? O carregamento js também tem entidades, e eu ainda uso novas, que diferentes de pessoas reais!
Isso mesmo, não é só colocar na frente? Isso envolve um problema de sequência!
É verdade que a imagem carregada em js é colocada na frente do desenho, mas demorará um pouco para carregar a imagem. É necessário dar tempo para o buffer da imagem. Espere até que a imagem seja carregada com sucesso antes de desenhá-la. O método drawImage não será chamado quando a imagem for usada antes de ser carregada. O desenho falhará. Eu vejo!
Algumas pessoas argumentam que as imagens nas tags img não demoram para carregar? Neste momento drawImage não está restrito? ! Mas não ignore o window.onload no início do js. Mesmo que a imagem seja carregada lentamente, mesmo que a ordem das tags da imagem seja posterior à tag canvas, mas eu tenha o window.onload cobrindo-a, minha imagem não pode ser. carregado, e seu drawImage não terá chance, certo?
A ordem aproximada é esta:
<img src=>window.onload = function(){ drawImage}Se a imagem não fosse inserida na estrutura html, essa restrição teria sido contornada pelo meu descuido:
Como solicitação de recurso, quando a imagem for carregada em js, naturalmente haverá um tempo de carregamento da imagem.
Mas como não há limite, na maioria dos casos drawImage é chamado quando a imagem não foi carregada e este método não funcionará.
resolver:Então, existe uma boa maneira de resolver o problema de falha no desenho do drawImage devido à sequência de carregamento da imagem?
Resumi os três métodos a seguir:
1. tag+janela.onload <img src=>window.onload = function(){ context.drawImage()}A solução principal dessa abordagem é onload, que carrega a imagem e o drawImage separadamente. O img é carregado primeiro para garantir que o desenho seja usado após a conclusão do carregamento.
1-2. Inserir tags mais tarde? É viávelUma situação é que ao usar a função de captura de tela, você também pode usar drawImage, e a captura de tela não tira uma captura de tela de sua própria imagem existente, mas usa o endereço de uma imagem como parâmetro.
Acho que esse tipo de coisa exige que o js crie um img e atribua o endereço a ele. Em seguida, gere a imagem e faça uma captura de tela.
var myImg = document.createElement('img');myImg.src = '///';document.body.appendChild(myImg);ctx1.drawImage(myImg,0,0,wWidth,wHeight);Não quer adicionar tags extras? Preciso usar js conforme mostrado abaixo para criar um novo objeto de imagem?
var bgImg = new Image();bgImg.src = 'images/background.jpg';
Conforme mencionado anteriormente, esse tipo de imagem criada usando new Image() requer tempo para armazenar a imagem em buffer. Espere até que a imagem seja carregada com sucesso antes de desenhá-la.
O objeto de imagem está pronto, mas como saber quando a imagem está realmente carregada? Bem, existe outra maneira:
Enquanto a tarefa js está sendo executada, você acha que estou muito perto do seu tempo de execução. Você pode me levar sozinho e me colocar na fila novamente e executá-la novamente mais tarde?
2. Implementação assíncrona do temporizador setTimeout(function(){ ctx1.drawImage(bgImg,0,0,wWidth,wHeight);},10)Por que o atraso em escrever 10 aqui em vez dos familiares 1000 ou 0?
Porque no teste do meu ambiente Wi-Fi específico e do meu computador desktop específico, 10 pode sair depois que a imagem é carregada, ao contrário de 0, que não sai, e não quero esperar meio dia como 1000.
Mas imagine se você mudar a imagem para uma maior, esse 10 ainda se aplicaria? Este 10 ainda se aplicará se o wifi for alterado para 2g?
Portanto, a desvantagem do timer é que não há garantia de que a imagem será carregada após o tempo acabar, e ainda travará se a rede não for rápida.
3. img.onloadwindow.onload nos dá uma ideia. Não podemos monitorar diretamente a conclusão do carregamento?
Use o evento de carregamento do img para monitorar o carregamento bem-sucedido da imagem e, em seguida, execute o efeito de desenho da tela. E esse método é mais confiável.
bgImg.onload = function(){ console.log('Imagem carregada com sucesso'); console.log(this);Na verdade, todos esses três métodos têm o mesmo núcleo, que é deixar a imagem carregar primeiro. Ou seja, pré-carregamento de imagem. Mas para imagens em cache, o pré-carregamento de imagens também precisa resolver o problema de monitoramento de imagens em cache quando a página não é atualizada.
Encontrei outro problema. . . . Primeiro, veja como fica a pintura de fundo depois de finalizada.
Então a imagem de fundo finalmente apareceu e continuei feliz.
Então desenhei imediatamente uma linha vermelha para evitar não ver, também aumentei a largura para 20:
bgImg.onload = function(){ ctx1.drawImage(bgImg,0,0,wWidth,wHeight } /* Desenhe a linha vermelha da seguinte forma: */ ctx1.beginPath(); ctx1.lineTo (10,wAltura-100); ctx1.strokeStyle = 'vermelho';Mas quando pressiono F5, ainda não há alteração e ainda não consigo ver a linha vermelha.
Depois de muito pesquisar, não o vi até desligar a imagem de fundo:
Ah, acontece que ele foi coberto pela imagem de fundo!
Mas por que?
Estou pensando que existem duas possibilidades
1. Problemas de hierarquia
2. Problemas de sequência
Em relação ao 1, parece o índice z do CSS, onde a imagem de fundo cobre a linha vermelha. Será que o nível da imagem de fundo é superior à linha vermelha?
Não tinha como testar essa hipótese, então desisti da segunda revelação possível.
Mas por que a imagem de fundo está no topo? É porque a imagem de fundo é desenhada posteriormente?
Isso pode ser observado mais facilmente por meio da impressão console.log() para observar a sequência de execução.
Acontece que o culpado é o retorno de chamada onload. Assim como o cronômetro, é uma tarefa assíncrona. Naturalmente, ele está classificado atrás da tarefa de sincronização (desenho de linhas abaixo)
Portanto, onload parece ser uma boa solução, mas suas deficiências também são expostas aqui.
Muito bom, parece que o plano de aprendizagem prometido deve ser agendado o mais rápido possível! Hahaha
O texto acima é todo o conteúdo deste artigo. Espero que seja útil para o estudo de todos. Também espero que todos apoiem a Rede VeVb Wulin.