tutorial examples ejemplos d3js javascript jquery json d3.js sunburst-diagram

javascript - examples - Actualice dinĂ¡micamente D3 Sunburst si el json de origen se actualiza(elemento agregado o eliminado)



d3js charts examples (3)

Soy nuevo en D3 e intento actualizar dinámicamente el gráfico si se modifica el json de origen. Pero no soy capaz de lograr esto.

Por favor revisa este plunkr

Js:

var width = 500, height = 500, radius = Math.min(width, height) / 2; var x = d3.scale.linear() .range([0, 2 * Math.PI]); var y = d3.scale.sqrt() .range([0, radius]); var color = d3.scale.category10(); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ") rotate(-90 0 0)"); var partition = d3.layout.partition() .value(function(d) { return d.size; }); var arc = d3.svg.arc() .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); }) .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); }) .innerRadius(function(d) { return Math.max(0, y(d.y)); }) .outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); }); //d3.json("/d/4063550/flare.json", function(error, root) { var root = initItems; var g = svg.selectAll("g") .data(partition.nodes(root)) .enter().append("g"); var path = g.append("path") .attr("d", arc) .style("fill", function(d) { return color((d.children ? d : d.parent).name); }) .on("click", click) .each(function(d) { this.x0 = d.x; this.dx0 = d.dx; }); //.append("text") var text = g.append("text") .attr("x", function(d) { return y(d.y); }) .attr("dx", "6") // margin .attr("dy", ".35em") // vertical-align .attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; }) .text(function(d) { return d.name; }) .style("fill", "white"); function computeTextRotation(d) { var angle = x(d.x + d.dx / 2) - Math.PI / 2; return angle / Math.PI * 180; } function click(d) { console.log(d) // fade out all text elements if (d.size !== undefined) { d.size += 100; }; text.transition().attr("opacity", 0); path.transition() .duration(750) .attrTween("d", arcTween(d)) .each("end", function(e, i) { // check if the animated element''s data e lies within the visible angle span given in d if (e.x >= d.x && e.x < (d.x + d.dx)) { // get a selection of the associated text element var arcText = d3.select(this.parentNode).select("text"); // fade in the text element and recalculate positions arcText.transition().duration(750) .attr("opacity", 1) .attr("transform", function() { return "rotate(" + computeTextRotation(e) + ")" }) .attr("x", function(d) { return y(d.y); }); } }); } //}); // Word wrap! var insertLinebreaks = function(t, d, width) { alert(0) var el = d3.select(t); var p = d3.select(t.parentNode); p.append("g") .attr("x", function(d) { return y(d.y); }) // .attr("dx", "6") // margin //.attr("dy", ".35em") // vertical-align .attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; }) //p .append("foreignObject") .attr(''x'', -width / 2) .attr("width", width) .attr("height", 200) .append("xhtml:p") .attr(''style'', ''word-wrap: break-word; text-align:center;'') .html(d.name); alert(1) el.remove(); alert(2) }; //g.selectAll("text") // .each(function(d,i){ insertLinebreaks(this, d, 50 ); }); d3.select(self.frameElement).style("height", height + "px"); // Interpolate the scales! function arcTween(d) { var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]), yd = d3.interpolate(y.domain(), [d.y, 1]), yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]); return function(d, i) { return i ? function(t) { return arc(d); } : function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); }; }; } function arcTweenUpdate(a) { console.log(path); var _self = this; var i = d3.interpolate({ x: this.x0, dx: this.dx0 }, a); return function(t) { var b = i(t); console.log(window); _self.x0 = b.x; _self.dx0 = b.dx; return arc(b); }; } setTimeout(function() { path.data(partition.nodes(newItems)) .transition() .duration(750) .attrTween("d", arcTweenUpdate) }, 2000);


En side the violín, setTimeout no se está ejecutando porque:

d3.select(self.frameElement).style("height", height + "px");

Obtendrá Unbeught SecurityError: Error al leer la propiedad ''frame'' desde ''Window'': Bloqueado un marco con origen " https://fiddle.jshell.net " de acceder a un marco con origen y el setTimeout nunca se llama.

Entonces puede eliminar esta línea d3.select(self.frameElement).style("height", height + "px"); solo por el violín.

Aparte de eso:

Su función de tiempo de espera debería verse así:

setTimeout(function() { //remove the old graph svg.selectAll("*").remove(); root = newItems; g = svg.selectAll("g") .data(partition.nodes(newItems)) .enter().append("g"); /make path path = g.append("path") .attr("d", arc) .style("fill", function(d) { return color((d.children ? d : d.parent).name); }) .on("click", click) .each(function(d) { this.x0 = d.x; this.dx0 = d.dx; }); //make text text = g.append("text") .attr("x", function(d) { return y(d.y); }) .attr("dx", "6") // margin .attr("dy", ".35em") // vertical-align .attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; }) .text(function(d) { return d.name; }) .style("fill", "white"); }

trabajando violín aquí


para el ingreso () y las transiciones al trabajo, necesita darle a d3 una forma de identificar cada elemento en sus datos. la función .data () tiene un segundo parámetro que le permite devolver algo para usar como un id. enter () usará la identificación para decidir si el objeto es nuevo.

intente cambiar

path.data(partition.nodes(newItems)) .data(partition.nodes(root));

a

path.data(partition.nodes(newItems), function(d){return d.name}); .data(partition.nodes(root), function(d){return d.name});


Además de lo que @Cyril sugirió para eliminar la siguiente línea:

d3.select(self.frameElement).style("height", height + "px");

Hice más modificaciones en tu violín: violín de trabajo

La idea utilizada aquí es agregar una función updateChart que toma los items y luego genera el gráfico:

var updateChart = function (items) { // code to update the chart with new items } updateChart(initItems); setTimeout(function () { updateChart(newItems); }, 2000);

Esto no utiliza la función arcTweenUpdate que ha creado, pero intentaré explicar el concepto subyacente:

Primero, deberá JOIN los datos nuevos con sus datos existentes:

// DATA JOIN - Join new data with old elements, if any. var gs = svg.selectAll("g").data(partition.nodes(root));

luego, ENTER para crear nuevos elementos si es necesario:

// ENTER var g = gs.enter().append("g").on("click", click);

Pero también necesitamos UPDATE los nodos de path y text existentes / nuevos con nuevos datos:

// UPDATE var path = g.append("path"); gs.select(''path'') .style("fill", function(d) { return color((d.children ? d : d.parent).name); }) //.on("click", click) .each(function(d) { this.x0 = d.x; this.dx0 = d.dx; }) .transition().duration(500) .attr("d", arc); var text = g.append("text"); gs.select(''text'') .attr("x", function(d) { return y(d.y); }) .attr("dx", "6") // margin .attr("dy", ".35em") // vertical-align .attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; }) .text(function(d) { return d.name; }) .style("fill", "white");

y, después de que todo se haya creado / actualizado, elimine los g nodos que no se están utilizando, es decir, EXIT :

// EXIT - Remove old elements as needed. gs.exit().transition().duration(500).style("fill-opacity", 1e-6).remove();

Este patrón completo de JOIN + ENTER + UPDATE + EXIT se demuestra en los siguientes artículos de Mike Bostock:

  1. Patrón de actualización general - I
  2. Patrón de actualización general - II
  3. Patrón de actualización general - III