javascript - Keep legend constant and only update chart in D3 -
my coding plot x axis location, y axis (value1,value2 or value3) , legend types(high, medium,low). i'm trying add menu value1,2,3 , add legend different types if change either menu or click on legend, plot got updated selected data. however, code below able create legend set default type or clicked not able include types. there way include types in legends no matter type clicked , update chart accordingly? thank you,
<script> var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 960- margin.left - margin.right, height = 900 - margin.top - margin.bottom, radius = 3.5, padding = 1, xvar = "location", cvar= " type"; default = "high"; // add tooltip area webpage var tooltip = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", 0); // force data update when menu changed var menu = d3.select("#menu select") .on("change", change); // load data d3.csv("sample.csv", function(error, data) { formatted = data; draw(); }); // set terms of transition take place // when new indicator menu or legend chosen function change() { //remove old plot , data var svg = d3.select("svg"); svg.transition().duration(100).remove(); //redraw new plot new data d3.transition() .duration(750) .each(draw) } function draw() { // add graph canvas body of webpage var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") // setup x var xvalue = function(d) { return d[xvar];}, // data -> value xscale = d3.scale.ordinal() .rangeroundbands([0,width],1), //value -> display xmap = function(d) { return (xscale(xvalue(d)) + math.random()*10);}, // data -> display xaxis = d3.svg.axis().scale(xscale).orient("bottom"); // setup y var yvar = menu.property("value"), yvalue = function(d) { return d[yvar];}, // data -> value yscale = d3.scale.linear().range([height, 0]), // value -> display ymap = function(d) { return yscale(yvalue(d));}, // data -> display yaxis = d3.svg.axis().scale(yscale).orient("left"); // setup fill color var cvalue = function(d) { return d[cvar];}, color = d3.scale.category10(); // filter unwanted data , plot chosen dataset. data = formatted.filter(function(d, i) { if (d[cvar] == default) { return d; } }); data = formatted; // change string (from csv) number format data.foreach(function(d) { d[xvar] = d[xvar]; d[yvar] = +d[yvar]; }); xscale.domain(data.sort(function(a, b) { return d3.ascending(a[xvar], b[xvar])}) .map(xvalue) ); // don't want dots overlapping axis, add in buffer data domain yscale.domain([d3.min(data, yvalue)-1, d3.max(data, yvalue)+1]); // x-axis svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xaxis) .append("text") .attr("class", "label") .attr("x", width) .attr("y", -6) .style("text-anchor", "end") .text(xvar); // y-axis svg.append("g") .attr("class", "y axis") .call(yaxis) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text(yvar); // draw dots var dot = svg.selectall(".dot") .data(data) .enter() .append("circle") .attr("class", "dot") .attr("r", radius) .attr("cx", xmap) .attr("cy", ymap) .style("fill", function(d) { return color(cvalue(d));}) .on("mouseover", function(d) { tooltip.transition() .duration(200) .style("opacity", .9); tooltip.html(d[sn] + "<br/> (" + xvalue(d) + ", " + yvalue(d) + ")") .style("left", (d3.event.pagex + 5) + "px") .style("top", (d3.event.pagey - 28) + "px"); }) .on("mouseout", function(d) { tooltip.transition() .duration(500) .style("opacity", 0); }); // draw legend var legend = svg.selectall(".legend") .data(color.domain().slice()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + * 20 + ")"; }); // draw legend colored rectangles legend.append("rect") .attr("x", width - 18) .attr("width", 18) .attr("height", 18) .style("fill", color) .on("click", function (d){ default = d; return change(); }); // draw legend text legend.append("text") .attr("x", width - 24) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .text(function(d) { return d;}) .on("click", function (d) { default = d; return change(); }); }; </script> </body>
sample.csv
location type value1 value2 value3 high 1 -2 -5 b medium 2 3 4 c low 4 1 2 c medium 6 3 4 high 4 5 6 d low -1 3 2
i found way include types in legend. first, extract unique types column "type" , save them in "legend_keys" array. second, instead of pre-define "default", set first type in "legend_keys" default. next default set event on click out of legend.
d3.csv("sample.csv", function(error, data) { formatted = data; var nest = d3.nest() .key(function(d) { return d[cvar]; }) .entries(formatted); console.log(nest); legend_keys = nest.map(function(o){return o.key}); default = legend_keys[0]; //console.log(legend_keys[0]); draw(); });
finally, when define legend, read "legend_keys" data below. doing this, can keep types in legend.
var legend = svg.selectall(".legend") .data(legend_keys) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + * 20 + ")"; }) .on("click", function (d){ default = d; console.log(default); return change(); });
Comments
Post a Comment