Feature detection für SVG
Für den letzten Blogeintrag über Twitter habe ich auf die Grafik des Vogels bei openclipart.org verlinkt. Sieht man sich diese Grafik mit Safari oder dem IE9 an, sieht sie ziemlich schlecht aus.
Das liegt daran, dass diese Browser bisher filter überhaupt nicht interpretieren. Dadurch sparen sie erhebliche Rechenzeit, erschweren damit aber selbst einfachste grafische Effekte. Das es besser geht zeigt, wieder einmal Chrome, der schnell bleibt und in der Interpretation von filter jetzt zu Opera und Firefox aufschließt.
Für die Grafik bei openclipart.org ist das ohne Belang, da Inkscape und andere Programme selbstverständlich diese Fähigkeiten haben und langfristig (bis Ende 2011) Safari und der Internet Explorer darum nicht herum kommen. Will man die Grafik heute im Web einsetzen, kann man natürlich diese Pfade weglassen, was ich auch getan habe. Eine andere Möglichkeit ist eine Browserweiche, welcher die Pfade nur dann ausblendet, wenn die Eigenschaft vom Browser nicht unterstützt wird. (feature detection)
Es soll nicht darum gehen, bestimmte Browser über ihren UA-String zu erkennen, sondern zu testen, ob sie die gewünschten Fähigkeiten haben. Dafür scheint ein in das Dokument integriertes Script, welches .hasFeature() nutzt, wie geschaffen. Das klappt auch recht gut, um Animationen zu erkennen, wie das c't-Beispiel zeigt.
Leider funktioniert das bei der Erkennung von SVG-Filtern, bisher nur in Opera. Folgende Lösung ist durch Anregung der SVG-Developer-Liste und von Thomas Meinike entstanden:
function noFilter() {
document.getElementById("highlight").setAttribute("opacity",0);
document.getElementById("highlightwing").setAttribute("opacity",0)
}
function init() {
var fsupport = ((document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Filter", "1.1")) || (!!document.createElementNS && /SVGFE/.test(toString.call(document.createElementNS('http://www.w3.org/2000/svg','feGaussianBlur')))))? true : false;
if (!fsupport) noFilter();
}
document.addEventListener("DOMContentLoaded", init, false);
Das Script wird beim Laden der Seite aufgerufen und setzt die Sichtbarkeit der "verwischten" Bereiche auf 0. Den kryptische Teil der init-Funktion, der von Erik Dahlström stammt, will ich kurz erklären:
(toString.call(document.createElementNS('http://www.w3.org/2000/svg','feGaussianBlur')))
Call ruft eine Funktion auf, die ein Objekt erstellt, die den Verwischen-Filter enthält. Das gelingt natürlich nur, wenn der Browser das auch unterstützt. Deshalb kann mit dem regulären Ausdruck
/SVGFE/
überprüft werden, ob dieser enthalten ist. Dies erledigt .test. Wenn es keine Übereinstimmung gibt, wird die Funktion noFilter() aufgerufen.
Demo des Twittervogels mit Featureerkennung
Da sich Otto Normalnutzer eine Seite nicht mit unterschiedlichen Browsern ansieht, wird die feature detection nur auf den Verwischen-Filter angewandt, um eine Störung des grafischen Effekts zu verhindern. Natürlich wird der Effekt, der die Federn simulieren soll, auch nicht angewandt.
Ergänzung (01.12.2010:)
Die Anregung von @molily habe ich aufgegriffen:
function init() {
var fsupport = ((document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Filter", "1.1")) || (typeof document.createElementNS('http://www.w3.org/2000/svg','feGaussianBlur').setStdDeviation == 'function'))? true : false;
if (!fsupport) noFilter();
Hier liegt der Clou darin, dass das erzeugte Obkekt daraufhin überprüft wird, ob eine bestimmte Funktion existiert. Für den blur-Filter muss es eine Standardabweichung geben.
verbesserte Demo des Twittervogels
geschrieben von Pawel
Kommentare
Danke für den Tip. Ich habe das Script und den Blogeintrag angepasst.
geschrieben von am 01.12.10
Eine wirkliche Feature-Detection ist das nun nicht. Es wird ein Element erzeugt und toString darauf aufgerufen. Dann wird angenommen, dass bei der Umwandlung ein bestimmter String herauskommt (der IDL-Interfacename). Was die Browser bei toString ausspucken, ist jedoch höchst willkürlich und meines Wissens nirgends standardisiert (außer bei der Anwendung von Object.prototype.toString auf ECMAScript-Basistypen).
Das hat nun wenig mit Feature-Detection zu tun und solche toString-Tests haben in der Vergangenheit schon einmal zu falschen Resultaten geführt. Warum hier nicht prüfen, ob beim erzeugten Element Eigenschaften und Methoden existieren. Z.B. ‘setStdDeviation’ in document.createElementNS(‘http://www.w3.org/2000/svg’,‘feGaussianBlur’) oder typeof document.createElementNS(‘http://www.w3.org/2000/svg’,‘feGaussianBlur’).setStdDeviation == ‘function’.
geschrieben von molily am 29.11.10