javascript - El gráfico NVD3 no puede calcular la longitud del texto de leyenda en Chrome, ya que Window.getComputedStyle no devuelve el tamaño de fuente correctamente
css svg (1)
Información de fondo
Creé una integración de gráficos NVD3 en Eclipse-RAP utilizando su marco de widget personalizado. El cuadro se genera en un div. El CSS se carga dinámicamente al crear una entrada de enlace en javascript. Compruebo si el CSS ya está cargado al crear un elemento SVG / texto, y verifico si su font-size
está bien o no (vea https://stackoverflow.com/a/7997710/337621 ). Si el CSS está cargado, creo el gráfico.
Problema
Por algún motivo, el gráfico no se muestra siempre correctamente en Chrome. Por lo general, la primera vez en mi sesión se muestra correctamente, pero la segunda vez se muestra siempre mal. En el caso equivocado, he encontrado esto en la consola:
Error: Invalid value for <g> attribute transform="translate(NaN,5)"
Si hago que el gráfico se vuelva a dibujar (por ejemplo, actualizando los datos del gráfico o cambiando el tamaño), la leyenda se representa correctamente.
Esperado:
Diseño incorrecto:
Después de algunas depuraciones, he encontrado la parte relevante del código d3. NVD3 pregunta por el tamaño de fuente para un elemento de texto SVG usando esta función:
d3_selectionPrototype.style = function(name, value, priority) {
var n = arguments.length;
if (n < 3) {
if (typeof name !== "string") {
if (n < 2) value = "";
for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
return this;
}
if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);
priority = "";
}
return this.each(d3_selection_style(name, value, priority));
};
La parte relevante de CSS es esta:
svg text {
font: normal 12px Arial;
}
Agregué el siguiente "punto de impresión" (punto de corte condicional, que nunca se detiene, pero imprime valores) en la línea con la llamada getComputedStyle
:
name == ''font-size'' &&
(
console.log(this.node()) ||
console.log( d3_window.getComputedStyle(this.node(), null) ) ||
console.log( d3_window.getComputedStyle(this.node(), null).getPropertyValue(name) ) ||
console.log( window.getMatchedCSSRules(this.node()) )
)
El resultado es realmente extraño. Si el cuadro es correcto, lo encuentro en la consola para el diseño correcto:
Y esto para el diseño incorrecto:
Este es el DOM para el diseño incorrecto:
<svg id="ujdh846lhqubvvlg2jbh16s6q9" width="1896" height="361">
<g class="nvd3 nv-wrap nv-pieChart" transform="translate(20,90)">
<g>
<g class="nv-pieWrap">
<g class="nvd3 nv-wrap nv-pie nv-chart-6450" transform="translate(0,0)">
<g>
<g class="nv-pie" transform="translate(928,125.5)">
<g class="nv-slice" fill="#1f77b4" stroke="#1f77b4">
<path d="M6.1477269317197136e-15,-100.4A100.4,100.4 0 0,1 65.39779726531111,76.17931551835622L0,0Z"/>
</g><g class="nv-slice" fill="#ff7f0e" stroke="#ff7f0e">
<path d="M65.39779726531111,76.17931551835622A100.4,100.4 0 0,1 -90.13957577290248,44.21557281638648L0,0Z"/>
</g><g class="nv-slice" fill="#2ca02c" stroke="#2ca02c">
<path d="M-90.13957577290248,44.21557281638648A100.4,100.4 0 0,1 -94.15031406756688,-34.869447385619964L0,0Z"/>
</g><g class="nv-slice" fill="#d62728" stroke="#d62728">
<path d="M-94.15031406756688,-34.869447385619964A100.4,100.4 0 0,1 -1.844318079515914e-14,-100.4L0,0Z"/>
</g>
</g><g class="nv-pieLabels" transform="translate(928,125.5)">
<g class="nv-label" transform="translate(112.95224431711586,-41.8329177051586)">
<rect rx="3" ry="3" style="stroke: rgb(255, 255, 255); fill: rgb(255, 255, 255);"/>
<text style="text-anchor: middle; fill: rgb(0, 0, 0);">alma</text>
</g><g class="nv-label" transform="translate(-24.246406744679096,117.98438142386297)">
<rect rx="3" ry="3" style="stroke: rgb(255, 255, 255); fill: rgb(255, 255, 255);"/>
<text style="text-anchor: middle; fill: rgb(0, 0, 0);">korte</text>
</g><g class="nv-label" transform="translate(-120.2954032887533,6.100692386622933)">
<rect rx="3" ry="3" style="stroke: rgb(255, 255, 255); fill: rgb(255, 255, 255);"/>
<text style="text-anchor: middle; fill: rgb(0, 0, 0);">szilva</text>
</g><g class="nv-label" transform="translate(-68.80925650816773,-98.86095649341644)">
<rect rx="3" ry="3" style="stroke: rgb(255, 255, 255); fill: rgb(255, 255, 255);"/>
<text style="text-anchor: middle; fill: rgb(0, 0, 0);">paradicsom</text>
</g>
</g>
</g>
</g>
</g><g class="nv-legendWrap" transform="translate(0,-90)">
<g class="nvd3 nv-legend" transform="translate(0,5)">
<g transform="translate(NaN,5)">
<g class="nv-series" transform="translate(0,5)">
<circle class="nv-legend-symbol" r="5" style="stroke-width: 2px; fill: rgb(31, 119, 180); stroke: rgb(31, 119, 180);"/>
<text text-anchor="start" class="nv-legend-text" dy=".32em" dx="8">alma</text>
</g><g class="nv-series" transform="translate(0,25)">
<circle class="nv-legend-symbol" r="5" style="stroke-width: 2px; fill: rgb(255, 127, 14); stroke: rgb(255, 127, 14);"/>
<text text-anchor="start" class="nv-legend-text" dy=".32em" dx="8">korte</text>
</g><g class="nv-series" transform="translate(0,45)">
<circle class="nv-legend-symbol" r="5" style="stroke-width: 2px; fill: rgb(44, 160, 44); stroke: rgb(44, 160, 44);"/>
<text text-anchor="start" class="nv-legend-text" dy=".32em" dx="8">szilva</text>
</g><g class="nv-series" transform="translate(0,65)">
<circle class="nv-legend-symbol" r="5" style="stroke-width: 2px; fill: rgb(125, 0, 0); stroke: rgb(125, 0, 0);"/>
<text text-anchor="start" class="nv-legend-text" dy=".32em" dx="8">paradicsom</text>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
¿Cómo puede ser que una vez que mi SVG / texto no tenga tamaño de fuente en el estilo calculado PERO siempre tenga el tamaño de fuente en una de las reglas CSS aplicadas?
¿Hay algún error conocido en Chrome para esto?
Tenga en cuenta que en Firefox todo funciona bien.
Detalles del entorno
Chrome 39.0.2171.71 (64 bits)
Kubuntu 3.13.0-29-genérico
Actualizar
Pensé que me afectaba este "comportamiento" de los navegadores: ¿cómo puedo cambiar el comportamiento predeterminado de console.log? (* Consola de error en safari, sin complemento *) . Esto significa que la consola no muestra el estado del objeto en el momento de la entrada del registro, sino que se refiere al estado actual. Así que hice un pequeño experimento aquí: http://jsfiddle.net/hdv7ty6L/ . Cambio la clase de javascript y compruebo si la lista de reglas cambia en la consola o no. Y parece ser una instantánea de la lista de reglas. Entonces todavía no hay pista, ¿qué está mal aquí? :)
Código de prueba:
document.body.className=''redbody'';
console.log(window.getMatchedCSSRules(document.body));
document.body.className=''bluebody'';
console.log("Class changed");
console.log(window.getMatchedCSSRules(document.body));
Salida de la consola:
Actualización 2
El problema también ocurre si el CSS es completamente estático y no se carga dinámicamente.
Actualización 3
Traté de reproducirlo en un jsfiddle: SVG creado dinámicamente dentro de un div con un gráfico creado de forma asincrónica (al hacer clic en un botón). El error no aparece desafortunadamente. https://jsfiddle.net/ewsb4d9k/1/
Lo siento, no soy muy fluido con D3, pero algunas ideas fuera de mi cabeza que podrían ser de alguna ayuda.
¿Ha intentado utilizar el método d3.select () y aplicando únicamente el tamaño de fuente de esta manera, para ver si puede limitar que la combinación de selector de fuente / texto sea un problema? Tal vez asigne una identificación o clase en la carga, luego defina sus estilos usando una hoja de estilo estática.
¿Has notado algo raro antes de que se rompa la longitud del texto de la leyenda? ¿La eliminación de la leyenda y la fuente de css funcionan el 100% del tiempo?
Me di cuenta de que estás usando Adblock. Vale la pena intentarlo si no lo has hecho todavía. Ese plugin hace cosas locas a veces.
¿Has probado una actualización completa del dom, o la actualización del contenedor, con carga? ¿Qué pasa con esto? ¿Rinde el 100% del tiempo? Aún fallas?
$("body").html($("body").html());
$("#d3div").html($("#d3div").html());
como se muestra en Timo en este hilo, el apéndice de jquery no funciona con el elemento svg?
"parece agregarlos en el explorador de DOM, pero no en la pantalla" y la razón de esto son diferentes espacios de nombres para html y svg.
La solución más fácil es "actualizar" toda la svg.
No parece que hayas trabajado con jQuery en esto, pero podría ser útil para probar en este caso.
Perdón por escuchar acerca de tu error loco. Espero que encuentres una solución.