HINWEIS : Dies hängt damit zusammen, wie vorhandene Canvas-Elemente beim Skalieren gerendert werden , nicht damit, wie Linien oder Grafiken auf einer Canvas-Oberfläche gerendert werden . Mit anderen Worten, hat dies alles zu tun mit Interpolation von skalierten Elementen , und nichts mitzu tun , den Anti - Aliasing von Grafiken auf einer Leinwand gezogen. Es geht mir nicht darum, wie der Browser Linien zeichnet. Mir ist wichtig, wie der Browser das Canvas-Element selbst rendert,wenn es vergrößert wird.
Gibt es eine Canvas-Eigenschaft oder eine Browsereinstellung, die ich programmgesteuert ändern kann, um die Interpolation beim Skalieren von <canvas>
Elementen zu deaktivieren ? Eine browserübergreifende Lösung ist ideal, aber nicht unbedingt erforderlich. Webkit-basierte Browser sind mein Hauptziel. Leistung ist sehr wichtig.
Diese Frage ist am ähnlichsten, veranschaulicht das Problem jedoch nicht ausreichend. Für das, was es wert ist, habe ich vergeblich versucht image-rendering: -webkit-optimize-contrast
.
Die Anwendung wird ein "Retro" 8-Bit-Spiel sein, das in HTML5 + JS geschrieben wurde, um klar zu machen, was ich brauche.
Zur Veranschaulichung hier ein Beispiel. ( Live-Version )
Angenommen, ich habe eine 21x21 Leinwand ...
<canvas id='b' width='21' height='21'></canvas>
... mit CSS, das das Element 5-mal größer macht (105x105):
canvas { border: 5px solid #ddd; }
canvas#b { width: 105px; height: 105px; } /* 5 * 21 = 105 */
Ich zeichne ein einfaches 'X' wie folgt auf die Leinwand:
$('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();
});
Das Bild links zeigt Chrom (14.0). Das Bild rechts ist das, was ich möchte (zur Veranschaulichung handgezeichnet).
quelle
Antworten:
Letzte Aktualisierung: 12.09.2014
Die Antwort ist vielleicht eines Tages . Im Moment müssen Sie auf Hack-arounds zurückgreifen, um das zu bekommen, was Sie wollen.
image-rendering
Der Arbeitsentwurf von CSS3 beschreibt eine neue Eigenschaft,
image-rendering
die tun soll, was ich will:Die Spezifikation beschreibt drei akzeptierte Werte:
auto
,crisp-edges
, undpixelated
.Standard? Browserübergreifend?
Da dies lediglich ein Arbeitsentwurf ist , gibt es keine Garantie dafür, dass dies zum Standard wird. Die Browserunterstützung ist derzeit bestenfalls unvollständig.
Das Mozilla Developer Network hat eine ziemlich gründliche Seite, die dem aktuellen Stand der Technik gewidmet ist und die ich sehr empfehlen kann.
Die Webkit-Entwickler haben dies zunächst vorläufig als implementiert
-webkit-optimize-contrast
, aber Chromium / Chrome scheint keine Version von Webkit zu verwenden, die dies implementiert.Update: 2014-09-12
Chrome 38 unterstützt jetzt
image-rendering: pixelated
!Firefox hat einen Fehlerbericht geöffnet, der
image-rendering: pixelated
implementiert werden kann,-moz-crisp-edges
funktioniert aber vorerst.Lösung?
Die bisher plattformübergreifendste CSS-Lösung ist daher:
Leider funktioniert dies noch nicht auf allen wichtigen HTML5-Plattformen (insbesondere Chrome).
Natürlich könnte man Bilder manuell mithilfe der Interpolation des nächsten Nachbarn auf hochauflösende Leinwandoberflächen in Javascript skalieren oder sogar Bilder serverseitig vorskalieren, aber in meinem Fall ist dies unerschwinglich teuer, so dass dies keine praktikable Option ist.
ImpactJS verwendet eine Textur- Vorskalierungstechnik , um all diese FUD zu umgehen . Der Entwickler von Impact, Dominic Szablewski, schrieb einen sehr ausführlichen Artikel darüber (er zitierte diese Frage sogar in seiner Forschung).
Siehe Simons Antwort für eine Canvas-basierte Lösung, die auf der
imageSmoothingEnabled
Eigenschaft basiert (nicht in älteren Browsern verfügbar, aber einfacher als die Vorskalierung und ziemlich weit verbreitet).Live-Demo
Wenn Sie die im MDN-Artikel beschriebenen CSS-Eigenschaften für
canvas
Elemente testen möchten , habe ich diese Geige erstellt, die je nach Browser verschwommen oder nicht angezeigt werden soll:quelle
Neue Antwort 31.07.2012
Dies ist endlich in der Canvas-Spezifikation!
Die Spezifikation hat kürzlich eine Eigenschaft namens aufgerufen
imageSmoothingEnabled
, die standardmäßig verwendettrue
und bestimmt, ob Bilder, die auf nicht ganzzahligen Koordinaten gezeichnet oder skaliert gezeichnet wurden, einen weicheren Algorithmus verwenden. Wenn es auf "false
Nächster Nachbar" eingestellt ist, wird ein weniger glattes Bild erzeugt und stattdessen nur größer aussehende Pixel erzeugt.Die Bildglättung wurde erst kürzlich zur Canvas-Spezifikation hinzugefügt und wird nicht von allen Browsern unterstützt. Einige Browser haben jedoch Versionen dieser Eigenschaft mit Herstellerpräfix implementiert. In dem
mozImageSmoothingEnabled
in Firefox sowiewebkitImageSmoothingEnabled
in Chrome und Safari vorhandenen Kontext wird das Auftreten von Anti-Aliasing verhindert, wenn diese auf false gesetzt werden. Leider haben IE9 und Opera diese Eigenschaft zum Zeitpunkt des Schreibens nicht implementiert, weder vorangestellt noch auf andere Weise.Vorschau: JSFiddle
Ergebnis:
quelle
Bearbeiten 31.07.2012 - Diese Funktionalität ist jetzt in der Canvas-Spezifikation! Siehe separate Antwort hier:
https://stackoverflow.com/a/11751817/154112
Alte Antwort ist unten für die Nachwelt.
Abhängig von Ihrem gewünschten Effekt haben Sie folgende Option:
http://jsfiddle.net/wa95p/
Was das schafft:
Wahrscheinlich nicht was du willst. Aber wenn Sie nur nach Unschärfe suchen, dann ist das das Ticket, also biete ich es für alle Fälle an.
Eine schwierigere Option besteht darin, die Pixelmanipulation zu verwenden und selbst einen Algorithmus für den Job zu schreiben. Jedes Pixel des ersten Bildes wird zu einem 5x5-Pixelblock auf dem neuen Bild. Mit Bilddaten wäre es nicht allzu schwer.
Aber Canvas und CSS allein helfen Ihnen hier nicht dabei, genau den gewünschten Effekt zu erzielen.
quelle
image-rendering: -webkit-optimize-contrast
sollte der Trick tun, scheint aber nichts zu tun. Ich könnte versuchen, eine Funktion zu rollen, um den Inhalt einer Leinwand mithilfe der Interpolation des nächsten Nachbarn zu skalieren.In Google Chrome werden Leinwandbildmuster nicht interpoliert.
Hier ist ein Arbeitsbeispiel, das aus der namuol-Antwort http://jsfiddle.net/pGs4f/ bearbeitet wurde.
quelle
Saviskis hier erläuterte Problemumgehung ist vielversprechend, da sie funktioniert auf:
Funktioniert aber nicht im Folgenden, aber der gleiche Effekt kann mit CSS-Bildwiedergabe erzielt werden:
Das Problem sind diese, weil ctx.XXXImageSmoothingEnabled nicht funktioniert und das Rendern von Bildern nicht funktioniert:
quelle