REMARQUE : cela a à voir avec la façon dont les éléments de canevas existants sont rendus lors de la mise à l'échelle , pas avec la façon dont les lignes ou les graphiques sont rendus sur une surface de canevas . En d'autres termes, cela a tout à voir avec l' interpolation des éléments mis à l'échelle , et rien à voir avec l' anticrénelage des graphiques dessinés sur une toile. Je ne suis pas préoccupé par la façon dont le navigateur trace des lignes; Je me soucie de la façon dont le navigateur rend l'élément de toile lui - même lorsqu'il est mis à l'échelle.
Existe-t-il une propriété de canevas ou un paramètre de navigateur que je peux modifier par programmation pour désactiver l'interpolation lors de la mise à l'échelle des <canvas>
éléments? Une solution multi-navigateurs est idéale mais pas indispensable; Les navigateurs basés sur Webkit sont ma principale cible. La performance est très importante.
Cette question est très similaire mais n'illustre pas suffisamment le problème. Pour ce que ça vaut, j'ai essayé image-rendering: -webkit-optimize-contrast
en vain.
L'application sera un jeu de style 8 bits «rétro» écrit en HTML5 + JS pour préciser ce dont j'ai besoin.
Pour illustrer, voici un exemple. ( version en direct )
Supposons que j'ai une toile 21x21 ...
<canvas id='b' width='21' height='21'></canvas>
... qui a css qui rend l'élément 5 fois plus grand (105x105):
canvas { border: 5px solid #ddd; }
canvas#b { width: 105px; height: 105px; } /* 5 * 21 = 105 */
Je dessine un simple 'X' sur la toile comme ceci:
$('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();
});
L'image de gauche est ce que Chromium (14.0) rend. L'image de droite est ce que je veux (dessinée à la main à des fins d'illustration).
la source
Réponses:
Dernière mise à jour: 2014-09-12
La réponse est peut - être un jour . Pour l'instant, vous devrez recourir à des hack-around pour obtenir ce que vous voulez.
image-rendering
Le projet de travail de CSS3 décrit une nouvelle propriété,
image-rendering
qui devrait faire ce que je veux:La spécification définit trois valeurs acceptées:
auto
,crisp-edges
etpixelated
.La norme? Cross-browser?
Puisqu'il ne s'agit que d'un projet de travail , il n'y a aucune garantie que cela deviendra la norme. La prise en charge du navigateur est actuellement inégale, au mieux.
Le Mozilla Developer Network a une page assez complète consacrée à l'état actuel de l'art que je recommande vivement de lire.
Les développeurs Webkit ont initialement choisi de l'implémenter provisoirement en tant que
-webkit-optimize-contrast
, mais Chromium / Chrome ne semble pas utiliser une version de Webkit qui implémente cela.Mise à jour: 2014-09-12
Chrome 38 prend désormais en charge
image-rendering: pixelated
!Firefox a un rapport de bogue ouvert pour être
image-rendering: pixelated
implémenté, mais-moz-crisp-edges
fonctionne pour le moment.Solution?
La solution CSS la plus multiplateforme à ce jour est donc:
Malheureusement, cela ne fonctionnera pas encore sur toutes les principales plates-formes HTML5 (Chrome, en particulier).
Bien sûr, on pourrait redimensionner manuellement les images en utilisant l'interpolation du plus proche voisin sur des surfaces de canevas haute résolution en javascript, ou même des images pré-échelle côté serveur, mais dans mon cas, cela sera extrêmement coûteux, ce n'est donc pas une option viable.
ImpactJS utilise une technique de pré-mise à l'échelle de la texture pour contourner tout ce FUD. Le développeur d'Impact, Dominic Szablewski, a écrit un article très approfondi à ce sujet (il a même fini par citer cette question dans ses recherches).
Voir la réponse de Simon pour une solution basée sur le canevas qui repose sur la
imageSmoothingEnabled
propriété (non disponible dans les anciens navigateurs, mais plus simple que la pré-mise à l'échelle et assez largement prise en charge).Démo en direct
Si vous souhaitez tester les propriétés CSS discutées dans l'article MDN sur les
canvas
éléments, j'ai fait ce violon qui devrait afficher quelque chose comme ça, flou ou non, en fonction de votre navigateur:la source
Nouvelle réponse 31/07/2012
C'est enfin dans les spécifications de la toile!
La spécification a récemment ajouté une propriété appelée
imageSmoothingEnabled
, qui prend la valeur par défauttrue
et détermine si les images dessinées sur des coordonnées non entières ou mises à l'échelle utiliseront un algorithme plus fluide. S'il est défini surfalse
alors le plus proche voisin est utilisé, produisant une image moins lisse et à la place, faisant simplement des pixels plus grands.Le lissage d'image n'a été ajouté que récemment à la spécification du canevas et n'est pas pris en charge par tous les navigateurs, mais certains navigateurs ont implémenté des versions préfixées par le fournisseur de cette propriété. Dans le contexte existant
mozImageSmoothingEnabled
dans Firefox,webkitImageSmoothingEnabled
Chrome et Safari, les définir sur false empêchera l'anti-aliasing de se produire. Malheureusement, au moment de la rédaction de cet article, IE9 et Opera n'ont pas implémenté cette propriété, préfixée par le fournisseur ou autre.Aperçu: JSFiddle
Résultat:
la source
Edit 7/31/2012 - Cette fonctionnalité est maintenant dans les spécifications du canevas! Voir la réponse séparée ici:
https://stackoverflow.com/a/11751817/154112
L'ancienne réponse est ci-dessous pour la postérité.
En fonction de l'effet souhaité, vous avez ceci comme une option:
http://jsfiddle.net/wa95p/
Ce qui crée ceci:
Probablement pas ce que vous voulez. Mais si vous cherchiez simplement à n'avoir aucun flou, ce serait le ticket, alors je vous l'offrirai au cas où.
Une option plus difficile consiste à utiliser la manipulation des pixels et à écrire vous-même un algorithme pour le travail. Chaque pixel de la première image devient un bloc de 5x5 pixels sur la nouvelle image. Ce ne serait pas trop difficile à faire avec imagedata.
Mais Canvas et CSS seuls ne vous aideront pas ici pour mettre à l'échelle l'un à l'autre avec l'effet exact que vous désirez.
la source
image-rendering: -webkit-optimize-contrast
ça devrait faire l'affaire mais ne semble rien faire. Je peux envisager de lancer une fonction pour agrandir le contenu d'un canevas en utilisant l'interpolation du plus proche voisin.Dans Google Chrome, les modèles d'image de canevas ne sont pas interpolés.
Voici un exemple de travail édité à partir de la réponse namuol http://jsfiddle.net/pGs4f/
la source
La solution de contournement de Saviski expliquée ici est prometteuse, car elle fonctionne sur:
Mais ne fonctionne pas dans ce qui suit, mais le même effet peut être obtenu en utilisant le rendu d'image CSS:
Les problèmes sont les suivants, car ctx.XXXImageSmoothingEnabled ne fonctionne pas et le rendu d'image ne fonctionne pas:
la source