Tengo la d3.js el código que se pega aquí.

Estoy tratando de mostrar más de uno de los gráficos en la misma página. A pesar de que el d3.js el código es el mismo. Dicen que uno de datos1.json y el otro de datos2.json. El siguiente es el fragmento que me molesta.

<svg width="960" height="960"></svg>

<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg2 = d3.select("svg"),
    margin = 20,
    diameter = +svg2.attr("width"),
    g = svg2.append("g").attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");

Como por diferentes respuestas en aquí, aquí, aquí, aquí o aquí, la solución parece ser uno de los siguientes:

  • Uso diferente del nombre de la variable para contener svgs como svg1, svg2.. etc..
    que he hecho.
  • Utilizar un método como el que se describe aquí.

       var chart1 = d3.select("#area1")
           .append("svg")

Método de los dos no está funcionando para mí, ya que muestra la página en blanco.

Cómo resolver esto. Estoy seguro de que no estoy recibiendo la sintaxis correctamente.

  • Usted parece estar usando uno de svg para varios gráficos (sólo tiene un elemento svg)? Método de los dos – ¿tiene usted un elemento html con un id="area1"? Has comprobado los desarrolladores de la consola de errores?

3 Comentarios

  1. 6

    No hay ningún problema en absoluto el uso de múltiples SVGs en la misma página. He aquí un ejemplo:

    JS:

    var svg1 = d3.select("#svg1");
    svg1.append("circle")
           .attr("cx",100)
           .attr("cy", 100)
           .attr("r", 90)
           .attr("fill", "red");
    var svg2 = d3.select("#svg2");
    svg2.append("circle")
           .attr("cx",100)
           .attr("cy", 100)
           .attr("r", 90)
           .attr("fill", "blue");

    HTML:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <svg width="200" height="200" id="svg1"></svg>
    <svg width="200" height="200" id="svg2"></svg>

    • Ok. ¡Lo tengo! Pero ¿cómo puedo convertir var svg2 = d3.select("svg"), margin = 20, diameter = +svg2.attr("width"), g = svg2.append("g").attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")"); a formato similar.
    • d3.select("svg") selecciona cada SVG objeto en el DOM. Usted no quiere hacer eso. En su lugar, dar a cada SVG un único id atributo (svg1 y svg2 en mi ejemplo), y las usan para referirse a los objetos SVG de forma individual con d3.select("#svg1") y d3.select("#svg2").
    • pastebin.com/evFYrn1f Aún no funciona. Siento que me estoy perdiendo algún tonto error de sintaxis.
    • Es d3.select("#svg1"), no d3.select("svg1").
    • usted dijo: «d3.seleccione(«svg») selecciona cada SVG objeto en el DOM». No, No es así. Ese código solo selecciona una SVG, que es el primero en el DOM.
    • Ah, tienes razón. Yo estaba pensando en jQuery. Gracias por decírmelo.
    • No se preocupe. En d3 tres es select y selectAll. El último haría lo que usted dijo en su comentario.
    • Buggeringly buena respuesta, delicado! Ayudó a uno de un estacionamiento, puedo decir.

  2. 3

    No hay necesidad de repetir todo el código, como estás haciendo ahora. Don’t repeat yourself.

    Una alternativa fácil es envolver todo su D3 código en una función que tiene dos parámetros, selector y url:

    function draw(selector, url){
        //code here
    };

    Luego, dentro de esa función draw, se establece la posición de su SVG:

    var svg = d3.select(selector).append("svg")...

    Y la URL de obtener los datos:

    d3.json(ulr, function(error, root) {...

    Después de eso, simplemente llame a la draw función dos veces, con distintos argumentos:

    draw(selector1, url1);
    draw(selector2, url2);

    Aquí es un demo, leerlo detenidamente para ver cómo funciona:

    JS:

    draw("#svg1", "#data1");
    draw("#svg2", "#data2");
    
    function draw(selector, url){
    
    var data = d3.csvParse(d3.select(url).text())
    
    var width = 500,
        height = 150;
    
    var svg = d3.select(selector)
        .append("svg")
        .attr("width", width)
        .attr("height", height);
    
    var xScale = d3.scalePoint()
        .domain(data.map(function(d) {
            return d.name
        }))
        .range([50, width - 50])
        .padding(0.5);
    
    var yScale = d3.scaleLinear()
        .domain([0, d3.max(data, function(d) {
            return d.value
        }) * 1.1])
        .range([height - 20, 6]);
    
    var line = d3.line()
    	.x(function(d){ return xScale(d.name)})
    	.y(function(d){ return yScale(d.value)});
    	
    svg.append("path")
    	.attr("d", line(data))
    	.attr("stroke", "teal")
    	.attr("stroke-width", "2")
    	.attr("fill", "none");
    
    var xAxis = d3.axisBottom(xScale);
    var yAxis = d3.axisLeft(yScale);
    
    svg.append("g").attr("transform", "translate(0,130)")
        .attr("class", "xAxis")
        .call(xAxis);
    
    svg.append("g")
        .attr("transform", "translate(50,0)")
        .attr("class", "yAxis")
        .call(yAxis);
    
    }

    CSS:

    pre {
    display: none;
    }

    HTML:

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <div>First SVG</div>
    <div id="svg1"></div>
    <div>Second SVG</div>
    <div id="svg2"></div>
    <pre id="data1">name,value
    foo,8
    bar,1
    baz,7
    foobar,9
    foobaz,4</pre>
    <pre id="data2">name,value
    foo,1
    bar,2
    baz,3
    foobar,9
    foobaz,8</pre>

    • Hola @Gerardo_Furtardo. ¿Me podrías recomendar algunos ejemplos con diferentes tipos de gráficos en una sola página (por ejemplo, la barra de grácos, diagramas de puntos, líneas…)? Estoy trabajando en un proyecto con varios gráficos en una página, se consigue sucio rápidamente. Algún consejo sobre esto? Gracias!
    • Hola @JdeMello, el enfoque más sencillo es la encapsulación de cada código en una función separada, que selecciona un contenedor en la página., como explico aquí: codereview.stackexchange.com/a/194948/143592
    • Excelente. Muchas gracias!
  3. 0

    Si las dos cartas tienen el mismo código, creo que la mayoría de d3-como manera de hacerlo sería

    var width = 960,
        height = 960,
        margin = 30;
    
    var svgs = d3.select('#area1')
        .selectAll('svg')
        .data([json1, json2])
        .enter()
        .append('svg')
        .attr('width', width)
        .attr('height', height)
    
    svgs.append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
        .each(function(d) {console.log(d)}) //will log json1, then json2

    Entonces tendrás json1 y json2 obligado a cada uno de los recién anexada svgs, y todo el código que sigue se hará a ambos.

    JS:

    var width = 200,
        height = 100,
        margin = 30;
    
    var svgs = d3.select('#area1')
        .selectAll('svg')
        .data([{text:'thing1'}, {text:'thing2'}])
        .enter()
        .append('svg')
        .attr('width', width)
        .attr('height', height);
    
    svgs.append("text")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
        .text(function(d) {return d.text});

    HTML:

    <script src="https://d3js.org/d3.v4.js"></script>
    <div id='area1'></div>

    • Hmm.. pastebin.com/4wiXDkyw es no mostrar nada 🙁
    • editado para añadir trabajando fragmento de código

Dejar respuesta

Please enter your comment!
Please enter your name here