Ich bin insgesamt n00b mit HTML5
und arbeite mit dem canvas
, um Formen, Farben und Text zu rendern. In meiner App habe ich einen Ansichtsadapter , der eine Zeichenfläche dynamisch erstellt und mit Inhalten füllt. Dies funktioniert sehr gut, außer dass mein Text sehr unscharf / verschwommen / gedehnt ist. Ich habe viele andere Beiträge darüber gesehen, warum das Definieren der Breite und Höhe in CSS
dieses Problem verursacht, aber ich definiere alles in javascript
.
Der relevante Code (siehe Geige ):
HTML
<div id="layout-content"></div>
Javascript
var width = 500;//FIXME:size.w;
var height = 500;//FIXME:size.h;
var canvas = document.createElement("canvas");
//canvas.className="singleUserCanvas";
canvas.width=width;
canvas.height=height;
canvas.border = "3px solid #999999";
canvas.bgcolor = "#999999";
canvas.margin = "(0, 2%, 0, 2%)";
var context = canvas.getContext("2d");
//////////////////
//// SHAPES ////
//////////////////
var left = 0;
//draw zone 1 rect
context.fillStyle = "#8bacbe";
context.fillRect(0, (canvas.height*5/6)+1, canvas.width*1.5/8.5, canvas.height*1/6);
left = left + canvas.width*1.5/8.5;
//draw zone 2 rect
context.fillStyle = "#ffe381";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*2.75/8.5, canvas.height*1/6);
left = left + canvas.width*2.75/8.5 + 1;
//draw zone 3 rect
context.fillStyle = "#fbbd36";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*1.25/8.5, canvas.height*1/6);
left = left + canvas.width*1.25/8.5;
//draw target zone rect
context.fillStyle = "#004880";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*0.25/8.5, canvas.height*1/6);
left = left + canvas.width*0.25/8.5;
//draw zone 4 rect
context.fillStyle = "#f8961d";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*1.25/8.5, canvas.height*1/6);
left = left + canvas.width*1.25/8.5 + 1;
//draw zone 5 rect
context.fillStyle = "#8a1002";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width-left, canvas.height*1/6);
////////////////
//// TEXT ////
////////////////
//user name
context.fillStyle = "black";
context.font = "bold 18px sans-serif";
context.textAlign = 'right';
context.fillText("User Name", canvas.width, canvas.height*.05);
//AT:
context.font = "bold 12px sans-serif";
context.fillText("AT: 140", canvas.width, canvas.height*.1);
//AB:
context.fillText("AB: 94", canvas.width, canvas.height*.15);
//this part is done after the callback from the view adapter, but is relevant here to add the view back into the layout.
var parent = document.getElementById("layout-content");
parent.appendChild(canvas);
Die Ergebnisse, die ich (in Safari ) sehe, sind viel verzerrter als in der Geige gezeigt:
Bergwerk
Geige
Was mache ich falsch? Benötige ich für jedes Textelement eine eigene Leinwand? Ist es die Schriftart? Muss ich zuerst die Zeichenfläche im HTML5-Layout definieren? Gibt es einen Tippfehler? Ich bin verloren.
quelle
clearRect
.Antworten:
Das Canvas-Element wird unabhängig vom Pixelverhältnis des Geräts oder Monitors ausgeführt.
Auf dem iPad 3+ beträgt dieses Verhältnis 2. Dies bedeutet im Wesentlichen, dass Ihre Leinwand mit einer Breite von 1000 Pixel jetzt 2000 Pixel ausfüllen muss, um der auf dem iPad-Display angegebenen Breite zu entsprechen. Zum Glück erledigt dies der Browser automatisch. Auf der anderen Seite ist dies auch der Grund, warum Bilder und Leinwandelemente, die so erstellt wurden, dass sie direkt in ihren sichtbaren Bereich passen, weniger definiert sind. Da Ihre Leinwand nur 1000 Pixel ausfüllt, aber aufgefordert wird, auf 2000 Pixel zu zeichnen, muss der Browser jetzt die Lücken zwischen den Pixeln intelligent ausfüllen, um das Element in der richtigen Größe anzuzeigen.
Ich würde Ihnen wärmstens empfehlen, diesen Artikel aus HTML5Rocks zu lesen , in dem ausführlicher erklärt wird, wie hochauflösende Elemente erstellt werden.
tl; dr? Hier ist ein Beispiel (basierend auf dem obigen Tut), das ich in meinen eigenen Projekten verwende, um eine Leinwand mit der richtigen Auflösung auszuspucken:
Hoffe das hilft!
quelle
Gelöst!
Ich beschloss zu sehen, was das ändert mir eingestellten Attribute für Breite und Höhe
javascript
zu sehen, wie sich dies auf die Leinwandgröße auswirkt - und das tat es nicht. Es ändert die Auflösung.Um das gewünschte Ergebnis zu erzielen, musste ich auch das
canvas.style.width
Attribut festlegen , das die physische Größe voncanvas
:quelle
window.devicePixelRatio
und es ist in den meisten modernen Browsern gut implementiert.Ich ändere die Größe des Canvas-Elements über CSS, um die gesamte Breite des übergeordneten Elements zu übernehmen. Ich habe festgestellt, dass Breite und Höhe meines Elements nicht skaliert sind. Ich suchte nach dem besten Weg, um die Größe einzustellen, die sein sollte.
Auf diese einfache Weise wird Ihre Leinwand perfekt eingestellt, unabhängig davon, welchen Bildschirm Sie verwenden.
quelle
Das hat es zu 100% für mich gelöst:
(Es ist nah an Adam Mańkowskis Lösung).
quelle
Ich habe den MyNameIsKo- Code unter canvg (SVG to Canvas js library) leicht angepasst . Ich war eine Weile verwirrt und verbrachte einige Zeit damit. Hoffe das hilft jemandem.
HTML
Javascript
quelle
Für diejenigen unter Ihnen, die in Reaktionen arbeiten, habe ich die Antwort von MyNameIsKo angepasst und es funktioniert großartig. Hier ist der Code.
In diesem Beispiel übergebe ich die Breite und Höhe der Leinwand als Requisiten.
quelle
Ich bemerkte ein Detail, das in den anderen Antworten nicht erwähnt wurde. Die Canvas-Auflösung wird auf ganzzahlige Werte gekürzt.
Die Standardabmessungen für die Leinwandauflösung sind
canvas.width: 300
undcanvas.height: 150
.Auf meinem Bildschirm
window.devicePixelRatio: 1.75
.Also , wenn ich gesetzt
canvas.height = 1.75 * 150
wird der Wert von dem gewünschten abgeschnitten262.5
nach unten zu262
.Eine Lösung besteht darin, die CSS-Layoutabmessungen für eine bestimmte Größe so zu wählen,
window.devicePixelRatio
dass beim Skalieren der Auflösung keine Kürzungen auftreten.Zum Beispiel könnte ich verwenden
width: 300px
undheight: 152px
was würde ganze Zahlen ergeben, wenn mit multipliziert1.75
.Bearbeiten : Eine andere Lösung besteht darin, die Tatsache zu nutzen, dass CSS-Pixel gebrochen sein können, um dem Abschneiden der Skalierung von Canvas-Pixeln entgegenzuwirken.
Unten finden Sie eine Demo mit dieser Strategie.
Bearbeiten : Hier ist die Geige des OP aktualisiert, um diese Strategie zu verwenden: http://jsfiddle.net/65maD/83/ .
quelle
Probieren Sie diese eine Zeile CSS auf Ihrer Leinwand aus:
image-rendering: pixelated
Wie pro MDN :
Somit wird Anti-Aliasing vollständig verhindert.
quelle
Für mich hat nur eine Kombination verschiedener "pixelgenauer" Techniken zur Archivierung der Ergebnisse beigetragen:
Holen Sie sich und skalieren Sie mit einem Pixelverhältnis, wie von @MyNameIsKo vorgeschlagen.
pixelRatio = window.devicePixelRatio / ctx.backingStorePixelRatio
Skalieren Sie die Leinwand in der Größenänderung (vermeiden Sie die Standard-Stretch-Skalierung der Leinwand).
Multiplizieren Sie die Zeilenbreite mit pixelRatio, um die richtige "echte" Pixelliniendicke zu ermitteln:
context.lineWidth = Dicke * pixelRatio;
Überprüfen Sie, ob die Dicke der Linie ungerade oder gerade ist. Addiere die Hälfte des pixelRatio zur Linienposition für die ungeraden Dickenwerte.
x = x + pixelRatio / 2;
Die ungerade Linie wird in der Mitte des Pixels platziert. Die obige Zeile wird verwendet, um es ein wenig zu verschieben.
Das Größenänderungsereignis wird im Snipped nicht ausgelöst, sodass Sie die Datei auf dem Github ausprobieren können
quelle