Ich versuche, einen serverseitigen Renderer für HighCharts zu implementieren. Alles scheint gut zu funktionieren, außer dass im resultierenden SVG-Markup überall die Werte für x, y, Breite und Höhe fehlen. Durch einige Debugging glaube ich, dass ich das Problem auf die Tatsache hingewiesen habe, dass offsetWidth, offsetHeight, offsetTop und offsetLeft für jedes Element nicht definiert sind.
Sollen diese Eigenschaften in einer zukünftigen Version enthalten sein? Gibt es auch eine Problemumgehung, die ich vorerst implementieren kann?
Ich denke, http://www.w3.org/TR/cssom-view/ müsste implementiert werden.
Wir haben mit der Integration von CSS begonnen, was einige der SVG-Probleme lösen sollte.
Es wäre in der Tat großartig, wenn wir auf die offset*-Eigenschaften zugreifen könnten, die für ein Canvas-bezogenes Projekt benötigt würden.
Wie ist der Fortschritt in diesem Thema? Ich würde mich auch über eine solche Funktion für das Backend-Sag-Rendering mit Highcharts freuen.
Das hätte ich auch gerne :)
Haben Sie irgendwelche Ersatzzyklen, die Ihnen helfen können? Persönlich brauche ich svg 1.1 nicht, aber ich wäre bereit zu helfen, es zu landen, wenn ihr Jungs genug brennt, um auch daran zu arbeiten.
@tmpvar : Ich würde gerne helfen, aber ich bin ziemlich neu in diesem serverseitigen JS-Zeug.
Vielleicht können Sie mir einen Tipp geben, wo ich anfangen soll und ich könnte mein Bestes geben, um etwas in Gang zu bringen :)
Ich interessiere mich auch sehr für SVG 1.1, um Highcharts auf dem Server zu aktivieren. Ich würde gerne Hilfe anbieten, aber zuerst muss ich mich mit SVG 1.0 und seiner aktuellen Implementierung in jsdom vertraut machen, was eine Weile dauern kann ;)
Ich denke, der erste Schritt hier ist, sich eine Kopie der Testsuite (http://www.w3.org/Graphics/SVG/WG/wiki/Test_Suite_Overview) zu besorgen und sie in Headless umzuwandeln (was ein ziemliches Unterfangen sein kann).
Dann können wir level2/svg.js
hinzufügen und mit der Implementierung beginnen.
Ich werde wahrscheinlich irgendwann dazu kommen, aber es steht derzeit nicht ganz oben auf meiner Liste der jsdom-Prioritäten.
@href die svg 1.0-Implementierung ist ziemlich kahl. Es besteht die Tests in level1/core
, implementiert jedoch nicht wirklich etwas svg-spezifisches.
Ich denke, das getBoundingCLientRect ist nicht richtig implementiert.
Ich habe diesen Code, um ein bestimmtes SVG-Element zu berechnen:
var html = '<!DOCTYPE html><html><head><title></title></head><body style="margin: 0; padding: 0;"><svg id="svg" xmlns="http://www.w3.org/2000/svg" version="1.1" style="margin: 0; padding: 0;"><rect style="" x="10" y="10" width="100" height="100" rx="0" ry="0"/></svg></body></html>';
jsdom.env({
html : html,
src: [jquery],
done: function (errors, window) {
var $ = window.$;
var clientBox = $("#svg").find(type)[0].getBoundingClientRect();
console.log(clientBox);
}
});
Und das Ergebnis ist:
{ bottom: 0, height: 0, left: 0, right: 0, top: 0, width: 0 }
Aber wenn ich den gleichen HTML-Code im Webbrowser teste, ist das Ergebnis folgendes:
{ bottom: 110, height: 100, left: 10, right: 110, top: 10, width: 100 }
@throrin19 : Lies
Es ist also unmöglich zu erreichen? Bisher habe ich es geschafft, dieses Problem durch phantomJS zu umgehen, aber es ist extrem langsam und wenn ich ein großes SVG habe, stürzt es ab.
Ich meine, es ist nicht unmöglich, aber wir müssten eine ganze Layout-Engine schreiben, und niemand hatte die Zeit dafür.
Ich habe darüber nachgedacht, aber dann verkrampft sich mein Gehirn und ich muss weg.
Gibt es Tests über Säure hinaus, die befolgt werden könnten?
+1 dafür, dass dies eine sehr wünschenswerte Funktion ist
Ich verwende dieses Snippet zur Unterstützung, was für meinen Fall funktioniert. Denken Sie daran, dass es weit von einer ordnungsgemäßen Implementierung entfernt ist. Beachten Sie, dass window
Ihr document.parentWindow
.
Wenn Sie eine bessere Implementierung benötigen, erweitern Sie den Code mit der Spezifikation:
http://dev.w3.org/csswg/cssom-view/#dom -htmlelement-offsetleft
Object.defineProperties(window.HTMLElement.prototype, {
offsetLeft: {
get: function() { return parseFloat(window.getComputedStyle(this).marginLeft) || 0; }
},
offsetTop: {
get: function() { return parseFloat(window.getComputedStyle(this).marginTop) || 0; }
},
offsetHeight: {
get: function() { return parseFloat(window.getComputedStyle(this).height) || 0; }
},
offsetWidth: {
get: function() { return parseFloat(window.getComputedStyle(this).width) || 0; }
}
});
Hat jemand anderes Erfolg mit dem, was Tobyhinloopen vorgeschlagen hat?
@tobyhinloopen : Mein Diagrammhintergrund, meine Achse und Beschriftungen werden
Ich hatte einen anderen Anwendungsfall, bei dem meine vorgeschlagene Implementierung funktionierte. Wenn es für Sie nicht funktioniert, verlängern Sie es. Likely OffsetHeight/width muss auch die Auffüllung enthalten. Ich würde einige hackige Hotfixes vorschlagen, damit es funktioniert, da eine perfekte Implementierung schwierig zu implementieren ist.
Die von @tobyhinloopen vorgeschlagene
@zallek Ich denke, Sie haben dann bereits offsetLeft-Unterstützung :) Was gibt window.HTMLElement.prototype.offsetLeft
zurück? Wenn es alles andere als undefiniert ist, funktioniert meine Lösung nicht
Wollte mich nur bedanken
@tobyhinloopen Vielen Dank für das Posten der Lösung! Es ist sehr hilfreich und funktioniert, solange ich eine Variable verwende, um den Wert von offset festzulegen und this
auszuschließen. this
kommt undefiniert heraus, was sinnvoll ist, wenn man bedenkt, dass der Kontext nicht die eigentliche Klasse ist. Ist das das, was Sie erwarten?
@jordantomax dies wird beim Aufruf der Funktion an das Element gebunden, nicht beim Definieren der Funktion. 'this' sollte das Element sein, wenn Sie es von einem beliebigen HTML-Element aus aufrufen.
Wenn nicht, würde ich gerne ein Beispiel sehen.
@tobyhinloopen Danke für die schnelle Antwort. Das würde ich erwarten. Wenn ich versuche, mein Problem in Codesandbox mit einer echten Browserumgebung zu reproduzieren, funktioniert es ordnungsgemäß. Aber wenn ich Scherze verwende, sehe ich this
als undefiniert. Ich habe ein kleines Beispiel-Repository erstellt, um Ihnen zu zeigen, was ich erlebe, vielleicht ist mein Setup falsch.
https://github.com/jordantomax/jest-htmlelement-prototype-sandbox
In Verbindung damit habe ich auch Probleme beim Überschreiben von Methoden wie scrollIntoView
mit jest und jsdom. Gibt es eine empfohlene Vorgehensweise?
Vielen Dank für deine Hilfe!
Ich denke , es ist , weil Sie verwenden get: () => {}
- Die () => {}
Funktion Syntax Verwirrungen mit Ihrem this
. Wenn Sie stattdessen get() {}
(empfohlen) oder get: function() {}
(alternativ) verwenden, funktioniert es. @jordantomax
Sie verwenden auch =>
in den it
/ describe
's Ihrer Testsuite. Ich kenne JEST nicht, aber in MOCHA wird es nicht empfohlen, da this
in Ihrem it
/ test
/ describe
alle Arten von hat Dienstprogramme, auf die Sie nicht zugreifen können, wenn Sie die Pfeilfunktionen verwenden. Zum Beispiel hat Mokka Dinge wie this.slow()
, this.timeout(4000)
usw.
https://mochajs.org/#arrow -Funktionen
In Verbindung damit habe ich auch Probleme beim Überschreiben von Methoden wie scrollIntoView mit jest und jsdom. Gibt es eine empfohlene Vorgehensweise?
Normalerweise ist auf MDN eine Art Polyfill verfügbar. Versuchen Sie andernfalls einfach, es basierend auf der Spezifikation so zu implementieren, dass es Ihren Anforderungen entspricht. Wenn alles fehlschlägt, verwenden Sie einfach eine andere Testumgebung. JSDom hat seinen Platz, aber irgendwann möchten Sie vielleicht stattdessen einen echten Browser in Betracht ziehen. Viele Testumgebungen ermöglichen das Testen in echten Browsern (auch in mehreren gleichzeitig) und melden gleichzeitig Echtzeit an Ihren Entwicklungscomputer. IIRC Karma macht das -> https://karma-runner.github.io/latest/index.html
Ich habe mehrere Browser gleichzeitig auf meinem Computer geöffnet (Firefox Chrome Safari Internet Explorer Edge + mobile in Simulatoren), und alle haben sich in Echtzeit mit Karma + Mocha gemeldet.
@tobyhinloopen Richtig bist du auf allen Konten! Dankeschön!! Mir ist immer noch ein wenig unklar, warum getComputedStyle
notwendig ist und ob es möglich ist, einen Setter mit dieser Methode zu schreiben. Bei mir scheint das zu funktionieren:
Object.defineProperties(window.HTMLElement.prototype, {
offsetTop: {
get () {
return this.marginTop
},
set (offset) {
this.marginTop = offset
}
}
})
Danke nochmal
@jordantomax getComputedStyle
holt den echten berechneten Stil für alle CSS-Eigenschaften, egal wo er angewendet wurde (Stylesheet, style
Attribut oder aus JS). Ich bin mir nicht sicher, ob this.marginTop
dasselbe tut, aber ich denke, es tut es (aber natürlich nur für den Rand, nicht für alle CSS-Requisiten)
@tobyhinloopen Ah, verstanden. Dankeschön!
Danke @tobyhinloopen . Ich verwende eine noch kürzere Version. Ich denke, getComputedStyle
wird nicht wirklich benötigt, da ich persönlich nie CSS zu meinen Unit-Tests hinzufüge, es sei denn, es ist Inline, weshalb .style
gut genug und schneller ist.
Object.defineProperties(window.HTMLElement.prototype, {
offsetLeft: {
get () { return parseFloat(this.style.marginLeft) || 0 }
},
offsetTop: {
get () { return parseFloat(this.style.marginTop) || 0 }
},
offsetHeight: {
get () { return parseFloat(this.style.height) || 0 }
},
offsetWidth: {
get () { return parseFloat(this.style.width) || 0 }
}
})
Wurde dies behoben, erhalte ich offsetWidth = 0
const dom = new JSDOM(`<!DOCTYPE html><body></body>`);
let document = dom.window.document
let span = document.createElement("span");
span.innerHtml = 'test
span.style.fontSize = 150 + 'px';
span.style.fontFamily = 'Arial'
document.body.appendChild(span)
console.log(span.offsetWidth) // 0
Wurde dies behoben, erhalte ich offsetWidth = 0
@petran Es ist nicht realistisch zu erwarten, dass jsdom die Breite Ihres SPAN berechnet, da dies die Kenntnis der Größe Ihrer Schriftart und aller geerbten CSS-Eigenschaften erfordert. Ich glaube nicht, dass das das Ziel von JSDOM ist. Wenn Sie eine genauere Simulation eines Browsers wünschen, sollten Sie einen tatsächlichen Browser verwenden.
Hilfreichster Kommentar
Ich verwende dieses Snippet zur Unterstützung, was für meinen Fall funktioniert. Denken Sie daran, dass es weit von einer ordnungsgemäßen Implementierung entfernt ist. Beachten Sie, dass
window
Ihrdocument.parentWindow
.Wenn Sie eine bessere Implementierung benötigen, erweitern Sie den Code mit der Spezifikation:
http://dev.w3.org/csswg/cssom-view/#dom -htmlelement-offsetleft