UWAGA : Ma to związek ze sposobem renderowania istniejących elementów kanwy po przeskalowaniu , a nie ze sposobem renderowania linii lub grafiki na powierzchni płótna . Innymi słowy, to ma wszystko wspólnego z interpolacją do skalowanych elementów i nie ma nic wspólnego z antialiasing grafiki są rysowane na płótnie. Nie obchodzi mnie, jak przeglądarka rysuje linie; Dbam o to, jak przeglądarka renderuje sam element canvas , gdy jest skalowany.
Czy istnieje właściwość kanwy lub ustawienie przeglądarki, które mogę zmienić programowo, aby wyłączyć interpolację podczas skalowania <canvas>
elementów? Rozwiązanie dla różnych przeglądarek jest idealne, ale nie jest niezbędne; Moim głównym celem są przeglądarki oparte na Webkit. Wydajność jest bardzo ważna.
To pytanie jest najbardziej podobne, ale nie ilustruje wystarczająco problemu. image-rendering: -webkit-optimize-contrast
Bezskutecznie próbowałem .
Aplikacja będzie "retro" 8-bitową grą napisaną w HTML5 + JS, aby było jasne, czego potrzebuję.
Aby to zilustrować, oto przykład. ( wersja na żywo )
Załóżmy, że mam płótno 21x21 ...
<canvas id='b' width='21' height='21'></canvas>
... który ma css, który sprawia, że element jest 5 razy większy (105x105):
canvas { border: 5px solid #ddd; }
canvas#b { width: 105px; height: 105px; } /* 5 * 21 = 105 */
Rysuję na płótnie prosty „X” w następujący sposób:
$('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();
});
Obraz po lewej stronie renderuje Chromium (14.0). Obraz po prawej jest tym, czego chcę (narysowany ręcznie w celach ilustracyjnych).
źródło
Odpowiedzi:
Ostatnia aktualizacja: 2014-09-12
Odpowiedź brzmi może kiedyś . Na razie będziesz musiał uciekać się do hacków, aby uzyskać to, czego chcesz.
image-rendering
Roboczy szkic CSS3 przedstawia nową właściwość,
image-rendering
która powinna zrobić to, co chcę:Specyfikacja przedstawia trzy wartości przyjętych:
auto
,crisp-edges
, ipixelated
.Standard? Wiele przeglądarek?
Ponieważ jest to tylko robocza wersja robocza , nie ma gwarancji, że stanie się to standardem. Obsługa przeglądarek jest obecnie w najlepszym razie niestabilna.
Mozilla Developer Network ma całkiem dokładną stronę poświęconą aktualnemu stanowi techniki, którą gorąco polecam przeczytać.
Programiści Webkit początkowo zdecydowali się wstępnie zaimplementować to jako
-webkit-optimize-contrast
, ale Chromium / Chrome nie używają wersji Webkit, która to implementuje.Aktualizacja: 2014-09-12
Chrome 38 obsługuje teraz
image-rendering: pixelated
!Firefox ma otwarty raport o błędzie do
image-rendering: pixelated
zaimplementowania, ale-moz-crisp-edges
na razie działa.Rozwiązanie?
Jak dotąd najbardziej wieloplatformowe rozwiązanie tylko dla CSS to:
Niestety, to nie zadziała jeszcze na wszystkich głównych platformach HTML5 (w szczególności Chrome).
Oczywiście można ręcznie skalować obrazy w górę za pomocą interpolacji najbliższego sąsiada na powierzchnie płótna o wysokiej rozdzielczości w javascript lub nawet obrazy wstępnie skalowane po stronie serwera, ale w moim przypadku będzie to kosztowne, więc nie jest to opłacalna opcja.
ImpactJS wykorzystuje technikę wstępnego skalowania tekstur, aby obejść to całe FUD. Deweloper firmy Impact, Dominic Szablewski, napisał na ten temat bardzo dogłębny artykuł (w swoich badaniach nawet zacytował to pytanie).
Zobacz odpowiedź Simona na rozwiązanie oparte na kanwie, które opiera się na
imageSmoothingEnabled
właściwości (niedostępne w starszych przeglądarkach, ale prostsze niż skalowanie wstępne i dość szeroko obsługiwane).Live Demo
Jeśli chcesz przetestować właściwości CSS omówione w artykule MDN na temat
canvas
elementów, zrobiłem to skrzypce, które powinny wyświetlać coś takiego, rozmyte lub nie, w zależności od przeglądarki:źródło
Nowa odpowiedź 31.07.2012
To jest wreszcie w specyfikacji płótna!
Specyfikacja ostatnio dodała właściwość o nazwie
imageSmoothingEnabled
, która jest wartością domyślnątrue
i określa, czy obrazy narysowane na współrzędnych innych niż całkowite lub narysowane skalowane będą korzystały z płynniejszego algorytmu. Jeśli jest ustawiona nafalse
, używany jest najbliższy sąsiad, co daje mniej gładki obraz, a zamiast tego po prostu powiększa wyglądające piksele.Wygładzanie obrazu zostało niedawno dodane do specyfikacji kanwy i nie jest obsługiwane przez wszystkie przeglądarki, ale niektóre przeglądarki zaimplementowały wersje tej właściwości z prefiksem dostawcy. W kontekście istnieje
mozImageSmoothingEnabled
w Firefoksie,webkitImageSmoothingEnabled
Chrome i Safari, a ustawienie ich na fałsz zatrzyma antyaliasing. Niestety, w chwili pisania tego tekstu IE9 i Opera nie zaimplementowały tej właściwości, z prefiksem dostawcy lub w inny sposób.Podgląd: JSFiddle
Wynik:
źródło
Edycja 31.07.2012 - Ta funkcja jest teraz w specyfikacji płótna! Zobacz oddzielną odpowiedź tutaj:
https://stackoverflow.com/a/11751817/154112
Stara odpowiedź jest poniżej dla potomnych.
W zależności od pożądanego efektu masz jedną opcję:
http://jsfiddle.net/wa95p/
Który to tworzy:
Prawdopodobnie nie to, czego chcesz. Ale gdybyś chciał tylko zerowego rozmycia, to byłby bilet, więc na wszelki wypadek zaoferuję go.
Trudniejszą opcją jest użycie manipulacji pikselami i samodzielne napisanie algorytmu do zadania. Każdy piksel pierwszego obrazu staje się blokiem pikseli 5x5 na nowym obrazie. Nie byłoby to trudne do zrobienia z obrazami.
Ale same płótno i CSS nie pomogą ci tutaj w skalowaniu jednego do drugiego z dokładnym efektem, którego pragniesz.
źródło
image-rendering: -webkit-optimize-contrast
powinien załatwić sprawę, ale wydaje się, że nic nie robi. Mogę spojrzeć na zwijanie funkcji, aby przeskalować zawartość płótna za pomocą interpolacji najbliższego sąsiada.W Google Chrome wzorce obrazów płótna nie są interpolowane.
Oto działający przykład zredagowany z odpowiedzi namuol http://jsfiddle.net/pGs4f/
źródło
Obejście Saviski za wyjaśniony tutaj jest obiecujący, ponieważ działa na:
Ale nie działa w następujących przypadkach, ale ten sam efekt można osiągnąć za pomocą renderowania obrazu CSS:
Problematyczne są te, ponieważ ctx.XXXImageSmoothingEnabled nie działa, a renderowanie obrazu nie działa:
źródło