zeichnen 10.000 Objekte auf Leinwand javascript
Muss ich ziehen über 10.000 Bilder (32x32 px) auf der Leinwand aber über 2000 zieht der Vorstellungen ist sehr schlecht.
dies ist ein kleines Beispiel:
Objekt-Struktur {position:0}
for(var nObject = 0; nObject < objects.length; nObject++){
ctx.save();
ctx.translate(coords.x,coords.y);
ctx.rotate(objects[nObject].position/100);
ctx.translate(radio,0);
ctx.drawImage(img,0,0);
ctx.restore();
objects[nObject].position++;
}
mit diesem code, den ich übersetzen die Bilder, um eine Koordinaten.
Was empfehlen Sie, um die Leistung zu verbessern?
update:
ich versuchen, Schichtung, aber die Leistungen verschlechtert
- Je nachdem, was Sie zeichnen, Sie zeichnen könnte Sie über mehrere Leinwände mit der statischen nicht ändern Objekte auf einen zu vermeiden, Neuzeichnen Sie,
- alle Bilder verändern Ihre position im Zyklus, aber nicht das Bild ändern
- Könnten Sie setup ein live-Beispiel
- jsfiddle.net/B72gk
- können Sie echte Bilder Beispiel? sind alle diese Bilder anders? können Sie vermeiden die rotation? alle diese Bilder ändern Ihre position bei jedem Bild? Mit diesem wissen kann helfen, zu finden-Optimierung.
- Hallo viliusL das Beispiel-Bild ist sehr ähnlich wie das original-und manchmal ist das Bild auch ändern.
- WADR, möchten Sie vielleicht ändern Sie Ihre design. 10,000 Elemente wie die in deinem Beispiel fiddle würde überwältigend sein, um die Zuschauer Aufmerksamkeit. Mehr ist nicht immer besser-versuchen Sie Ihr design mit 500 Elementen statt. Die Ergebnisse werden innerhalb der Leistungsgrenzen von html-canvas und innerhalb Ihrer Zuschauer Grenzen der Wertschätzung!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich kann Ihnen 10.000 es gibt aber zwei wesentliche Nachteile.
Können Sie feststellen, die Bilder nicht respektieren, Transparenz komplett aus, es ist möglich, zu beheben.. aber das würde den Rahmen dieser Antwort.
Müssen Sie mit Mathematik zu tun, jede Art von Veränderungen, denn das standard-canvas-transformation matrix nicht angewendet werden können, um Bilddaten
Live-Demo
Erklärung des Codes und Methoden
So um die Schnellste Leistung möglich mit Leinwand und eine große Anzahl von Objekten, die Sie verwenden müssen,Bilddaten. Dies ist der Zugriff auf das canvas-element auf einer pro-pixel-Ebene, im Grunde, und erlaubt Ihnen, alle Arten von Coole Sachen. Früher habe ich zwei primäre Methoden.
Ist auch hier ein nettes tutorial, geht in es ein bisschen zu helfen, ein besseres Verständnis.
So habe ich zunächst erstellt eine temporäre Leinwand für das Bild
Nächsten Ist das wichtigste Stück, das in der rendering-Funktion
Ich bin einfach nur posten die relevanten Teile.
Den wichtigsten Weg von diesem ist, wenn Sie brauchen, um zu zeichnen, eine lächerliche Anzahl von Objekten auf der Leinwand, die Sie nicht Verwendung
drawImage
, pixel manipulation ist dein Freund.Uint32Array
Blick über die zugrunde liegendenArrayBuffers
verwendet für dieUint8Clamped
arrays voncData
undImagePixData
und kopieren von 32 bits auf einmal. Dies ist etwas schneller.h
in die äußere Schleife, undw
im inneren). Zweitens, werden Sie nicht rufen SiecreateImagedata
jeder Runde mit Schleife - tun Sie es einmal in einem set-up-Funktion und re-verwenden Sie IhrecData
array (um den Bildschirm zu löschen, verwenden SiecData.fill(0)
). TypedArray-Allokation ist immer noch ein bisschen langsamIch denke diese, was Sie brauchen.
Eric Rowell (Schöpfer von KineticJS) hat getan, einige tests hier.
Und er sagt dies:
"Erstellen Sie in 10 Ebenen jede enthält 1000 Formen zu schaffen, die 10.000-Formen. Dies verbessert die Leistung, da nur 1000 Formen haben, gezogen zu werden, zu einer Zeit, als ein Kreis, der entfernt wird, ein layer statt alle 10.000 Formen."
"Im Hinterkopf behalten, dass zu viele Schichten können auch verlangsamen Leistung. Ich fand, dass mit 10 Ebenen mit jeweils 1.000 Formen besser abschneidet als 20 Ebenen mit 500 Formen oder 5 Schichten mit 2.000 Formen."
Update: müssten Sie führen test-Fälle, in denen die optimierte Verfahren für Sie sein würde.
Beispiel: 10000 Formen kann erreicht werden, indem entweder:
Je nachdem, was funktioniert für Sie,wählen Sie!
Es hängt von Ihrem code.
Hier sind einige Schritte, die Sie tun können, um die Leistung zu erhöhen:
save
/restore
- Sie sind sehr teuer, fordert und ersetzt werden kann, mitsetTransform
FIDDLE
Beispiel mit Schleife abgewickelt für 4 Iterationen:
(erwarte nicht, dass Echtzeit-performance aber).
Obwohl, es ist vielleicht ein bisschen sinnlos, Zeichnung 2000-Objekte in einem so kleinen Bereich. Wenn Sie nach der Wirkung ich würde vorschlagen, diesen Ansatz statt:
Wenn Sie brauchen mehr Flüssigkeit sehen einfach produzieren mehr frames. Speichern Sie jedes Bild in einer einzigen Leinwand, basierend auf Zellen, die Sie verwenden, wie ein sprite-Blatt später. Beim zeichnen müssen Sie natürlich aufpassen, dass die aktuellen Positionen sind statisch versus bewegt, wenn tatsächlich animiert. Rotation und die daraus resultierende position ist ein weiterer Faktor.
Nach diversen tests komme ich zu folgenden Schlussfolgerungen:
das Ergebnis ist eine kleine Mischung aus allen Beiträgen. aber muss verbessert werden.
Getestet mit 30.000 Objekte und die Leistung bleibt bei 60/fps.
http://jsfiddle.net/NGn29/1/
Wenn die Bilder nicht überlappen, dann ist das resultierende Bild ist 3200x3200 Pixel, das ist mehr als die meisten displays angezeigt werden können. So können Sie versuchen, um die bounding-box des transformierten Bildes und überspringen diejenigen, die sich außerhalb des sichtbaren Bereichs (auch wenn die Leinwand sollte schon das für Sie tun).
Einer anderen Idee kombinieren Sie die kleinen Bilder in größeren und verwandeln Sie zusammen als eine Gruppe.
Wenn Sie möchten, organisieren der Bilder in einem ring, dann können Sie zeichnen, Sie einmal als ring, speichern als Bild, und drehen Sie dann die "ring-Bild" anstatt jedes einzelne Bild.
Schließlich haben Sie einen Blick auf WebGL, die möglicherweise effizienter als 2D -
canvas
API.