mmofacts.com

Performante Methode um viele Grafiken einzubinden?

gepostet vor 13 Jahre, 11 Monate von condor83

Hallo an alle die hier lesen.

Ich weiß, der titel ist nicht so Optimal...

Foldendes:

Ich arbeite an einer Karte die sich aus vielen kleinen Grafiken zusammensetzt und per Drag&Drop verschiebbar ist, beim darüberfahren Infos anzeigt usw...

Ich lade dabei alle Karteninfos in Javascript und somit gibts beim Scrollen und Neuzeichnen der Karte keinen weiteren Traffic. Alle grafiken liegen in einer Bilddatei.

Mein erster versuch war es für jeden Grafikschnipsel ein div zu generieren und mit clip den entsprechenden Inhalt anzeigen. Da die karte aber Vollbild ist werden das bei größeren Monitoren einige 100 bis 1000 divs. Trotzdem funktioniert diese Variante recht flüsig auf den gängigen Browsern.

Einen weiteren veruch hab ich mit dem neuen canvas Element versucht um darin die Karte zu zeichnen. Läuft im Firefox sehr gut und bietet viele zusätzliche praktische Möglichkeiten. Aber der IE unterstützt kein HTML5 und daher mußte ich für den auf ein script namens excanvas zurückgreifen aber da ist die Performance mieserabel - und den IE ausschliesen kann und will ich auch nicht (auch wenn ich kein Fan davon bin).

Kennt jemand weitere Möglichkeiten um viele viele Teilgrafiken schnell in den Browser zu zeichnen (per Javascript - eine neue Sprache muß es nicht sein...) sodass beim Scrollen ein recht flüssiger Eindruck entsteht?

Sollte auf den gängigen Browsern laufen und wenn möglich keine Plugins nutzen, die der Nutzer vorher installieren müsste.

gepostet vor 13 Jahre, 11 Monate von MrMaxx

Ich habe mich mit dem Canvas Element noch nicht auseinandergesetzt, daher gibt es von mir nur traditionelle Lösungen für DOM. Diese beruht auf meiner damaligen Recherche und eigenen Erfahrungen.

Das schnellste Methode ist es Elemente über innerHTML als String an den DOM zu hängen.

var elementString = 'blubber';

$('someElementId').innerHTML = elementString;

Das ganze hat jedoch einen grosse Nachteil: fügst du nachträglich weitere Elemente hinzu, wird der komplette innerHTML-String neu gerendert....alle Elemente!!! Und das ist bei mehreren hundert oder tausend Elementen nicht mehr schnell, sondern sehr sehr langsam.

Meine Lösung ist es verschiedene Layer zu haben. Meine eigentlich statische Karte rendere ich vor. Diese liegt als ein Bild vor uns muss einmal vom Benutzer geladen werden. die eigentlichen dynamischen Elemente werden immer komplett gerendert. Vetrschiebt sich der Bildschirmausschnitt, so schmeisse ich den kompletten Inhalt weg und render ihn neu. Das geht recht fix, wenn man immer den kompletten innerHTML auswechselt.

var elementStrings = new Array();

mydata.each(function( elem ){ elementString.push( Renderer.render() ); });

$('someElementId').innerHTML = elementString.join(' ');

Das ist bestimmt nicht die beste Lösung für alle Problemfälle, aber für mich funktionert es sehr gut.

Wer sich über die JS-Syntax wundert...ich verwende Prototype...diese veraltete JS-Library, die heutzutage kaum mehr verwendet wird. Falls sich jemand das ganze mal ansehen will, wie es bei mir funktionert kann er das gerne machen unter: http://overwatch.de .

Ihr braucht euch nicht registrieren, sonder könnt gleich über die Tutorials einsteigen.

Mein Javascript ist weder minified, noch obfuscated. Daher also gut lesbar.

EntryAreaRenderer ist für das High-Level Rendering der Eintrittspunkt-Elemente für Aliens zuständig.

TileFactory ist für das Low-Level Rendering von allen Elementen zuständig.

Vielleicht hilft dir das Beispiel ja...

Maxx

gepostet vor 13 Jahre, 11 Monate von SurelyPlus

Hallo condor83,

ich kenne mich nur mit der Generierung von HTML in Javascript ein wenig aus. Dabei bin ich über folgenden interessanten Vergleich von Generierungsmethoden für HTML Tables gestolpert:

http://www.oreillynet.com/javascript/2003/05/06/examples/dyn_table_benchmarker_ora.html

Dabei fand ich besonders interessant, dass die Methoden über die verschiedenen Browser hinweg unterschiedlich performant waren. D.h. in Firefox war Methode X besser als Y und im aktuellen Chrome umgekehrt.

Diese Generierung passt natürlich nicht 100% auf DIVs, da die Spezialmethoden für Tables verwendet werden, aber innerHTML (wie schon von MrMaxx genannt) und createElement sind die 2 Hauptmethoden.

Ein weiterer wichtiger Punkt bei der Manipulation des DOM Baums ist der "Reflow":

http://code.google.com/intl/de-DE/speed/articles/reflow.html

Reflow is the name of the web browser process for re-calculating the positions and geometries of elements in the document, for the purpose of re-rendering part or all of the document.

Z.B. sollte beim Erzeugen von Nodes mit der Javascript Methode create darauf geachtet, werden, dass die Elemente nicht Stück für Stück hinzugefügt werden, sondern zunächst ein DocumentFragment erzeugt wird, diese mit allen "neuen" Elementen befüllt und anschließend in das Dokument gehängt.

Hast du möglicherweise schon Beispielcode oder eine Seite wo man sich das später gewünschte Ergebnis mal anschauen kann?

Gruß

SurelyPlus

gepostet vor 13 Jahre, 11 Monate von condor83

Vielen dank für die Antworten.

Die Methode mit innerHTML ist eben auch meine beste Möglichkeit die auf jedem Browser recht gut läuft. Dabei schreibe ich derzeit alles in einen String den ich dan als ganzes an innerHTML übergebe. Eine einzellne Grafik als Hintergrundkarte ist leider nicht möglich da diese Bilddatei riesig wäre und ständig wachsen würde... (die Karte hat variable Dimmensionen)

Ich hatte gehofft dass es vielleicht ewas besseres "schöneres" als die oft kritisierte innerHTML methode gibt. Canvas wär perfekt - aber Microsoft spielt nicht mit.

Hab mir einige Gedanken gemacht wie ich Grafiken besser zusammenfassen kann um divs zu sparen. Oder eben 2 Mapengines. Eine mit divs für den IE die halt nicht ganz so schön und schnell ist. Und eine mit canvas für alle Anderen... (ich hasse doppeltes programmieren)

@MrMaxx - interessantes Spiel! Erinnert an die alten X-COM / UFO Spiele die ich bis zum umfallen gespielt habe.

gepostet vor 13 Jahre, 11 Monate von BlackScorp

hm.. ich denke ich werde auch mal mit string und innerhtml versuchen. zz mache ich das ganze mit

var tile =document.createElement('div');

tile.irgendwas setzen

$('.map').append(tile);

und läuft eigentlich ganz flüssig

http://cruel-online.de/map2/

(noch keine ajax requests drin und koordinate sind falsch:D)

habe gerade die map geändert.. davor hatte ich das mit jQuery und append einzelne tiles reingesetzt.. bei x/y koordinaten 2000/2000 ist dann JS abgestürzt... mit string zusammensetzen und dann innerhtml stürzt es nicht mehr ab..

Auf diese Diskussion antworten