Pagination of legends - javascript

actually I am working on D3js charts . I have implemented pagination in legends but in the end there are two legends which are repeating.
how should i fix this??
I have provided the fiddle for my current code here. jsfiddle link
Thanks in advance for any help
var data=[
{
"age":"<5",
"population":2704659
},
{
"age":"5-10",
"population":4499890
},
{
"age":"10-13",
"population":6736433
},
{
"age":"14-16",
"population":2159981
},
{
"age":"16-18",
"population":3853788
},
{
"age":"18-22",
"population":8848383
},
{
"age":"22-30",
"population":8384390
},
{
"age":"30-44",
"population":14106543
},
{
"age":"45-64",
"population":8819342
},
{
"age":"≥65",
"population":800000
}
]
var width = 1060,
height = 600,
radius = 175,
color = d3.scale.category10(),
legendNo=4, // number of legends to display at a time
legendCount=0; //To store number of legends
//creating svg element and appending to body
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); //transform it to center of body
//creating start and end angle for each arc
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.population; });
//creating the arcs based on pie layout
var arc = d3.svg.arc() //inner arc with color
.outerRadius(radius)
.innerRadius(radius-70);
//calculate the total to display in hole
var total=0;
data.forEach(function(d) {
d.population;
total +=parseInt(d.population);
legendCount++;
});
//creating svg element for center text
var center_group = svg.append("svg:g")
.attr("class", "center_group")
.attr("transform", "translate(" + (width/2) + "," + (height/2) + ")");
//selecting all inner arcs and appending data
var g = svg.selectAll("arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc")
//giving colour to each inner arc and execute onClick function
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.age); })
//display text in the inner arcs
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.style("font-size", "14px")
.text(function(d) { return d.data.age; });
count = 0;
var p=0;
var viewdata = data.slice(p,p+legendNo);
var hidedata;
var temp;
//selecting all legend elements
var legend = svg.selectAll(".legend")
.data(viewdata).enter()
.append("g").attr("class", "legend")
//.attr("width", )
.attr("id", function() {
return count++;
})
.attr("transform", function(d, i) {
return "translate("+(-(width/2-30)+ i * 50)+"," + (height/2-50)+ ")";
})
//appending coloured rectangles to legend
svg.selectAll("rect")
.data(viewdata)
.enter().append("rect")
.attr("x", width/2-150)
.attr("y",5)
.attr("dy", "3.00em")
.attr("dx", "1.75em")
.attr("width", 23).attr("height", 23)
.attr("transform", function(d, i) {
return "translate("+(-(width/2-30)+ i * 50)+"," + (height/2-50)+ ")";
})
.style("fill", function(d) {
return color(d.age);
});
var prev=svg.append("svg:text")
.attr("id","prev")
.attr("x", width-1260)
.attr("y",height-385)
.attr("dy", "2.90em")
.attr("dx", "1.75em")
//.attr("stroke", "black")
//.style("fill","white")
// .style("text-anchor", "middle")
.style("font-size", "20px")
//.attr("width", 45).attr("height", 25)
.text("<|")
.on("click",onPrevClick)
var next=svg.append("svg:text")
.attr("id","next")
.attr("x", width-950)
.attr("y",height-385)
.attr("dy", "2.90em")
.attr("dx", "1.75em")
.style("font-size", "20px")
//.attr("stroke", "black")
//.style("fill","white")
//.attr("width", 45).attr("height", 25)
.text("|>")
.on("click",onNextClick)
function onNextClick()
{p+=legendNo;
if(p>=legendCount){
p-=legendNo;
viewdata = data.slice(p,legendCount);
//temp=legendNo-(legendCount-p);
//hidedata =data.slice(p-temp-2,p-2);
}
else{
viewdata = data.slice(p,p+legendNo);
//hidedata =data.slice(0,0);
}
svg.selectAll("rect")
.data(viewdata)
.attr("x", width/2-150)
.attr("y",5)
.attr("dy", "3.00em")
.attr("dx", "1.75em")
.attr("width", 23).attr("height", 23)
.attr("transform", function(d, i) {
return "translate("+(-(width/2-30)+ i * 50)+"," + (height/2-50)+ ")";
})
.style("fill", function(d) {
return color(d.age);
});
legend.select("text").attr("x", width/2-150)
.data(viewdata)
.attr("y", 15)
.attr("dy", "3.00em")
.attr("dx", "1.75em")
//.attr("transform", function(d, i) {return "rotate("+45*i+","+d.age+",200)";})
.attr("text-anchor", "middle").text(function(d) {
return d.age;
});
}
function onPrevClick(){
p-=legendNo;
if(p<=0){
p=0;
}
viewdata = data.slice(p,p+legendNo);
svg.selectAll("rect")
.data(viewdata)
.attr("x", width/2-150)
.attr("y",5)
.attr("dy", "3.00em")
.attr("dx", "1.75em")
.attr("width", 23).attr("height", 23)
.attr("transform", function(d, i) {
return "translate("+(-(width/2-30)+ i * 50)+"," + (height/2-50)+ ")";
})
.style("fill", function(d) {
return color(d.age);
});
legend.select("text").attr("x", width/2-150)
.data(viewdata)
.attr("y", 15)
.attr("dy", "3.00em")
.attr("dx", "1.75em")
//.attr("transform", function(d, i) {return "rotate("+45*i+","+d.age+",200)";})
.attr("text-anchor", "middle").text(function(d) {
return d.age;
});
}
// giving text to legends
legend.append("text").attr("x", width/2-150)
.data(viewdata)
.attr("y", 15)
.attr("dy", "3.00em")
.attr("dx", "1.75em")
//.attr("transform", function(d, i) {return "rotate("+45*i+","+d.age+",200)";})
.attr("text-anchor", "middle").text(function(d) {
return d.age;
});
//displaying legend title
var legendTitle = svg.append("svg:text")
.attr("x", -(width/2-200))
.attr("y", height/2-25)
.style("font-size", "14px")
.style("text-decoration", "underline")
.text("Age Group");

Working demo: http://jsfiddle.net/m6cx7/6/
You need to handle enter and exit of the legends on each Next and Prev click:
var rects = svg.selectAll("rect")
.data(viewdata);
rects.enter()
.append('rect');
rects.exit()
.remove();
rects
.attr("x", width/2-150)
.attr("y",5)
// ...
var legends = svg.selectAll(".legend")
.data(viewdata);
legends.enter()
.append('g')
.classed('legend', true)
.attr("id", function() {
return count++;
})
.attr("transform", function(d, i) {
return "translate("+(-(width/2-30)+ i * 50)+"," + (height/2-50)+ ")";
})
.append('text');
legends.exit()
.remove();
legends
.select('text')
.attr('x', width/2-150)
// ...

Related

Color Specific Links on D3 Sankey Chart

we are needing help coloring the specific links of this sankey chart. We want the links that connect with "Raleigh" to be green, all the others staying grey.
Here is a picture of what it looks like, followed by a picture of what where the green links will go:
We are new to d3 and just can't figure it out, any help would be great!!
var svg = d3.select("svg").attr("style", "outline: thin solid grey;"),
width = +svg.attr("width"),
height = +svg.attr("height");
var formatNumber = d3.format(",.0f"),
format = function(d) { return formatNumber(d) + " TWh"; },
color = d3.scaleOrdinal(d3.schemeCategory10);
var school = {"nodes": [
{"name":"Happiness Index"}, // 0
{"name":"Business Cost Index"}, // 1
{"name":"Home Price to Income"}, // 2
{"name":"Population Growth"}, // 3
{"name":"3 Year GDP Growth"}, // 4
{"name":"Percent with Degree"}, // 5
{"name":"Austin"}, // 6
{"name":"Nashville"}, // 7
{"name":"Atlanta"}, // 8
{"name":"Raleigh"}, // 9
{"name":"Washington DC"}, // 10
],
"links":[
// From Happiness
{"source":0,"target":6,"value":97},
{"source":0,"target":9,"value":100},
{"source":0,"target":10,"value":96},
// From Business Cost
{"source":1,"target":9,"value":87},
{"source":1,"target":8,"value":88},
{"source":1,"target":7,"value":99},
// From PTI
{"source":2,"target":8,"value":86},
// From Pop Growth
{"source":3,"target":9,"value":87},
{"source":3,"target":6,"value":94},
// From 3yrgdp
{"source":4,"target":9,"value":100},
{"source":4,"target":6,"value":88},
{"source":4,"target":7,"value":96},
// From percent undergrad
{"source":5,"target":9,"value":85},
{"source":5,"target":10,"value":100},
]};
var sankey = d3.sankey()
.nodeWidth(15)
.nodePadding(10)
.extent([[1, 1], [width - 1, height - 6]]);
var link = svg.append("g")
.attr("class", "links")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.2)
.selectAll("path");
var node = svg.append("g")
.attr("class", "nodes")
.attr("font-family", "sans-serif")
.attr("font-size", 15)
.selectAll("g");
sankey(school);
link = link
.data(school.links)
.enter().append("path")
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke-width", function(d) { return Math.max(1, d.width); })
// link hover values
link.append("title")
.text(function(d) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); });
node = node
.data(school.nodes)
.enter().append("g");
node.append("rect")
.attr("x", function(d) { return d.x0; })
.attr("y", function(d) { return d.y0; })
.attr("height", function(d) { return d.y1 - d.y0; })
.attr("width", function(d) { return d.x1 - d.x0; })
.attr("fill", function(d) { return color(d.name.replace(/ .*/, "")); })
.attr("stroke", "#000");
node.append("text")
.attr("x", function(d) { return d.x0 - 6; })
.attr("y", function(d) { return (d.y1 + d.y0) / 2; })
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.text(function(d) { return d.name; })
.filter(function(d) { return d.x0 < width / 2; })
.attr("x", function(d) { return d.x1 + 6; })
.attr("text-anchor", "start");
svg.append("text")
.attr("x", 10)
.attr("y", 30)
.attr("class", "graphTitle")
.text(" ");
svg.append("text")
.attr("x", width - 80)
.attr("y", height - 10)
Modify the links to:
link = link
.data(school.links)
.enter().append("path")
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke-width", function(d) { return Math.max(1, d.width); })
.style("stroke", function(d){
return d.target.name == "Raleigh" ? "green" : "gray";
});
Running code:
<!DOCTYPE html>
<html>
<head>
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://unpkg.com/d3-sankey#0.7.1/build/d3-sankey.js"></script>
</head>
<body>
<svg width="500" height="500"></svg>
<script>
var svg = d3.select("svg").attr("style", "outline: thin solid grey;"),
width = +svg.attr("width"),
height = +svg.attr("height");
var formatNumber = d3.format(",.0f"),
format = function(d) { return formatNumber(d) + " TWh"; },
color = d3.scaleOrdinal(d3.schemeCategory10);
var school = {"nodes": [
{"name":"Happiness Index"}, // 0
{"name":"Business Cost Index"}, // 1
{"name":"Home Price to Income"}, // 2
{"name":"Population Growth"}, // 3
{"name":"3 Year GDP Growth"}, // 4
{"name":"Percent with Degree"}, // 5
{"name":"Austin"}, // 6
{"name":"Nashville"}, // 7
{"name":"Atlanta"}, // 8
{"name":"Raleigh"}, // 9
{"name":"Washington DC"}, // 10
],
"links":[
// From Happiness
{"source":0,"target":6,"value":97},
{"source":0,"target":9,"value":100},
{"source":0,"target":10,"value":96},
// From Business Cost
{"source":1,"target":9,"value":87},
{"source":1,"target":8,"value":88},
{"source":1,"target":7,"value":99},
// From PTI
{"source":2,"target":8,"value":86},
// From Pop Growth
{"source":3,"target":9,"value":87},
{"source":3,"target":6,"value":94},
// From 3yrgdp
{"source":4,"target":9,"value":100},
{"source":4,"target":6,"value":88},
{"source":4,"target":7,"value":96},
// From percent undergrad
{"source":5,"target":9,"value":85},
{"source":5,"target":10,"value":100},
]};
var sankey = d3.sankey()
.nodeWidth(15)
.nodePadding(10)
.extent([[1, 1], [width - 1, height - 6]]);
var link = svg.append("g")
.attr("class", "links")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.2)
.selectAll("path");
var node = svg.append("g")
.attr("class", "nodes")
.attr("font-family", "sans-serif")
.attr("font-size", 15)
.selectAll("g");
sankey(school);
link = link
.data(school.links)
.enter().append("path")
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke-width", function(d) { return Math.max(1, d.width); })
.style("stroke", function(d){
return d.target.name == "Raleigh" ? "green" : "gray";
})
// link hover values
link.append("title")
.text(function(d) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); });
node = node
.data(school.nodes)
.enter().append("g");
node.append("rect")
.attr("x", function(d) { return d.x0; })
.attr("y", function(d) { return d.y0; })
.attr("height", function(d) { return d.y1 - d.y0; })
.attr("width", function(d) { return d.x1 - d.x0; })
.attr("fill", function(d) { return color(d.name.replace(/ .*/, "")); })
.attr("stroke", "#000");
node.append("text")
.attr("x", function(d) { return d.x0 - 6; })
.attr("y", function(d) { return (d.y1 + d.y0) / 2; })
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.text(function(d) { return d.name; })
.filter(function(d) { return d.x0 < width / 2; })
.attr("x", function(d) { return d.x1 + 6; })
.attr("text-anchor", "start");
svg.append("text")
.attr("x", 10)
.attr("y", 30)
.attr("class", "graphTitle")
.text(" ");
svg.append("text")
.attr("x", width - 80)
.attr("y", height - 10)
</script>
</body>
</html>

Filter out certain values from stacked bar chart in d3js

I have created a stacked bar chart which works fine but I wanted to filter out the bars which are of very small length so that the chart looks good. Here is my code:-
<!DOCTYPE html>
<style>
.axis .domain {
}
</style>
<svg width="3000" height="700"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 200, left: 60},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleBand()
.rangeRound([0, 700])
.paddingInner(0.55)
.align(0.5);
var y = d3.scaleLinear()
.rangeRound([height,0]);
var z = d3.scaleOrdinal()
.range(["pink","purple"]);
//.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
d3.csv("pivot2.csv", function(d, i, columns) {
for (i = 1, t = 0; i < columns.length; ++i)
t += d[columns[i]] = +d[columns[i]];
d.total = t;
return d;
}, function(error, data) {
if (error) throw error;
var keys = data.columns.slice(1);
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { if(d.total>2000){return d.Name;} }));
y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
z.domain(keys);
g.append("g")
.selectAll("g")
.data(d3.stack().keys(keys)(data))
.enter().append("g")
.attr("fill", function(d) {return z(d.key); })
.selectAll("rect")
.data(function(d) { return d;})
.enter().append("rect")
.attr("x", function(d) { return x(d.data.Name); })
.attr("y", function(d) { return y(d[1]) ; })
.attr("height",0)
.transition()
.duration(50)
.delay(function (d, i) { return i*100; })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
.attr("width",20)
//.attr("width", x.bandwidth())
g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(1))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");
//.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks().pop()) + 0.2)
.attr("dy", "0.32em")
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "start")
//.text("Duration");
var legend = g.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g")
.data(keys.slice().reverse())
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x",1500)
//.attr("x", width - 20)
.attr("width", 19)
.attr("height",0)
.transition()
.duration(200)
.delay(function (d, i) { return i*50; })
.attr("height", 19)
.attr("fill", z);
legend.append("text")
.attr("x",1490)
.attr("font-size","20px")
//.attr("x", width - 30)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text(function(d) { return d; });
});
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," +
(height + margin.top + 200) + ")")
.style("text-anchor", "middle")
.style("font-size","28px")
.style("fill","green")
.text("Customer Name");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y",-5)
.attr("x",-200)
//.attr("y", 0 - margin.left)
//.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.style("fill","green")
.style("font-size","28px")
.text("Machine Duration By Mode");
</script>
As you can see I have applied an "IF" condition
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { if(d.total>2000){return d.Name;} }));
y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
z.domain(keys);
But the problem is that all the remaining rectangles are being appended in the bottom left corner above the "Locust Valley Central School District" as you can see in the screenshot I have provided. Please help me to remove these extra rectangles.Screenshot for extra rectangles in the stacked bar chart
Map function here:
data.map(function(d) { if(d.total>2000){return d.Name;} })
Doesn't actually change data array, it returns a new array instead, which is used to initialize x.domain only.
Then you use unchanged data to create rectangles:
g.append("g")
.selectAll("g")
.data(d3.stack().keys(keys)(data))
.enter().append("g")
.attr("fill", function(d) {return z(d.key); })
.selectAll("rect")
.data(function(d) { return d;})
.enter().append("rect")
And it creates redundant rectangles with empty x coordinate. To fix this, you need to filter your data first:
data = data.filter(function(d) {
if (d.total > 2000) {
return true
}
})
And then use it to set x.domain (without any conditions here):
x.domain(data.map(function(d) { return d.Name }))
The rest of the code remains the same.

Dynamically create scrollable SVG

I am trying to create a scrollable list. I have looked at other tutorials on here but it does not seem to be working. Essentially I am appending an SVG to a div. Inside this SVG is a D3JS stacked Bar Graph. to the right of this bar graph I am appending a 'g' element with an svg inside. I have set a height for this right SVG. Inside this I have populated a list that would extend beyond the height of the SVG. I have set the CSS for this svg to 'overflow-y: scroll'.
In spite of all of this I can not get this svg to scroll. Instead it just grows to the size of the list and extends past to intended bounds. Please See code below.
var barSVG = d3.select("#documents_reviewed_bar_chart").append("svg")
.classed('barChart-docs-reviewed', true)
.attr('id', 'barSVG')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr('id', 'gElement')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var count = 0;
var graph = barSVG.append('g')
.attr('id', 'graphElement')
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Date"; }));
data.forEach(function(d) {
var myDate = d.Date; //add to stock code
var y0 = 0;
d.people = color.domain().map(function(name) { return {myDate:myDate, name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.people[d.people.length - 1].y1;
count = isNaN(d.total) ? count : count + d.total
});
x.domain(data.map(function(d) { return d.Date; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
graph.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)" )
.style("cursor", "pointer")
.on('click', renderHorizontalChart);
graph.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end");
//.text("Population");
graph.append('text')
.text('Total: ' + count)
.attr('x', 20)
.attr('y', -10)
var state = graph.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + "0" + ",0)"; });
//.attr("transform", function(d) { return "translate(" + x(d.Date) + ",0)"; })
state.selectAll("rect")
.data(function(d) {
return d.people;
})
.enter().append("rect")
.attr("width", x.rangeBand())
.attr("y", height)
.attr("x",function(d) { //add to stock code
return x(d.myDate)
})
.attr("height", 0 )
.style("fill", function(d) { return color(d.name); })
.transition()
.duration(1000)
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.attr("class", function(d) {
classLabel = d.name.replace(/,\s/g, ''); //remove spaces
return "class" + classLabel;
});
state.selectAll("rect")
.on("mouseover", function(d){
var delta = d.y1 - d.y0;
var xPos = parseFloat(d3.select(this).attr("x"));
var yPos = parseFloat(d3.select(this).attr("y"));
var height = parseFloat(d3.select(this).attr("height"))
d3.select(this).attr("stroke","black").attr("stroke-width",2);
tooltip.style("visibility", "visible");
tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");
tooltip.style('background', 'black')
tooltip.style('color', 'white')
tooltip.style('border-radius', '3px')
tooltip.style('padding', '5px')
tooltip.style('opacity', '0.8')
tooltip.style('font-size', '10px;')
tooltip.text(d.name +": "+ delta)
})
.on("mouseout",function(){
tooltip.style("visibility", "hidden");
graph.select(".tooltip").remove();
d3.select(this).attr("stroke","pink").attr("stroke-width",0.2);
})
var itemsAmount = 0
var rightSVG = barSVG.append('svg').classed('rightSVG', true)
.attr('height', '390')
.attr('id', 'rightSVG')
var legendSVG = rightSVG.append('svg').classed('legendSVG', true)
.attr('id', 'legendSVG')
var legend = legendSVG.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
//.attr("class", "legend")
.attr("class", function (d) {
itemsAmount = itemsAmount + 1
legendClassArray.push(d.replace(/,\s/g, '')); //remove spaces
return "legend";
})
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
//reverse order to match order in which bars are stacked
legendClassArray = legendClassArray.reverse();
legend.append("rect")
.attr("x", width - 0)
.attr("width", 18)
.attr("height", 18)
.style("fill", color)
.attr("id", function (d, i) {
return "id#" + d.replace(/,\s/g, '');
})
.on("mouseover",function(){
if (active_link === "0") d3.select(this).style("cursor", "pointer");
else {
if (active_link.split("class").pop() === this.id.split("id#").pop()) {
d3.select(this).style("cursor", "pointer");
} else d3.select(this).style("cursor", "auto");
}
})
.on("click",function(d){
if (!this.id.includes('active')) { //nothing selected, turn on this selection
d3.select(this)
.attr('id', function(){
return this.id + 'active'
})
.style("stroke", "black")
.style("stroke-width", 2);
active_link = this.id.split("id#").pop();
plotSingle(this);
} else { //deactivate
d3.select(this)
.classed("active", false)
.attr('id', function() {
return this.id.replace('active', '')
})
.style("stroke", "none")
.style("stroke-width", 0);
plotSingle(this);
}
});
legend.append("text")
.attr("x", width - 6)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
legendSVG.append("text")
.classed('queryButton', true)
.attr("x", width - 6)
.attr("y", height)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text('Run Query')
.on('click', function(){
if (newArr.length > 0) {
d3.select('#barSVG').remove();
runScript(newArr)
}
});
legendSVG.append("text")
.classed('queryButton', true)
.attr("x", width - 6)
.attr("y", height + 18)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text('Reset')
The Specific SVG that I want to be scrollable is the 'rightSVG'.
As you can see in the image, the names are cut off. There should be a scrollable legend where I am able to see 29 data items.
Also, I have added the below CSS:
#documents_reviewed_bar_chart, #gElement{
max-height: 390;
overflow-y: scroll;
}
Short answer: you can't have a scrollable SVG inside another SVG. The overflow-y: scroll applies to HTML elements, not to SVG elements.
Alternative (and hacky) answer: technically, what you want is possible, but you'll have to wrap your inner SVG in an HTML element, which has to be inside a foreignObject.
This alternative is suboptimal, makes little sense and doesn't work on IE. However, just for the sake of curiosity, this is how you can do it:
var outerSvg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 200)
.style("background-color", "darkkhaki");
var foreign = outerSvg.append("foreignObject")
.attr("x", 300)
.attr("y", 10)
.attr("width", 150)
.attr("height", 180)
.append("xhtml:div")
.style("max-height", "180px")
.style("overflow-y", "scroll");
var innerSvg = foreign.append("svg")
.attr("width", 133)
.attr("height", 1000)
.style("background-color", "powderblue");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var texts = innerSvg.selectAll("foo")
.data(d3.range(65))
.enter()
.append("text")
.attr("x", 40)
.attr("y", (d,i)=> 20 + 15*i)
.text("foo bar baz")
var rects = innerSvg.selectAll("foo")
.data(d3.range(65))
.enter()
.append("rect")
.attr("x", 10)
.attr("y", (d,i)=> 8 + 15*i)
.attr("width", 20)
.attr("height", 13)
.attr("fill", (d,i)=>color(i));
<script src="https://d3js.org/d3.v4.min.js"></script>
The outer SVG is light brown (or khaki). The inner SVG, at the right, is blue, and it's inside a <div> with overflow-y: scroll;.

Total height of Stacked Bar on tip of every rectangle in stacked Bar Chart using d3

I drawn a stackedbar Chart in which now I trying to place the Total value(I mean the yaxis value) on tip of the every rectangle. I have coded to fetch the details but here the problem is I am getting Every Layer value on tip of every layer but i need to show only the last layer value.
the problem is shown in below fig's.
My code is Shown below
var fData =
[{"orders":"A","Total_Orders":76,"A_Lines":123,"B_Lines":0,"C_Lines":0,"D_Lines":0,"Total_Lines":123,"Total_Units":3267},
{"orders":"B","Total_Orders":68,"A_Lines":0,"B_Lines":107,"C_Lines":0,"D_Lines":0,"Total_Lines":107,"Total_Units":3115},
{"orders":"C","Total_Orders":81,"A_Lines":0,"B_Lines":0,"C_Lines":123,"D_Lines":0,"Total_Lines":123,"Total_Units":3690},
{"orders":"D","Total_Orders":113,"A_Lines":0,"B_Lines":0,"C_Lines":0,"D_Lines":203,"Total_Lines":203,"Total_Units":7863},
{"orders":"AB","Total_Orders":62,"A_Lines":70,"B_Lines":76,"C_Lines":0,"D_Lines":0,"Total_Lines":146,"Total_Units":1739},
{"orders":"AC","Total_Orders":64,"A_Lines":77,"B_Lines":0,"C_Lines":79,"D_Lines":0,"Total_Lines":156,"Total_Units":2027},
{"orders":"AD","Total_Orders":100,"A_Lines":127,"B_Lines":0,"C_Lines":0,"D_Lines":144,"Total_Lines":271,"Total_Units":6467},
{"orders":"BC","Total_Orders":64,"A_Lines":0,"B_Lines":80,"C_Lines":84,"D_Lines":0,"Total_Lines":164,"Total_Units":1845},
{"orders":"BD","Total_Orders":91,"A_Lines":0,"B_Lines":108,"C_Lines":0,"D_Lines":135,"Total_Lines":243,"Total_Units":4061},
{"orders":"CD","Total_Orders":111,"A_Lines":0,"B_Lines":0,"C_Lines":132,"D_Lines":147,"Total_Lines":279,"Total_Units":5011},
{"orders":"ABC","Total_Orders":45,"A_Lines":58,"B_Lines":63,"C_Lines":55,"D_Lines":0,"Total_Lines":176,"Total_Units":1245},
{"orders":"ABD","Total_Orders":69,"A_Lines":105,"B_Lines":87,"C_Lines":0,"D_Lines":116,"Total_Lines":308,"Total_Units":4538},
{"orders":"ACD","Total_Orders":66,"A_Lines":91,"B_Lines":0,"C_Lines":88,"D_Lines":132,"Total_Lines":311,"Total_Units":4446},{
{"orders":"BCD","Total_Orders":68,"A_Lines":0,"B_Lines":84,"C_Lines":95,"D_Lines":111,"Total_Lines":290,"Total_Units":4187},
{"orders":"ABCD","Total_Orders":56,"A_Lines":96,"B_Lines":90,"C_Lines":93,"D_Lines":143,"Total_Lines":422,"Total_Units":6331}]
var headers = ["A_Lines", "B_Lines", "C_Lines", "D_Lines"];
var colors = ["#9999CC", "#F7A35C", "#99CC99", "#CCCC99"];
var colorScale = d3.scale.ordinal()
.domain(headers)
.range(colors);
var layers = d3.layout.stack()(headers.map(function (count) {
return fData.map(function (d, i) {
// alert(d);
return { x: d.ORDER_TYPE, y: +d[count], color: colorScale(count) };
});
}));
//StackedBar Rectangle Max
var yStackMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y0 + d.y; }); });
// Set x, y and colors
var xScale = d3.scale.ordinal()
.domain(layers[0].map(function (d) { return d.x; }))
.rangeRoundBands([25, width], .08);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
// var color = d3.scale.ordinal()
//.domain(headers)
// .range(["#9999CC", "#F7A35C", "#99CC99", "#CCCC99"]);
// Define and draw axes
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(1)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function (d, i) { return colorScale(i); });
var rect = layer.selectAll("rect")
.data(function (d) { return d; })
.enter().append("rect")
.attr("x", function (d) { return xScale(d.x); })
.attr("y", height)
.attr("width", xScale.rangeBand())
.attr("height", 0)
.attr("class", function (d) {
return "rect bordered " + "color-" + d.color.substring(1);
});
layer.selectAll("text.rect")
.data(function (layer) { return layer; })
.enter().append("text")
.attr("text-anchor", "middle")
.attr("x", function (d) { return xScale(d.x) + xScale.rangeBand() / 2; })
.attr("y", function (d) { return y(d.y + d.y0) - 3; })
.text(function (d) { return d.y + d.y0; })
.style("fill", "4682b4");
//********** AXES ************
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text").style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-45)"
});
svg.attr("class", "x axis")
.append("text")
.attr("text-anchor", "end") // this makes it easy to centre the text as the transform is applied to the anchor
.attr("transform", "translate(" + (width / 2) + "," + (height + 60) + ")") // centre below axis
.text("Order Velocity Group");
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(20,0)")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr({ "x": -75, "y": -70 })
.attr("dy", ".75em")
.style("text-anchor", "end")
.text("No. Of Lines");
//********** LEGEND ************
var legend = svg.selectAll(".legend")
.data(headers.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) { return "translate(" + i * (-100) + "," + (height + 50) + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
//.style("fill", color);
.style("fill", function (d, i) { return colors[i]; })
.on("mouseover", function (d, i) {
svg.selectAll("rect.color-" + colors[i].substring(1)).style("stroke", "blue");
})
.on("mouseout", function (d, i) {
svg.selectAll("rect.color-" + colors[i].substring(1)).style("stroke", "white");
});
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function (d) { return d; });
transitionStacked();
function transitionStacked() {
y.domain([0, yStackMax]);
rect.transition()
.duration(500)
.delay(function (d, i) { return i * 10; })
.attr("y", function (d) { return y(d.y0 + d.y); })
.attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); })
.transition()
.attr("x", function (d) { return xScale(d.x); })
.attr("width", xScale.rangeBand());
rect.on('mouseover', tip.show)
.on('mouseout', tip.hide)
};
can anyone help me.
Here is what you need: First, we'll set fData as the data for the texts:
layer.selectAll("text.rect")
.data(fData)
.enter()
.append("text")
But, as this dataset doesn't have the correct yScale value, we'll have to extract it using a filter:
.attr("y", function (d) {
var filtered = fData.filter(function(e){
return e.Total_Units == d.Total_Units
});
return y(filtered[0].Total_Lines) - 3;
})
All together:
layer.selectAll("text.rect")
.data(fData)
.enter().append("text")
.attr("text-anchor", "middle")
.attr("x", function(d) {
return xScale(d.orders) + xScale.rangeBand() / 2;
})
.attr("y", function(d) {
var filtered = fData.filter(function(e) {
return e.Total_Units == d.Total_Units
});
return y(filtered[0].Total_Lines) - 3;
})
.text(function(d) {
return d.Total_Units
})
.style("fill", "4682b4");
Here is your fiddle: https://jsfiddle.net/wnwb6meh/

Data not being redrawn after being filtered on d3 bar chart

I've been trying to add a filter to a bar chart. The bar is removed when I click on the legend, but when I try to reactivate the bar is not being redrawn.
Here is a plnk;
http://plnkr.co/edit/GZtErHGdq8GbM2ZawQSD?p=preview
I can't seem to work out the issue - if anyone could lend a hand?
Thanks
JS code;
// load the data
d3.json("data.json", function(error, data) {
var group = [];
function updateData() {
group = [];
var organization = data.organizations.indexOf("Org1");
var dateS = $("#selectMonth").text()
for (var country = 0; country < data.countries.length; country++) {
var date = data.dates.indexOf(dateS);
group.push({
question: data.organizations[organization],
label: data.countries[country],
value: data.values[organization][country][date]
});
}
}
function draw(create) {
updateData();
x.domain(group.map(function(d) {
return d.label;
}));
y.domain([0, 100]);
// add axis
// Add bar chart
var bar = svg.selectAll("rect")
.data(group);
if (create) {
bar
.enter().append("rect")
.attr('x', function(d) {
return x(d.label);
})
.attr('y', function(d) {
return y(d.value);
})
.attr('width', x.rangeBand())
.attr('height', function(d) {
return height - y(d.value);
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Value");
}
bar
.transition()
.duration(750)
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
});
// Existing code to draw y-axis:
var legendGroups = d3.select("#legend")
.selectAll(".legendGroup")
.data(group, function(d) {
return d.label; // always try and use a key function to uniquely identify
});
var enterGroups = legendGroups
.enter()
.append("g")
.attr("class", "legendGroup");
legendGroups
.exit()
.remove();
legendGroups
.attr("transform", function(d, i) {
return "translate(10," + (10 + i * 15) + ")"; // position the whole group
});
enterGroups.append("text")
.text(function(d) {
return d.label;
})
.attr("x", 15)
.attr("y", 10);
enterGroups
.append("rect")
.attr("width", 10)
.attr("height", 10)
.attr("fill", function(d) {
return "#bfe9bc";
})
.attr("class", function(d, i) {
return "legendcheckbox " + d.label.replace(/\s|\(|\)|\'|\,|\.+/g, '')
})
.on("click", function(d) {
d.active = !d.active;
d3.select(this).attr("fill", function(d) {
if (d3.select(this).attr("fill") == "#cccccc") {
return "#bfe9bc";
} else {
return "#cccccc";
}
})
var result = group.filter(function(d) {
return $("." + d.label.replace(/\s|\(|\)|\'|\,+/g, '')).attr("fill") != "#cccccc"
})
x.domain(result.map(function(d) {
return d.label;
}));
bar
.select(".x.axis")
.transition()
.call(xAxis);
bar
.data(result, function(d) {
return d.label.replace(/\s|\(|\)|\'|\,|\.+/g, '')
})
.enter()
.append("rect")
.attr("class", "bar")
bar
.transition()
.attr("x", function(d) {
return x(d.label);
})
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
});
bar
.data(result, function(d) {
return d.label.replace(/\s|\(|\)|\'|\,|\.+/g, '')
})
.exit()
.remove()
});
}
The bar disappear because you totally remove it with
.remove()
What you can do is hide the element when not selected like that :
d3.selectAll('.graph').selectAll("rect").attr("visibility", function(e) {
return e.active ? "hidden" : "";
})
See http://plnkr.co/edit/2UWaZOsffkw1vkdIJuSA?p=preview

Categories