NOTA : Isso tem a ver com a forma como os elementos da tela existentes são renderizados quando redimensionados , não com a maneira como as linhas ou os gráficos são renderizados em uma superfície da tela . Em outras palavras, isso tem tudo a ver com interpolação de elementos dimensionados e nada a ver com antialiasing de gráficos desenhados em uma tela. Não estou preocupado com o modo como o navegador desenha linhas; Preocupo-me com a forma como o navegador renderiza o próprio elemento da telaquando é ampliado.
Existe uma propriedade da tela ou uma configuração do navegador que eu possa alterar programaticamente para desativar a interpolação ao dimensionar <canvas>
elementos? Uma solução entre navegadores é ideal, mas não essencial; Navegadores baseados em Webkit são meu principal alvo. O desempenho é muito importante.
Essa pergunta é muito semelhante, mas não ilustra o problema suficientemente. Pelo que vale a pena, tentei image-rendering: -webkit-optimize-contrast
sem sucesso.
O aplicativo será um jogo com estilo "retro" de 8 bits, escrito em HTML5 + JS para deixar claro o que eu preciso.
Para ilustrar, aqui está um exemplo. ( versão ao vivo )
Suponha que eu tenho uma tela 21x21 ...
<canvas id='b' width='21' height='21'></canvas>
... com css que torna o elemento 5 vezes maior (105x105):
canvas { border: 5px solid #ddd; }
canvas#b { width: 105px; height: 105px; } /* 5 * 21 = 105 */
Eu desenho um simples 'X' na tela assim:
$('canvas').each(function () {
var ctx = this.getContext("2d");
ctx.moveTo(0,0);
ctx.lineTo(21,21);
ctx.moveTo(0,21);
ctx.lineTo(21,0);
ctx.stroke();
});
A imagem à esquerda é o que o Chromium (14.0) renderiza. A imagem à direita é o que eu quero (desenhada à mão para fins ilustrativos).
fonte
Respostas:
Ultima atualização: 2014-09-12
A resposta é talvez algum dia . Por enquanto, você terá que recorrer a truques para conseguir o que deseja.
image-rendering
O rascunho de trabalho do CSS3 descreve uma nova propriedade,
image-rendering
que deve fazer o que eu quero:A especificação descreve três valores aceitos:
auto
,crisp-edges
, epixelated
.Padrão? Cross-browser?
Como esse é apenas um rascunho de trabalho , não há garantia de que isso se tornará padrão. Atualmente, o suporte ao navegador é irregular, na melhor das hipóteses.
A Mozilla Developer Network possui uma página bastante completa, dedicada ao estado da arte atual, que eu recomendo a leitura.
Os desenvolvedores do Webkit inicialmente optaram por implementar isso provisoriamente como
-webkit-optimize-contrast
, mas o Chromium / Chrome não parece estar usando uma versão do Webkit que o implementa.Atualização: 12/09/2014
O Chrome 38 agora é compatível
image-rendering: pixelated
!O Firefox tem um relatório de erros aberto para ser
image-rendering: pixelated
implementado, mas-moz-crisp-edges
funciona por enquanto.Solução?
A solução mais CSS, entre plataformas, até agora é:
Infelizmente, isso ainda não funciona em todas as principais plataformas HTML5 (Chrome, em particular).
Obviamente, é possível dimensionar manualmente as imagens usando a interpolação do vizinho mais próximo em superfícies de tela de alta resolução em javascript ou até pré-dimensionar as imagens no servidor, mas no meu caso isso será proibitivamente caro, por isso não é uma opção viável.
O ImpactJS usa uma técnica de pré-escala de textura para contornar todo esse FUD. O desenvolvedor do Impact, Dominic Szablewski, escreveu um artigo muito aprofundado sobre isso (ele acabou citando essa pergunta em sua pesquisa).
Veja a resposta de Simon para uma solução baseada em tela que depende da
imageSmoothingEnabled
propriedade (não disponível em navegadores antigos, mas mais simples que em pré-dimensionamento e com suporte bastante amplo).Demonstração ao vivo
Se você quiser testar as propriedades CSS discutidas no artigo MDN sobre os
canvas
elementos, criei esse violino que deve exibir algo como isto, embaçado ou não, dependendo do seu navegador:fonte
Nova resposta 31/07/2012
Esta é finalmente a especificação da tela!
A especificação adicionou recentemente uma propriedade chamada
imageSmoothingEnabled
, que padronizatrue
e determina se as imagens desenhadas em coordenadas não inteiras ou desenhadas em escala usarão um algoritmo mais suave. Se estiver definido como ofalse
vizinho mais próximo, será usado, produzindo uma imagem menos suave e produzindo pixels com aparência maior.A suavização de imagem foi recentemente adicionada à especificação de tela e não é suportada por todos os navegadores, mas alguns navegadores implementaram versões dessa propriedade com prefixo de fornecedor. No contexto, existe
mozImageSmoothingEnabled
no Firefox ewebkitImageSmoothingEnabled
no Chrome e Safari, e defini-los como false impedirá a ocorrência de anti-aliasing. Infelizmente, no momento em que escrevi, o IE9 e o Opera não implementaram essa propriedade, prefixada pelo fornecedor ou não.Visualização: JSFiddle
Resultado:
fonte
Editar 31/07/2012 - Esta funcionalidade está agora na especificação de tela! Veja a resposta em separado aqui:
https://stackoverflow.com/a/11751817/154112
A resposta antiga está abaixo para a posteridade.
Dependendo do efeito desejado, você tem isso como uma opção:
http://jsfiddle.net/wa95p/
O que cria isso:
Provavelmente não é o que você quer. Mas se você estava apenas procurando um borrão zero, esse seria o bilhete, então eu o oferecerei por precaução.
Uma opção mais difícil é usar a manipulação de pixels e escrever um algoritmo para o trabalho. Cada pixel da primeira imagem se torna um bloco 5x5 de pixels na nova imagem. Não seria muito difícil fazer com dados de imagem.
Mas o Canvas e o CSS por si só não o ajudarão aqui a escalar um para o outro com o efeito exato que você deseja.
fonte
image-rendering: -webkit-optimize-contrast
deve fazer o truque, mas parece não fazer nada. Eu posso examinar uma função para aumentar o conteúdo de uma tela usando a interpolação do vizinho mais próximo.No google chrome, os padrões de imagem da tela não são interpolados.
Aqui está um exemplo de trabalho editado a partir da resposta namuol http://jsfiddle.net/pGs4f/
fonte
A solução alternativa de Saviski explicada aqui é promissora, porque funciona em:
Mas não funciona da seguinte maneira, mas o mesmo efeito pode ser alcançado usando a renderização de imagem CSS:
Os problemáticos são estes, porque ctx.XXXImageSmoothingEnabled não está funcionando e a renderização de imagem não está funcionando:
fonte