Html2canvas: Maneira de aumentar a resolução da imagem gerada via toDataURL

Criado em 10 jul. 2013  ·  58Comentários  ·  Fonte: niklasvh/html2canvas

Este é mais um pedido de recurso. Sou facilmente capaz de gerar o PNG chamando toDataURL no canvas retornado. Mas a qualidade da imagem é bastante desfocada / pobre. Eu fiz algumas pesquisas no Google e descobri que, por padrão, ele apenas retorna uma imagem em 96 dpi. E não parece haver uma maneira padrão de melhorar isso. Além disso, o toDataURLHD é experimental e não funciona de nenhuma maneira.

Existe alguma maneira de html2canvas retornar uma imagem em uma resolução mais alta? Ou mesmo que possa fornecer uma maneira de obter o DOM sendo renderizado, posso usar alguma biblioteca que use o DOM (com todos os estilos calculados aplicados a ele) e, em seguida, gerar qualquer imagem que eu quiser.

Comentários muito úteis

1 para isso. Procurando obter uma imagem com html2canvas para inserir em um PDF, mas obtendo uma qualidade borrada.

Todos 58 comentários

Sei que falamos sobre isso em algum ponto em outros problemas / solicitações e alguém enviou uma solicitação pull, mas nunca vi as solicitações pull mescladas.

Eu tenho um método de trabalho que usamos para verificar a densidade de pixels do dispositivo. Mas isso pode afetar o desempenho. Em vez disso, talvez queiramos ter um parâmetro para instruí-lo a renderizar com dpi mais alto?

@missing Sim, um parâmetro para especificar o DPI seria incrível.

Além disso, se você não se importar em compartilhar o método de trabalho para a densidade de pixels do dispositivo, isso será legal. Meu aplicativo principal é apenas exportar um png de uma nuvem de palavras de no máximo 50 termos. Portanto, não estou muito preocupado com o desempenho neste caso.

é o seu problema é a qualidade da imagem ou é um efeito borrado (em alguns casos, algumas imagens são geradas por html2canvas com efeito borrado)?

@brcontainer Acho que a qualidade da imagem é o problema. Eu penso. Por exemplo, em 100% de zoom a foto parece ok-decente-ish. Mas assim que eu amplio até 5% você pode ver uma queda perceptível na qualidade da foto. Por favor, veja a imagem em anexo.
association-cloud-apple-twitter

Só posso ter certeza de algo vendo um exemplo do problema em tempo de execução.

Experimente o mesmo local usando o http://jsfiddle.net/ , e poste o link aqui.

[editar]
chance de você estar tentando aplicar _zoom_ em uma tela gerada por html2canvas, você pode tentar usar (antes de salvar como uma imagem):

ctx.webkitImageSmoothingEnabled = false;
ctx.mozImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;

Boa sorte

Oi,

Precisamos de uma resolução superior a 96DPI. Precisamos de mais 300 DPI.

Isso é _possível_ fazer com html2canvas?

Temos o mesmo problema com manchas na imagem. Precisamos de qualquer solução que remova nosso embaçamento e nos dê um DPI que pareça bom.

Alguma ideia / sugestão sobre como isso pode ser feito ou alguma forma alternativa de obter o mesmo efeito?

Obrigado

@brcontainer Acabei de editar agora. Fiz o que você sugeriu e ainda não tive sorte com a qualidade da imagem. Aqui está o que eu fiz -

                var ctx = canvas.getContext('2d');

                ctx.webkitImageSmoothingEnabled = false;
                ctx.mozImageSmoothingEnabled = false;
                ctx.imageSmoothingEnabled = false;

                var rawData = canvas.toDataURL("image/png");

está na ordem errada, você deve aplicar "ImageSmoothingEnabled" antes de redimensionar a imagem.

Coloque uma amostra do seu código em http://jsfiddle.net e tentarei editá-lo

Oi, pessoal,

Desejo fazer upload de imagens de alta resolução sem a restrição de 96dpi de toDataURL. Já que toDataURLHD ainda não está disponível, como posso realizar meu sonho? :-)

Agradecemos antecipadamente por qualquer dica

@brcontainer Não tenho certeza se entendi o que você quer dizer com aplicação de suavização antes de redimensionar, porque não estou redimensionando a imagem de forma alguma. Em qualquer caso, criei um jsfiddle para você olhar em http://jsfiddle.net/tankchintan/92mra/4/

Estou ansioso para resolver isso! :)

Amigo você está confundindo, tem o toDataURL que tem que redimensionar, você tem que redimensionar o CANVAS .
Estou tentando criar um exemplo, mas ainda não consegui fazer funcionar.

Oi,

Tenho tentado seguir essas sugestões para obter uma melhor qualidade de imagem, mas também não está claro para mim.

brcontainer, é possível que você possa esclarecer, ou alterar / criar um violino JS que tankchintan criou, com as idéias sobre as quais você está falando? Isso não faz sentido para mim, mesmo se criarmos uma imagem com 2x o tamanho, a pixilação na imagem ainda permanecerá depois de convertermos a imagem para 192 DPI.

Olá pessoal, há mais algum feedback sobre esse problema? Estou experimentando uma qualidade de imagem extremamente profissional com html2canvas em comparação com algo como PhantomJS, onde você pode definir zoomFactor (entre outros ajustes) para aumentar a qualidade / resolução.

Eu tenho um problema semelhante. Eu tenho um requisito de obter um instantâneo da página da web em um documento PDF para o qual estou usando html2canvas para converter meu div em uma imagem e, em seguida, uso o iTextsharp para adicionar a imagem a um PDF. No entanto, a imagem gerada parece um pouco borrada e torna difícil visualizá-la constantemente. Eu quero saber se posso criar uma imagem de resolução especificada no próprio tempo de criação no html2canvas.

Oi,
Tenho exatamente os mesmos requisitos acima. e mesmo problema Iam enfrentando.
"Obtendo um instantâneo da página da web em um documento PDF para o qual estou usando html2canvas para converter meu div em uma imagem e, em seguida, adicionar a imagem a um PDF."
No entanto, a imagem gerada parece um pouco desfocada.

Segui as sugestões acima, mas ainda estou recebendo uma imagem borrada.
aqui no meu código: html2canvas gera instantâneo da página da web é baseado na resolução do sistema.
Estou obtendo a mesma página da web "instantâneo" em tamanhos diferentes, com base na resolução do sistema.

Exemplo :
tamanho da imagem: 816x422
tamanho da imagem: 1193x437
tamanho da imagem: 1275x437
Aqui, minha expectativa é: Dimensão 2000 x 1784 e acima.

é possível obter esta dimensão da imagem.
por favor, dê suas valiosas sugestões e obrigado por seu valioso tempo.

1 para isso. Procurando obter uma imagem com html2canvas para inserir em um PDF, mas obtendo uma qualidade borrada.

Você já tentou usar a matriz de transformação CSS em um parentNode para o elemento que deseja exportar em uma resolução mais alta? Isso funciona para mim. Por exemplo, "transformar: escala (2, 2)"

@mudcube funcionou parcialmente para mim

@brcontainer está funcionando bem para mim

existe alguma solução encontrada ?? por favor, compartilhe como melhorar a resolução de imagem borrada, eu tenho que fazer um pdf disso

+1 existe alguma solução / diretriz para isso?

alguma solução encontrada?

Pessoal, usem transform: scale(2, 2) e dá certo.

Você pode fornecer mais detalhes?

@matiasinsaurralde logo antes de fazer a captura de tela, adicione a classe css .x2 contendo a regra css de cima para o elemento e, em seguida, remova essa classe no retorno de chamada html2canvas . Você obterá elemento de tamanho duplo e captura de tela de tamanho duplo também. E é perfeito para que você provavelmente não observe nenhum redimensionamento.

image
captura de tela quando tentei seguir nossa sugestão

escala não aumentou a resolução para mim. Tive que resolver com JS -
https://github.com/niklasvh/html2canvas/issues/379

Teve sorte, rapazes?

transform: scale(2, 2); também não é a solução para dygraph.js

@premerddyn , veja minha solução no problema vinculado.
Está funcionando bem, mas requer ampliação antes da captura de tela.
Se meu comentário não for claro, acrescentarei mais explicações

bem, o que eu fiz foi criar um div com o dobro do tamanho e diminuir a visibilidade e todos os conteúdos que tinha aqui eu postei naquele div e tirei uma captura de tela. Dessa forma, nenhuma clareza de imagem é perdida e eu ajustei um código de tamanho de fonte para torná-lo trabalho.Eu entendo isso funcionando bem. Mas meu problema é com traço de texto e fundo de texto com várias linhas.

dimensionar por 2 funciona para mim, no entanto, acho que a renderização é limitada pela resolução / tamanho da janela. Se o div escalado for mais largo do que a janela, parte dele será cortada

então, não há como capturar telas maiores do que a tela?

Ah, deste tópico:

var h = $(element)[0].ownerDocument.defaultView.innerHeight;
    $(element)[0].ownerDocument.defaultView.innerHeight = $(element).height();
    html2canvas($(element)).then(function(canvas) {
        $(element)[0].ownerDocument.defaultView.innerHeight = h;
        //Do whatever you want with your canvas
    }

https://jsfiddle.net/enjoythedaycsk/9L966sdd/1/

Tentei conseguir algo de alta resolução neste exemplo, mas não consegui ...

Clique no botão download pngx2 ..

É possível fazer operações no backend, como quando o botão é clicado, a tela torna-se duas vezes maior e, em seguida, a imagem é capturada e, em seguida, a tela volta ao tamanho normal.

Claro, você poderia fazer isso. Eu aciono uma tela do tamanho que quero usando o
código fornecido. Descobri que obter o valor pode ser impreciso, então
defina a largura / altura diretamente.

No sábado, 7 de maio de 2016, enjoytheday [email protected] escreveu:

https://jsfiddle.net/enjoythedaycsk/9L966sdd/1/

Tentei alcançar algo de alta resolução neste exemplo, mas não consegui
naquela...

Clique no botão download pngx2 ..

É possível fazer operações no backend como quando o botão é clicado
a tela fica com o dobro do tamanho e a imagem é capturada e depois novamente
a tela voltou ao tamanho normal.

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/niklasvh/html2canvas/issues/241#issuecomment -217634634

A ilustração mais antiga do mundo
ForeverScape.com http://www.foreverscape.com/ | @foreverscape
https://twitter.com/foreverscape | No Github
https://github.com/vance/foreverscapecore | Nas noticias
http://www.foreverscape.com/art/reviews/

@vance você pode definir isso no exemplo do jsfiddle?

https://jsfiddle.net/enjoythedaycsk/9L966sdd/1/

Eu tentei, mas não foi definido por mim.

Você pode editá-lo completamente ou pode criar um novo.

Será útil para muitos: dançarino:

Tentei simular rapidamente, mas não tive tempo de consertar o div de teste. Capturar algo com transform:scale() não faz nada porque a altura interna do div _NÃO_ é afetada. É por isso que é uma transformação. Suas propriedades w / h não foram alteradas (internamente), que você pode testar obtendo getBoundingClientRect() . Sua largura / altura muda apenas _atualmente_ quando vista no contexto do pai. Você tem que pegar o div do contêiner depois de dimensionado.

https://jsfiddle.net/jano9ao4/1/

Eu enfrento o mesmo problema, existe alguma solução viável? ヾ (´ ・ ・ `。) ノ "

Consegui fazer funcionar, capturar elementos maiores do que a janela. Apenas lembre-se, você não pode obter uma imagem "maior" simplesmente de um elemento transformado, porque (para si mesmo), ele ainda tem as mesmas dimensões.

Eu tive que fazer o meu em um iframe e enviar os dados da base64 de volta como uma mensagem ... porque fazendo o seguinte QUEBRA o evento de redimensionamento da janela.

Novamente com comentários:

   //store the original size
    var h = $(element)[0].ownerDocument.defaultView.innerHeight;
    var w = $(element)[0].ownerDocument.defaultView.innerWidth;

   //set the document to the element's size
    $(element)[0].ownerDocument.defaultView.innerHeight = $(element).height();
    $(element)[0].ownerDocument.defaultView.innerWidth = $(element).width();

    html2canvas($(element)).then(function(canvas) {
        //restore the document size
        $(element)[0].ownerDocument.defaultView.innerHeight = h;
        $(element)[0].ownerDocument.defaultView.innerWidth = w;
        //Do whatever you want with your canvas
    }

Eu escrevi a seguinte função para obter facilmente uma captura de tela com DPI mais alto de um elemento HTML usando html2canvas.

  • se a altura ou largura for restrita (por exemplo, há uma largura fixa do corpo), as restrições devem ser removidas durante o processamento - o elemento de origem deve ser capaz de crescer até a escala desejada
  • srcEl deve ser um elemento existente
  • destIMG deve ser um elemento de imagem existente (vazio)
  • dpi deve ser múltiplos de 96
var makeHighResScreenshot = function(srcEl, destIMG, dpi) {
    var scaleFactor = Math.floor(dpi / 96);
    // Save original size of element
    var originalWidth = srcEl.offsetWidth;
    var originalHeight = srcEl.offsetHeight;
    // Save original document size
    var originalBodyWidth = document.body.offsetWidth;
    var originalBodyHeight = document.body.offsetHeight;

    // Add style: transform: scale() to srcEl
    srcEl.style.transform = "scale(" + scaleFactor + ", " + scaleFactor + ")";
    srcEl.style.transformOrigin = "left top";

    // create wrapper for srcEl to add hardcoded height/width
    var srcElWrapper = document.createElement('div');
    srcElWrapper.id = srcEl.id + '-wrapper';
    srcElWrapper.style.height = originalHeight*scaleFactor + 'px';
    srcElWrapper.style.width = originalWidth*scaleFactor + 'px';
    // insert wrapper before srcEl in the DOM tree
    srcEl.parentNode.insertBefore(srcElWrapper, srcEl);
    // move srcEl into wrapper
    srcElWrapper.appendChild(srcEl);

    // Temporarily remove height/width constraints as necessary
    document.body.style.width = originalBodyWidth*scaleFactor +"px";
    document.body.style.height = originalBodyHeight*scaleFactor +"px";

    window.scrollTo(0, 0); // html2canvas breaks when we're not at the top of the doc, see html2canvas#820
    html2canvas(srcElWrapper, {
        onrendered: function(canvas) {
            destIMG.src = canvas.toDataURL("image/png");
            srcElWrapper.style.display = "none";
            // Reset height/width constraints
            document.body.style.width = originalBodyWidth + "px";
            document.body.style.height = originalBodyHeight + "px";
        }
    });
};

Uso:

var src = document.getElementById("screenshot-source");
var img = document.getElementById("screenshot-img");
makeHighResScreenshot(src, img, 192); // DPI of 192 is 4x resolution (2x normal DPI for both width and height)

Você descobriu que fazer isso também quebra os manipuladores de eventos window.onresize? Por esse motivo, tive que fazer tudo isso dentro de um iframe e postar o resultado de volta usando parent.window.postMessage (data) para retornar o conteúdo. Isso só importa para mim porque é um aplicativo móvel e é fundamental ter um fogo de tamanho único.

@vance : No meu caso, não preciso nem uso nenhuma dessas coisas - estou usando isso para contornar um bug em um renderizador de HTML para PDF. Adoraria ver um exemplo completo do seu método, parece mais flexível.

Descobri outra maneira de obter uma imagem de alta resolução que não precise redimensionar o corpo. No entanto, ele precisa posicionar absolutamente o elemento de origem devido a um bug no html2canvas (# 790, # 820, # 893, # 922, etc). Baseado no código de retina de @MisterLamb .

function takeHighResScreenshot(srcEl, destIMG, scaleFactor) {
    // Save original size of element
    var originalWidth = srcEl.offsetWidth;
    var originalHeight = srcEl.offsetHeight;
    // Force px size (no %, EMs, etc)
    srcEl.style.width = originalWidth + "px";
    srcEl.style.height = originalHeight + "px";

    // Position the element at the top left of the document because of bugs in html2canvas. The bug exists when supplying a custom canvas, and offsets the rendering on the custom canvas based on the offset of the source element on the page; thus the source element MUST be at 0, 0.
    // See html2canvas issues #790, #820, #893, #922
    srcEl.style.position = "absolute";
    srcEl.style.top = "0";
    srcEl.style.left = "0";

    // Create scaled canvas
    var scaledCanvas = document.createElement("canvas");
    scaledCanvas.width = originalWidth * scaleFactor;
    scaledCanvas.height = originalHeight * scaleFactor;
    scaledCanvas.style.width = originalWidth + "px";
    scaledCanvas.style.height = originalHeight + "px";
    var scaledContext = scaledCanvas.getContext("2d");
    scaledContext.scale(scaleFactor, scaleFactor);

    html2canvas(srcEl, { canvas: scaledCanvas })
    .then(function(canvas) {
        destIMG.src = canvas.toDataURL("image/png");
        srcEl.style.display = "none";
    });
};

Uso:

var src = document.getElementById("screenshot-src");
var img = document.getElementById("screenshot-img");
takeHighResScreenshot(src, img, 2); // This time we provide desired scale factor directly, no more messing with DPI

EDITAR: hackiness reduzido usando posicionamento absoluto em vez de realmente mover o elemento e ajustar as margens, graças a @ jason-o-matic pela sugestão.

isso funciona com a versão mais recente (0.5.0-alpha). mas não 0.4.1

se você quiser resolver esse problema na 0.4.1, terá que brincar com o tamanho da tela.

Apenas uma nota rápida para quem está usando a correção de @airdrummingfool (que funciona muito bem) ...

Você não pode ter nenhum elemento "relativo" envolvendo o elemento que deseja despejar na tela, não importa o quão longe eles estejam na xtree. Eles precisam ser mudados para estáticos durante o screendump para que o elemento que você deseja realmente apareça em 0,0 em relação à janela, não um DIV circundante.

Levei várias horas para resolver isso, então espero que isso ajude alguém a evitar os mesmos problemas.

Boa tarde gente,
Alguém tem um jsfiddle de solução @airdrummingfool , estou tentando implementá-lo em meu projeto sem sorte. Um exemplo prático seria ótimo para eu entender como isso funciona e me ajudaria muito na tentativa de implementá-lo em meu projeto.

Muito obrigado por qualquer assistência que possa ser prestada.

Olá a todos! Estou tentando usar a solução @airdrummingfool . Mas recebo um erro irritante. Dentro do elemento do qual desejo obter a imagem, há um e ao fazer o procedimento, o elemento img fica em branco e o src é ignorado. Você sabe como posso resolver isso? Alguém já enfrentou esse problema antes com o html2canvas?

Agradecemos antecipadamente a este tópico! Isso está me salvando !! : D

EDIT: Eu também estou recebendo apenas metade da imagem renderizada. Mas a resolução parece perfeita xD

Corrigido o problema da imagem !! O useCORS não foi habilitado! Mas ainda estou obtendo apenas metade da imagem renderizada.

Excelente! A meia imagem pode ser devido ao problema de renderização fora da tela . Também fiz uma solicitação de pull para adicionar resolução / dimensionamento ao html2canvas , você pode achar mais fácil de usar do que a solução @airdrummingfool .

Até que eles sejam integrados ao html2canvas, você pode obter minha construção personalizada com ambos e algumas outras correções de bugs aqui .

Olá, @eKoopmans. Obrigado pela sua resposta. Acabei de consertar o meu multiplicando a altura por 2. Mas, acho que estou obtendo uma imagem maior com espaços em branco acima e abaixo ... então ... Vou tentar o seu e relatar em alguns minutos !

OM (F) G @eKoopmans .. Você trabalhou fora da caixa. Valeu mesmo, cara. Essa solicitação de pull ... eles deveriam apenas aceitá-la agora. Há MUITAS pessoas querendo esta opção de dpi para html2canvas.

Fechando em favor de # 1087

@airdrummingfool ... Obrigado. Isso funciona perfeitamente.

a versão mais recente do html2canvas oferece a opção de escalonamento. Funciona muito bem.

html2canvas (elemento, {
escala: 2
});

Para renderização de várias páginas de PDF a partir de conteúdo de html e imagem, definir scale: 1 pode corrigir o problema de resolução e, ao mesmo tempo, evitar que as imagens excedam a borda do pdf.

Acho que isso ajuda, usei html2canvas

baixar PDF() {
var doc = new jsPDF ({
formato: "a4"
});

html2canvas (document.getElementById ("pdf-doc"), {
escala: "5"
}). então (canvas => {
this.imgFile = canvas;
doc.addImage (this.imgFile, "JPEG", 5, 5, 200, 285);
doc.save ("nome do arquivo" + ".pdf");
});
}

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

kunal886496 picture kunal886496  ·  3Comentários

Loki180 picture Loki180  ·  4Comentários

dking3876 picture dking3876  ·  4Comentários

tibewww picture tibewww  ·  4Comentários

yasergh picture yasergh  ·  5Comentários