Legend text background change on mouse-hover over d3 doughnut chart - html

I have one doughnut chart whose values display on mouse-hover. But, I want to change the legend text background while hovering over the respective doughnut chart area.
return {
restrict: 'E',
scope: {
values: '='
},
link: function (scope, element, attrs) {
scope.$watch('values', function(values) {
var data = [];
if(values) {
console.log('values from directive: ', values);
var w = 700,
h = 700,
r = 290,
inner = 190,
color = d3.scale.category20();
data=values;
var total = d3.sum(data, function(d) {
return d3.sum(d3.values(d));
});
var vis = d3.select("#pieChartsD3")
.append("svg:svg")
.data([data])
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" +320+ "," +320+ ")")
var textTop = vis.append("text")
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("class", "textTop")
.text( "TOTAL" )
.attr("y", -10),
textBottom = vis.append("text")
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("class", "textBottom")
.text(total.toFixed(0) )
.attr("y", 10);
var arc = d3.svg.arc()
.innerRadius(inner)
.outerRadius(r);
var arcOver = d3.svg.arc()
.innerRadius(inner + 20)
.outerRadius(r + 20);
var pie = d3.layout.pie()
.value(function(d) { return d.val; });
var arcs = vis.selectAll("g.slice")
.data(pie)
.enter()
.append("svg:g")
.attr("class", "slice")
.style('word-wrap', 'break-word')
.on("mouseover", function(d) {
d3.select(this).select("path").transition()
.duration(200)
.attr("d", arcOver)
textTop.text(d3.select(this).datum().data.name)
.style('fill', 'red')
.attr("y", -10);
textBottom.text(d3.select(this).datum().data.val.toFixed(0))
.style('fill', 'blue')
.attr("y", 10);
})
.on("mouseout", function(d) {
d3.select(this).select("path").transition()
.duration(100)
.attr("d", arc);
textTop.text( "TOTAL" )
.attr("y", -10);
textBottom.text(total.toFixed(0));
});
arcs.append("svg:path")
.attr("fill", function(d, i) { return color(i); } )
.attr("d", arc);
console.log("datas length: "+data.length)
var legend = d3.select("#legend").append("svg")
.attr("class", "legend")
.attr("width", 400)
.attr("height", 20*data.length)
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) { return color(i); });
legend.append("text")
.attr("x", 24)
.attr("y", 9)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
}
})
}
}

(BTW I'm inferring about your request because you haven't explicitly stated a question. With that said...)
Inside the .on("mouseover", function(d) { block, add another section:
legend.filter(function(l){
l === d; // remember d is the value bound to the donut segment
})
.attr("fill","yellow")
And be sure to write the logic to undo it, by setting fill back to grey or none, in .on("mouseout".

Related

D3 svg chart can't display in IE

I'm building a website which contains d3 svg to display the bar chart. It can display in Chrome, Firefox, Edge, Safari, but it is not working in IE. I have tried to use canvas method, but it is not working. Then I tried set viewbox for svg, but it is not working as well. Could anyone help me solve this problem?
Here's my d3.js and html code
function homeStats() {
var jsonobj = document.getElementById('stats-data').value;
var data = JSON.parse(jsonobj);
var parentDiv = document.getElementById("home-stats");
function drawbar() {
var margin = { top: 40, right: 20, bottom: 100, left: 40 };
var width = parentDiv.clientWidth - margin.left - margin.right;
var height = parentDiv.clientHeight - margin.top - margin.bottom;
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return "<span style='color:white'>" + d.value + "</span>";
})
d3.selectAll('#home-stats-svg').remove()
var svg = d3.select("#home-stats").append("svg").attr("id", "home-stats-svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.call(tip);
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .65);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#f79944", "#20b5e1"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
var columnNames = d3.keys(data[0]).filter(function (key) { return key !== "Year"; });
data.forEach(function (d) {
d.subGroups = columnNames.map(function (name) { return { name: name, value: +d[name] }; });
});
x0.domain(data.map(function (d) { return d.Year; }));
x1.domain(columnNames).rangeRoundBands([0, 30]);
y.domain([0, d3.max(data, function (d) { return d3.max(d.subGroups, function (d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end");
const rx = 5;
const ry = 5;
var Year = svg.selectAll(".Year")
.data(data)
.enter().append("g")
.attr("class", "Year")
.attr("transform", function (d) { return "translate(" + x0(d.Year) + ",0)"; });
Year.selectAll("rect")
.data(function (d) { return d.subGroups; })
.enter().append("path")
.style("fill", function (d) { return color(d.name); })
.attr("d", item => `
M${x1(item.name)},${y(item.value) + ry}
a${rx},${ry} 0 0 1 ${rx},${-ry}
h${10 - 2 * rx}
a${rx},${ry} 0 0 1 ${rx},${ry}
v${height - y(item.value) - ry}
h${-(10)}Z
`)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
var legend = svg.selectAll(".legend")
.data(columnNames.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 5)
.attr("width", "1vw")
.attr("height", "2vh")
.style("fill", color);
legend.append("text")
.attr("x", width - 7)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function (d) { return d; });
}
drawbar();
}
Html
<div id="home-stats" style="height:50vh; width:45vw">
<input type="hidden" id="stats-data" value=#ViewBag.deaths_json />
<svg id="home-stats-svg" viewBox="0 0 100 100"></svg>
</div>
Since the arrow function expression doesn't support IE browser, we could use babeljs.io to convert this function to ES5 format.

D3 v4 simple bar chart - date always returns null. timeParsing/format issue

For some odd reason, my dates won't properly show up on my bar chart. When checking for errors, my dates always show up as "null" in the console. My professor and I have tried re-arranging the format of the code regarding the dates, as well as the .csv spreadsheet itself.
The gradient still works fine, but ever since we've been stumped on implementing the dated timeline feature, the bar chart info is out of view, as well.
I'm using the core sample 'Dogecoin' from this website:
https://coinmetrics.io/data-downloads/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>DOGECOIN BAR CHART</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
var w = 1000;
var h = 500;
var margin = ({
top: 20,
right: 20,
bottom: 30,
left: 50
});
var svgMAIN = d3.select("body")
.append("svg")
.attr("height", h - margin.top - margin.bottom)
.attr("width", w - margin.left - margin.right);
var g = svgMAIN.append("g").attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var gradient = svgMAIN.append("defs")
.append("linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "100%")
.attr("spreadMethod", "pad");
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", "#3f51b5")
.attr("stop-opacity", 1);
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", "#009688")
.attr("stop-opacity", 0);
svgMAIN.append("rect")
.attr("width", w)
.attr("height", h)
.style("fill", "url(#gradient)");
var price = [];
var date = [];
var fixTime = d3.timeParse("%e-%b-%y");
var x = d3.scaleTime().range([0, w]);
var y = d3.scaleLinear().range([h, 0]);
d3.csv("doge.csv", function(error, data) {
data.map(function(d) {
d.date = fixTime(d.date);
price.push(d.priceUSD);
y.domain([0, d3.max(data, function(d) {
return d.priceUSD;
})]);
x.domain(d3.extent(data, function(d) {
return d.date;
}));
});
svgMAIN.append("g")
.attr("transform", "translate(0," + h + ")")
.call(d3.axisBottom(x))
g.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Price ($)");
var rect = svgMAIN.selectAll("rect")
.data(price)
.enter()
.append("rect")
.attr("x", function(d, i) {
return i * (w / price.length);
})
.attr("y", function(d) {
return d;
})
.attr("width", w / price.length)
.attr("height", function(d) {
return d;
})
.attr("fill", "midnightblue")
.on("mouseover", mouseOverPrice)
.on("mouseout", mouseOutPrice);
function mouseOverPrice(d, i) {
d3.select(this).raise()
.attr("fill", "white");
svgMAIN.append("text")
.attr("id", "priceValue")
.attr("x", "50")
.attr("y", "150")
.text("$" + d)
.attr("font-family", "sans-serif")
.attr("font-size", "150px")
.attr("fill", "white")
.attr("font-weight", "bold");
};
function mouseOutPrice(d, i) {
d3.select(this).attr("fill", "midnightblue");
d3.select("#priceValue").remove();
};
});
</script>
</body>
</html>

The values on x-axis are descending values on grouped bar chart using d3.js

I have transformed the vertical grouped bar chart from horizontal grouped bar chart. I have taken the code from the site https://bl.ocks.org/mbostock/3887051. The problem is when I have transformed horizontal to vertical axis the values on x-axis are not ascending but they are descending i.e., the values are 10M, 8M, 6M, 4M etc....I am not sure where I have made a mistake.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 50, left: 140},
width = 800 - margin.left - margin.right,
height = 900 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0],.1);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(y)
.orient("top").ticks(5);
var yAxis = d3.svg.axis()
.scale(x0)
.orient("left");
var svg = d3.select("body").append("svg")
.attr("height", width + margin.left + margin.right)
.attr("width", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("data.csv", function(error, data) {
if (error) throw error;
var ageNames = d3.keys(data[0]).filter(function(key) { return key !== "State"; });
data.forEach(function(d) {
d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.State; }));
x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0,0)")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "translate(0," + height + ")")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Population");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "state")
.attr("transform", function(d) { return "translate(0," + x0(d.State) + ")"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("height", x1.rangeBand())
.attr("y", function(d) { return x1(d.name); })
//.attr("x", function(d) { return y(d.value); })
.attr("width", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(ageNames.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 10)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 14)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
You y-scale which is used on your x-axis is defined as:
var y = d3.scale.linear()
.range([height, 0] , 0.1);
This runs it in reverse and should be:
var y = d3.scale.linear()
.range([0, height] , 0.1);

Unable to create bar chart from d3 using URL

I am trying to create bar chart from json file which is a URL but i am unable to do so please help me, as i am new to d3. The code is here please tell me where i am making mistake.
var width = 960,
height = 500;
var y = d3.scale.linear().range([height, 0]);
var chart = d3.select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
generateChart();
function generateChart() {
d3.json('http://dataserver.org:8009/topic/domain/cancer',
function(error, data) {
y.domain([0, d3.max(data, function(d) {
return d.occurrence
})]);
var barWidth = width / data.length; //width of each bar
var bar = chart.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(" + i * barWidth + ", 0)";
});
bar.append("rect")
.attr("y", function(d) {
return y(d.occurrence);
})
.attr("height", function(d) {
return height - y(d.occurrence);
})
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) {
return y(d.occurrence) - 10;
})
.attr("dy", ".75em")
.text(function(d) {
return d.authorName;
});
});
};
It is not a problem of cross domain as I checked your API. Assuming that you are fetching d3.js from CDN, I am suggesting a change. Your chart will depend on "institute" as it is containing all the required values for chart. So I changed it as per structure your API's response.
**in some case data was coming as "undefined" so I am fetching d3.js from CDN
Here is whole modified file:-
function generateChart() {
d3.json('http://srvgal78.deri.ie:8009/topic/domain/cancer',
function(error, data) {
data = data.institute;
y.domain([0, d3.max(data, function(d) {
return d.occurrence
})]);
var barWidth = width / data.length; //width of each bar
var bar = chart.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(" + i * barWidth + ", 0)";
});
bar.append("rect")
.attr("y", function(d) {
return y(d.occurrence);
})
.attr("height", function(d) {
return height - y(d.occurrence);
})
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) {
return y(d.occurrence) - 10;
})
.attr("dy", ".75em")
.text(function(d) {
return d.authorName;
});
});
};

d3 Bar Chart not showing up or giving me any errors to work from

Ok, so I'm trying to make a d3 chart, but when I do nothing shows up. Here is how my data is coming out in the JSON:
[{"Commodity":"Base","num_complete_print":"3","num_incomplete_print":15},{"Commodity":"Blade","num_complete_print":"1","num_incomplete_print":53},{"Commodity":"DTE","num_complete_print":"1","num_incomplete_print":17},{"Commodity":"HUB","num_complete_print":"0","num_incomplete_print":"18"},{"Commodity":"MH","num_complete_print":"0","num_incomplete_print":"18"},{"Commodity":"Mid","num_complete_print":"0","num_incomplete_print":18},{"Commodity":"Top","num_complete_print":"0","num_incomplete_print":18}]
Here is my javascript....
<script type="text/javascript">
var margin = {top: 20, right: 20, bottom: 100, left: 100},
width = 750 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width-100], .1); //width-100 to make room for the legend.
var y = d3.scale.linear()
.rangeRound([height, 0]);
var color = d3.scale.ordinal()
//.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
//.range(["#1f77b4", "#ff7f0e","d62728"]); //blue, orange, red
//color code for Progress Report
.range(["#00FFFF","#00FF00","#990099","#FF0000","#FFFF00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select("#area_progress_report").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 + ")");
// Get the data
var data = <?php echo json_encode($dataset_progress001); ?>;
//d3.csv("data.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Commodity"; }));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
//use this to sort the bars from largest to smallest
//data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { return d.Commodity; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text") //added this line through rotate to change orientation of x axis
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-1em")
.attr("transform", function(d) {
return "rotate(-90)"
});
svg.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");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.Commodity) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
//Added y label 10/28
svg.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("y", -60)
.attr("x",-190)
.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.text("Number Of Components");
</script>
And of course in my body I have this
<div id="area_progress_report"></div>
What am I doing wrong? I include the d3 locally...
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> <!-- added to try to avoid the d3 is not valid -->
<script type="text/javascript" src="d3-master/d3.v3.js"></script> <!-- load the d3.js library -->
<script type="text/javascript" src="d3-master/d3.v3.min.js"></script> <!-- load the d3.js library -->
Seems to work for me:
http://jsfiddle.net/wqHqP/
I simply replaced the line:
var data = <?php echo json_encode($dataset_progress001); ?>;
with your output JSON.