Je joue avec l'élément <canvas>
, en traçant des lignes, etc.
J'ai remarqué que mes lignes diagonales sont antialiasées. Pour ma part, je préférerais que mon look soit irrégulier - y at-il un moyen de désactiver cette fonctionnalité?
Pour les images, il y a maintenant context.imageSmoothingEnabled
= false
.
Cependant, rien ne permet de contrôler explicitement le dessin au trait. Vous devrez peut-être tracer vos propres traits ( à la dure ) en utilisant getImageData
et putImageData
.
Tracez vos lignes 1-pixel
sur des coordonnées telles que ctx.lineTo(10.5, 10.5)
. Tracer une ligne d'un pixel sur le point (10, 10)
signifie que ce pixel 1
situé à cette position va de 9.5
à 10.5
, ce qui donne deux lignes dessinées sur le canevas.
Une astuce intéressante pour ne pas toujours avoir besoin d'ajouter le 0.5
à la coordonnée sur laquelle vous voulez dessiner si vous avez beaucoup de lignes d'un pixel, est de ctx.translate(0.5, 0.5)
votre toile entière au début.
Cela peut être fait dans Mozilla Firefox. Ajoutez ceci à votre code:
contextXYZ.mozImageSmoothingEnabled = false;
Dans Opera, c'est actuellement une demande de fonctionnalité, mais j'espère qu'elle sera bientôt ajoutée.
L'anticrénelage est requis pour un traçage correct des graphiques vectoriels impliquant des coordonnées non entières (0.4, 0.4), ce que tous, mais très peu de clients, feront.
Lorsqu'on lui donne des coordonnées non entières, le canevas a deux options:
La dernière stratégie fonctionnera pour les graphiques statiques, bien que pour les petits graphiques (un cercle de rayon 2), les courbes montrent des marches claires plutôt que des courbes lisses.
Le vrai problème est lorsque les graphiques sont traduits (déplacés) - les sauts entre pixels (1,6 => 2, 1,4 => 1) signifient que l’origine de la forme peut sauter par rapport au conteneur parent (décalage constant). 1 pixel vers le haut/bas et gauche/droite).
Astuce n ° 1: vous pouvez atténuer (ou renforcer) l'antialiasing en redimensionnant le canevas (par exemple, par x), puis appliquez vous-même l'échelle réciproque (1/x) aux géométries (sans utiliser le canevas).
Comparer (pas de mise à l'échelle):
avec (échelle de la toile: 0,75; échelle manuelle: 1,33):
et (échelle de la toile: 1,33; échelle manuelle: 0,75):
Astuce n ° 2: Si vous recherchez vraiment un look irrégulier, essayez de dessiner chaque forme plusieurs fois (sans l’effacer). A chaque tirage, les pixels anti-crénelage deviennent plus sombres.
Comparer. Après avoir dessiné une fois:
Après avoir dessiné trois fois:
Je dessinerais tout en utilisant un algorithme de ligne personnalisé tel que l'algorithme de ligne de Bresenham. Découvrez cette implémentation JavaScript: http://members.chello.at/easyfilter/canvas.html
Je pense que cela va certainement résoudre vos problèmes.
Je veux ajouter que j'ai eu du mal à réduire la taille d'une image et à dessiner sur une toile, elle utilisait toujours le lissage, même si elle ne l'était pas lors de la conversion.
J'ai résolu en utilisant ceci:
function setpixelated(context){
context['imageSmoothingEnabled'] = false; /* standard */
context['mozImageSmoothingEnabled'] = false; /* Firefox */
context['oImageSmoothingEnabled'] = false; /* Opera */
context['webkitImageSmoothingEnabled'] = false; /* Safari */
context['msImageSmoothingEnabled'] = false; /* IE */
}
Vous pouvez utiliser cette fonction comme ceci:
var canvas = document.getElementById('mycanvas')
setpixelated(canvas.getContext('2d'))
Peut-être que cela est utile pour quelqu'un.
ctx.translate(0.5, 0.5);
ctx.lineWidth = .5;
Avec ce combo, je peux dessiner de belles lignes fines de 1px.
Remarquez un truc très limité. Si vous souhaitez créer une image à 2 couleurs, vous pouvez dessiner la forme de votre choix avec la couleur # 010101 sur un arrière-plan de couleur # 000000. Une fois que cela est fait, vous pouvez tester chaque pixel dans le fichier imageData.data [] et définir sur 0xFF quelle que soit la valeur qui n’est pas 0x00:
imageData = context2d.getImageData (0, 0, g.width, g.height);
for (i = 0; i != imageData.data.length; i ++) {
if (imageData.data[i] != 0x00)
imageData.data[i] = 0xFF;
}
context2d.putImageData (imageData, 0, 0);
Le résultat sera une image en noir et blanc non antialiasée. Ce ne sera pas parfait, car un antialiasing aura lieu, mais cet antialiasing sera très limité, la couleur de la forme ressemblant beaucoup à celle du fond.
Juste deux notes sur la réponse de StashOfCode:
Il vaut mieux le faire à la place:
Contournez et remplissez avec #FFFFFF
, puis procédez comme suit:
imageData.data[i] = (imageData.data[i] >> 7) * 0xFF
Cela le résout pour les lignes d'une largeur de 1px.
En dehors de cela, la solution de StashOfCode est parfaite car elle ne nécessite pas d'écrire vos propres fonctions de rastérisation (pensez non seulement aux lignes, mais à Béziers, aux arcs de cercle, aux polygones remplis avec des trous, etc.).