Title does not appear on my D3js radar chart - javascript

I am new to java script and I am trying to draw a radar chart. Everything works well except title. Can u please tell me what is wrong? I attached the code below. First I create text var and call it to show.
<style>
body {
overflow: hidden;
margin: 0;
font-size: 14px;
font-family: "Helvetica Neue", Helvetica;
}
#chart {
position: absolute;
top: 60px;
left: 20px;
}
</style>
<script type="text/javascript" src="<c:url value='/js/radar.js'/>"></script>
<div id="body">
<div id="chart"></div>
</div>
<script>
var w = 200;
var h = 200;
var colorscale = d3.scale.category10();
//Legend, titles
var LegendOptions = ['Try Count','Succcess Count', 'Success Rate'];
////////////////////////////////////////////
/////////// Initiate legend ////////////////
////////////////////////////////////////////
var svg = d3.select('#body')
.selectAll('svg')
.append('svg')
.attr("width", w+300)
.attr("height", h)
//Create the title for the legend
var text = svg.append("text")
.attr("class", "title")
.attr('transform', 'translate(90,0)')
.attr("x", w - 70)
.attr("y", 10)
.attr("font-size", "12px")
.attr("fill", "#404040")
.text("What % of owners use a specific service in a week");
//Initiate Legend
var legend = svg.append("g")
.attr("class", "legend")
.attr("height", 100)
.attr("width", 200)
.attr('transform', 'translate(90,20)')
;
//Create colour squares
legend.selectAll('rect')
.data(LegendOptions)
.enter()
.append("rect")
.attr("x", w - 65)
.attr("y", function(d, i){ return i * 20;})
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d, i){ return colorscale(i);})
;
//Create text next to squares
legend.selectAll('text')
.data(LegendOptions)
.enter()
.append("text")
.attr("x", w - 52)
.attr("y", function(d, i){ return i * 20 + 9;})
.attr("font-size", "11px")
.attr("fill", "#737373")
.text(function(d) { return d; })
;
//Options for the Radar chart, other than default
var mycfg = {
w: w,
h: h,
maxValue: 0.6,
levels: 6,
ExtraWidthX: 300
}

Try changing:
var svg = d3.select('#body')
.selectAll('svg')
.append('svg')....
To:
var svg = d3.select('#body')
.append('svg')....
As you are only appending one svg, you do not need the selectAll() portion. The following takes your code and makes that one change:
var w = 200;
var h = 200;
var svg = d3.select('#body')
.append('svg')
.attr("width", w+300)
.attr("height", h)
var text = svg.append('g').append("text")
.attr("class", "title")
.attr('transform', 'translate(90,0)')
.attr("x", w - 70)
.attr("y", 10)
.attr("font-size", "12px")
.attr("fill", "#404040")
.text("What % of owners use a specific service in a week");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="body"></div>

Related

Graph is no longer appearing when I use d3.json to access json data

I'm very new to D3.js - please can you help? I have successfully created a bar chart and used json data within the code, but when I removed it to create a separate json file and inserted d3.json("sales.json").then(function(data){ graph as before};) it no longer works. It's such a simple line of code to insert and matches the code I've found online so I can't see why it isn't working. Can anyone help please? Thanks.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="L4F - Axes and scales ">
<title>SVG</title>
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
</head>
<body>
<h1> Sales data </h1>
<script>
d3.json("sales.json").then(function(data){
var w = 500;
var h = 500;
var padding = 2;
var lmargin = 50;
var bmargin = 50;
var tmargin = 50;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h)
.style("background", "white");
var plotArea = svg.append('g');
function colourPicker(v){
if (v<=20) {return "#666666";}
else if (v>20) {return "#ff0033";}
}
plotArea.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x",function(d, i){return i * ((w - lmargin)/dataset.length) + lmargin;})
.attr("y",function (d){ return h - (d.s*4) - bmargin;})
.attr("width", (w-lmargin)/dataset.length - padding)
.attr("height", function(d){return d.s*4;})
.attr("fill", function(d){ return colourPicker(d.s);})
plotArea.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {return (d.m+" £"+d.s);})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {return i*((w - lmargin)/dataset.length)+((w - lmargin)/dataset.length - padding)/2;})
.attr("y", function(d) { return h-(d.s*4)+14 - bmargin;})
.attr("font-family", "sans-serif")
.attr("font-size", 12)
.attr("fill", "white")
var maxY = d3.max(dataset.map(function(d){return (d.s);}))
var yScale = d3.scaleLinear()
.domain([0, maxY*4])
.range([h-maxY*4, 0]);
var yAxis = d3.axisLeft()
.scale(yScale);
var yAxisGroup = svg.append('g')
.attr('transform', 'translate('+lmargin+','+(bmargin)+')')
.call(yAxis);
yAxisGroup.append("text")
.text("Sales")
.attr("y", h/2 - bmargin)
.attr("x", lmargin/2)
.attr("transform", "translate(-230,230) rotate(270)")
.style("fill", "black")
.attr("font-size", "14")
.attr("text-anchor", "middle");
};)
</script>
</body>
</html>
And my json file looks like this..
[
{
"s":25,
"m":"Jan"
},
{
"s":10,
"m":"Feb"
},
{
"s":15,
"m":"Mar"
}
]

Add chart to tooltip in d3

I am attempting to add a simply bar chart to my tooltip; it consists of 2 variables -- men and women. I was hoping someone might be able to help me put this inside of the tooltip instead of appending it to where it is currently being appended. I've given this a particular area to be appended just so that I know that it is, in fact, showing up(which it is), but I don't know how to get it into the tool tip. Any help is much appreciated. Oh, and this needs to be done in d3, which is partial to why I am asking this question -- I saw a similar question that wasn't implemented in pure d3, and I couldn't completely follow what was going on to emulate it in this example.
.on("mouseover", function(d)
{
tip.show(d);
var state = d.properties.name;
var men = d.properties.men;
var women = d.properties.women;
var dataset = [men, women];
var barHeight = 20;
var x = d3.scale.linear()
.domain([0, d3.max(dataset)])
.range([0, width/2]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", barHeight * dataset.length);
var bar = chart.selectAll("g")
.data(dataset)
.enter().append("g")
.attr("transform", function(d, i)
{
return "translate(0," + i * barHeight + ")";
});
bar.append("rect")
.attr("width", x)
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d)
{
return x(d)/2+5;
})
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d)
{
return "$" + d;
});
})
Since you didn't shared the whole code to create the chart, this answer will deal with your question's title only:
How to create a chart inside a tooltip?
I'm not a d3.tip() user, since I create my own tooltips. But what you want is not complicated at all: As the tooltips are <div> elements, you can definitely add a SVG inside them.
However, you have to know where to create the SVG. So, in the following demo, I'm creating this d3.tip tooltip:
var tool_tip = d3.tip()
.attr("class", "d3-tip")
.offset([20, 120])
.html("<p>This is a SVG inside a tooltip:</p>
<div id='tipDiv'></div>");
//div ID here --^
The important part here is this: there is a inner <div> inside the d3.tip div, with a given ID (in that case, tipDiv). I'm gonna use that ID to create my SVG inside the tooltip:
selection.on('mouseover', function(d) {
tool_tip.show();
var tipSVG = d3.select("#tipDiv")
//select the div here--^
.append("svg")
//etc...
})
Here is the demo:
var svg = d3.select("body")
.append("svg")
.attr("width", 300)
.attr("height", 300);
var tool_tip = d3.tip()
.attr("class", "d3-tip")
.offset([20, 120])
.html("<p>This is a SVG inside a tooltip:</p><div id='tipDiv'></div>");
svg.call(tool_tip);
var data = [14, 27, 19, 6, 17];
var circles = svg.selectAll("foo")
.data(data)
.enter()
.append("circle");
circles.attr("cx", 50)
.attr("cy", function(d, i) {
return 20 + 50 * i
})
.attr("r", function(d) {
return d
})
.attr("fill", "teal")
.on('mouseover', function(d) {
tool_tip.show();
var tipSVG = d3.select("#tipDiv")
.append("svg")
.attr("width", 200)
.attr("height", 50);
tipSVG.append("rect")
.attr("fill", "steelblue")
.attr("y", 10)
.attr("width", 0)
.attr("height", 30)
.transition()
.duration(1000)
.attr("width", d * 6);
tipSVG.append("text")
.text(d)
.attr("x", 10)
.attr("y", 30)
.transition()
.duration(1000)
.attr("x", 6 + d * 6)
})
.on('mouseout', tool_tip.hide);
.d3-tip {
line-height: 1;
padding: 6px;
background: wheat;
border-radius: 4px solid black;
font-size: 12px;
}
p {
font-family: Helvetica;
}
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<p>Hover over the circles:</p>

How to create different colour shades to column bar in d3 [duplicate]

I have created a D3 bar chart, which takes in my data, applies a scale and then draws my rectangles. Here's my current output:
I would like to make it more visual. The values are temperatures, so I'd like to create something like the first bar here:
Basically I want to make a bar that is made up of many rectangles of different colors.
After considering several options, I decided to try to inject a pattern into my bars. I tried making my pattern from paths, and then I attempted rectangles, but no success.
I'm not tied to the 'pattern' approach, so an different approach, or how I can make this pattern, is what I'm after. Here's my code:
// Set variables.
var dataset = // an array of objects, each with two properties: location and temperature
w = 500,
h = 800,
xScale = d3.scale.linear()
.domain([-30, 40])
.range([5, 350]),
yScale = d3.scale.ordinal();
// Create SVG element.
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
/* svg.append("defs")
.append("pattern")
.attr("id", "heatHatch")
.attr("patternUnits", "userSpaceOnUse")
.attr("width", 350)
.attr("height", 25);
.append("path")
.attr("d", "M10 0 L10 20 L0 20 L0 0 Z M22 0 L22 20 L12 20 L12 0 Z")
.attr("fill", "pink")
.append("path")
.attr("d", "M22 0 L22 20 L12 20 L12 0 Z")
.attr("fill", "red");
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 10)
.attr("height", 20)
.attr("fill", "pink"); */
// Create bars.
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", 0)
.attr("y", function(d, i) {
return i * 25;
})
.attr("width", function(d) {
return xScale(d[1]);
})
.attr("height", 20);
/*.attr("fill", "url(#heatHatch)"); */
Thanks.
If you want pattern that scales to the bar size, use a gradient pattern:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script>
var w = 500,
h = 500;
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
var color = d3.scale.category10();
var gradient = svg.append("svg:defs")
.append("svg:linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "50%")
.attr("x2", "100%")
.attr("y2", "50%")
.attr("spreadMethod", "pad");
d3.range(10).forEach(function(d, i) {
var c = color(i);
gradient.append("svg:stop")
.attr("offset", (i * 10) + "%")
.attr("stop-color", c)
.attr("stop-opacity", 1);
gradient.append("svg:stop")
.attr("offset", ((i + 1) * 10) + "%")
.attr("stop-color", c)
.attr("stop-opacity", 1);
});
svg.selectAll("bar")
.data(d3.range(10))
.enter()
.append("rect")
.attr("class", "bar")
.attr("width", function(d,i){
return (w / 10) * i;
})
.attr("height", (h / 10) - 10)
.attr("y", function(d,i){
return (h / 10) * i;
})
.style("fill", "url(#gradient)");
</script>
</body>
</html>
If you want a pattern with statically sized colors, create a pattern of rects:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script>
var w = 500,
h = 500;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
var color = d3.scale.category10();
var pattern = svg.append("svg:defs")
.append("svg:pattern")
.attr("width", w)
.attr("height", 4)
.attr("id", "myPattern")
.attr("patternUnits","userSpaceOnUse");
d3.range(10).forEach(function(d, i) {
var c = color(i);
pattern.append("rect")
.attr("height", "4px")
.attr("width", w / 10)
.attr("x", (w / 10) * i)
.attr("fill", c);
});
svg.selectAll("bar")
.data(d3.range(10))
.enter()
.append("rect")
.attr("class","bar")
.attr("width", function(d,i){
return (w / 10) * i;
})
.attr("height", (h / 10) - 10)
.attr("y", function(d,i){
return (h / 10) * i;
})
.style("fill", "url(#myPattern)");
</script>
</body>
</html>

Tooltip for svg heatmap/colorscale in d3js

I am adapting this gradient example in AngularJS. Here is a bit of the dataset I'm using:
var stays=[
{
day:2,
hour:1,
time_spent:127
},
{
day:4,
hour:1,
time_spent:141
},
{
day:1,
hour:1,
time_spent:134
},
{
day:5,
hour:1,
time_spent:174
},
{
day:3,
hour:1,
time_spent:131
},
{
day:6,
hour:1,
time_spent:333
}];
The problem is that I want to construct a tooltip for each of the squares that are created in the heatmap. The tooltip is here:
var heatMap = svg.selectAll(".hour")
.data(stays)
.enter().append("rect")
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("stroke", "white")
.style("stroke-opacity", 0.6)
.style("stroke-width", 0.8)
.style("fill", function(d) { return colorScale(d.time_spent); })
.on("mouseover", function(d, i) {
// Construct tooltip
var tooltip_html = '';
tooltip_html += '<div class="header"><strong>' + 'Stays' + ' </strong></div><br>';
// Add info to the tooltip
angular.forEach(stays, function (d) {
tooltip_html += '<div><span><strong>' + makeid() + '</strong></span>';
tooltip_html += '<span>' + ' ' + d.time_spent + '</span></div>';
console.log(d.time_spent);
}, days);
// Set tooltip width
tooltip.html(tooltip_html)
.style("width", 300 + "px")
.style("left", (d3.event.layerX+10) + "px")
.style("top", (d3.event.layerY+10) + "px");
// Tooltip transition and more styling
tooltip.style('display', 'block')
.transition()
.ease('ease-in')
.duration(100)
.style("opacity", .9);
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(100)
.ease('ease-in')
.style('opacity', 0);
});
The idea here is, for each square that I visit, the tooltip will show the labels associated (I'm still not using labels but they are going to be part of the dataset I've shown, I'm using the makeid() function to create random names) to that square, together with a breakdown of the associated time_spent data. With what I'm using now it is writing the full list of numbers and not the ones associated to each square. Ideas? Thank you.
Rather than building tootip HTML for each cell, consider attaching the data to each cell rect. Create a single data div and fill it when the cursor moves over the cell.
I added this to the heatmap gradient example. Give it a try.
var accidents=[{day:2,hour:1,count:127},{day:4,hour:1,count:141},{day:1,hour:1,count:134},{day:5,hour:1,count:174},{day:3,hour:1,count:131},{day:6,hour:1,count:333},{day:7,hour:1,count:311},{day:2,hour:2,count:79},{day:4,hour:2,count:99},{day:1,hour:2,count:117},{day:5,hour:2,count:123},{day:3,hour:2,count:92},{day:6,hour:2,count:257},{day:7,hour:2,count:293},{day:2,hour:3,count:55},{day:4,hour:3,count:73},{day:1,hour:3,count:107},{day:5,hour:3,count:89},{day:3,hour:3,count:66},{day:6,hour:3,count:185},{day:7,hour:3,count:262},{day:2,hour:4,count:39},{day:4,hour:4,count:67},{day:1,hour:4,count:59},{day:5,hour:4,count:83},{day:3,hour:4,count:45},{day:6,hour:4,count:180},{day:7,hour:4,count:220},{day:2,hour:5,count:48},{day:4,hour:5,count:57},{day:1,hour:5,count:73},{day:5,hour:5,count:76},{day:3,hour:5,count:72},{day:6,hour:5,count:168},{day:7,hour:5,count:199},{day:2,hour:6,count:129},{day:4,hour:6,count:102},{day:1,hour:6,count:129},{day:5,hour:6,count:140},{day:3,hour:6,count:117},{day:6,hour:6,count:148},{day:7,hour:6,count:193},{day:2,hour:7,count:314},{day:4,hour:7,count:284},{day:1,hour:7,count:367},{day:5,hour:7,count:270},{day:3,hour:7,count:310},{day:6,hour:7,count:179},{day:7,hour:7,count:192},{day:2,hour:8,count:806},{day:4,hour:8,count:811},{day:1,hour:8,count:850},{day:5,hour:8,count:609},{day:3,hour:8,count:846},{day:6,hour:8,count:208},{day:7,hour:8,count:144},{day:2,hour:9,count:1209},{day:4,hour:9,count:1214},{day:1,hour:9,count:1205},{day:5,hour:9,count:960},{day:3,hour:9,count:1073},{day:6,hour:9,count:286},{day:7,hour:9,count:152},{day:2,hour:10,count:750},{day:4,hour:10,count:808},{day:1,hour:10,count:610},{day:5,hour:10,count:655},{day:3,hour:10,count:684},{day:6,hour:10,count:482},{day:7,hour:10,count:253},{day:2,hour:11,count:591},{day:4,hour:11,count:593},{day:1,hour:11,count:573},{day:5,hour:11,count:695},{day:3,hour:11,count:622},{day:6,hour:11,count:676},{day:7,hour:11,count:326},{day:2,hour:12,count:653},{day:4,hour:12,count:679},{day:1,hour:12,count:639},{day:5,hour:12,count:736},{day:3,hour:12,count:687},{day:6,hour:12,count:858},{day:7,hour:12,count:402},{day:2,hour:13,count:738},{day:4,hour:13,count:749},{day:1,hour:13,count:631},{day:5,hour:13,count:908},{day:3,hour:13,count:888},{day:6,hour:13,count:880},{day:7,hour:13,count:507},{day:2,hour:14,count:792},{day:4,hour:14,count:847},{day:1,hour:14,count:752},{day:5,hour:14,count:1033},{day:3,hour:14,count:942},{day:6,hour:14,count:983},{day:7,hour:14,count:636},{day:2,hour:15,count:906},{day:4,hour:15,count:1031},{day:1,hour:15,count:954},{day:5,hour:15,count:1199},{day:3,hour:15,count:1014},{day:6,hour:15,count:1125},{day:7,hour:15,count:712},{day:2,hour:16,count:1101},{day:4,hour:16,count:1158},{day:1,hour:16,count:1029},{day:5,hour:16,count:1364},{day:3,hour:16,count:1068},{day:6,hour:16,count:1062},{day:7,hour:16,count:736},{day:2,hour:17,count:1303},{day:4,hour:17,count:1426},{day:1,hour:17,count:1270},{day:5,hour:17,count:1455},{day:3,hour:17,count:1407},{day:6,hour:17,count:883},{day:7,hour:17,count:666},{day:2,hour:18,count:1549},{day:4,hour:18,count:1653},{day:1,hour:18,count:1350},{day:5,hour:18,count:1502},{day:3,hour:18,count:1507},{day:6,hour:18,count:830},{day:7,hour:18,count:652},{day:2,hour:19,count:998},{day:4,hour:19,count:1070},{day:1,hour:19,count:787},{day:5,hour:19,count:1027},{day:3,hour:19,count:1019},{day:6,hour:19,count:575},{day:7,hour:19,count:519},{day:2,hour:20,count:661},{day:4,hour:20,count:756},{day:1,hour:20,count:596},{day:5,hour:20,count:730},{day:3,hour:20,count:648},{day:6,hour:20,count:494},{day:7,hour:20,count:486},{day:2,hour:21,count:431},{day:4,hour:21,count:539},{day:1,hour:21,count:430},{day:5,hour:21,count:509},{day:3,hour:21,count:457},{day:6,hour:21,count:443},{day:7,hour:21,count:421},{day:2,hour:22,count:352},{day:4,hour:22,count:428},{day:1,hour:22,count:362},{day:5,hour:22,count:462},{day:3,hour:22,count:390},{day:6,hour:22,count:379},{day:7,hour:22,count:324},{day:2,hour:23,count:329},{day:4,hour:23,count:381},{day:1,hour:23,count:293},{day:5,hour:23,count:393},{day:3,hour:23,count:313},{day:6,hour:23,count:374},{day:7,hour:23,count:288},{day:2,hour:24,count:211},{day:4,hour:24,count:249},{day:1,hour:24,count:204},{day:5,hour:24,count:417},{day:3,hour:24,count:211},{day:6,hour:24,count:379},{day:7,hour:24,count:203}];
///////////////////////////////////////////////////////////////////////////
//////////////////// Set up and initiate svg containers ///////////////////
///////////////////////////////////////////////////////////////////////////
var days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
times = d3.range(24);
var margin = {
top: 170,
right: 50,
bottom: 70,
left: 50
};
var width = Math.max(Math.min(window.innerWidth, 1000), 500) - margin.left - margin.right - 20,
gridSize = Math.floor(width / times.length),
height = gridSize * (days.length+2);
//SVG container
var svg = d3.select('#trafficAccidents')
.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 + ")");
//Reset the overall font size
var newFontSize = width * 62.5 / 900;
d3.select("html").style("font-size", newFontSize + "%");
///////////////////////////////////////////////////////////////////////////
//////////////////////////// Draw Heatmap /////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//Based on the heatmap example of: http://blockbuilder.org/milroc/7014412
var colorScale = d3.scale.linear()
.domain([0, d3.max(accidents, function(d) {return d.count; })/2, d3.max(accidents, function(d) {return d.count; })])
.range(["#FFFFDD", "#3E9583", "#1F2D86"])
//.interpolate(d3.interpolateHcl);
var dayLabels = svg.selectAll(".dayLabel")
.data(days)
.enter().append("text")
.text(function (d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
.attr("class", function (d, i) { return ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); });
var timeLabels = svg.selectAll(".timeLabel")
.data(times)
.enter().append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)")
.attr("class", function(d, i) { return ((i >= 8 && i <= 17) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });
var heatMap = svg.selectAll(".hour")
.data(accidents)
.enter().append("rect")
//----attach data to rect---
.attr("data","This is the data for this cell")
.attr("onmouseover","showData(evt)")
.attr("onmouseout","hideData(evt)")
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("stroke", "white")
.style("stroke-opacity", 0.6)
.style("fill", function(d) { return colorScale(d.count); });
//Append title to the top
svg.append("text")
.attr("class", "title")
.attr("x", width/2)
.attr("y", -90)
.style("text-anchor", "middle")
.text("Number of Traffic accidents per Day & Hour combination");
svg.append("text")
.attr("class", "subtitle")
.attr("x", width/2)
.attr("y", -60)
.style("text-anchor", "middle")
.text("The Netherlands | 2014");
//Append credit at bottom
svg.append("text")
.attr("class", "credit")
.attr("x", width/2)
.attr("y", gridSize * (days.length+1) + 80)
.style("text-anchor", "middle")
.text("Based on Miles McCrocklin's Heatmap block");
///////////////////////////////////////////////////////////////////////////
//////////////// Create the gradient for the legend ///////////////////////
///////////////////////////////////////////////////////////////////////////
//Extra scale since the color scale is interpolated
var countScale = d3.scale.linear()
.domain([0, d3.max(accidents, function(d) {return d.count; })])
.range([0, width])
//Calculate the variables for the temp gradient
var numStops = 10;
countRange = countScale.domain();
countRange[2] = countRange[1] - countRange[0];
countPoint = [];
for(var i = 0; i < numStops; i++) {
countPoint.push(i * countRange[2]/(numStops-1) + countRange[0]);
}//for i
//Create the gradient
svg.append("defs")
.append("linearGradient")
.attr("id", "legend-traffic")
.attr("x1", "0%").attr("y1", "0%")
.attr("x2", "100%").attr("y2", "0%")
.selectAll("stop")
.data(d3.range(numStops))
.enter().append("stop")
.attr("offset", function(d,i) {
return countScale( countPoint[i] )/width;
})
.attr("stop-color", function(d,i) {
return colorScale( countPoint[i] );
});
///////////////////////////////////////////////////////////////////////////
////////////////////////// Draw the legend ////////////////////////////////
///////////////////////////////////////////////////////////////////////////
var legendWidth = Math.min(width*0.8, 400);
//Color Legend container
var legendsvg = svg.append("g")
.attr("class", "legendWrapper")
.attr("transform", "translate(" + (width/2) + "," + (gridSize * days.length + 40) + ")");
//Draw the Rectangle
legendsvg.append("rect")
.attr("class", "legendRect")
.attr("x", -legendWidth/2)
.attr("y", 0)
//.attr("rx", hexRadius*1.25/2)
.attr("width", legendWidth)
.attr("height", 10)
.style("fill", "url(#legend-traffic)");
//Append title
legendsvg.append("text")
.attr("class", "legendTitle")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "middle")
.text("Number of Accidents");
//Set scale for x-axis
var xScale = d3.scale.linear()
.range([-legendWidth/2, legendWidth/2])
.domain([ 0, d3.max(accidents, function(d) { return d.count; })] );
//Define x-axis
var xAxis = d3.svg.axis()
.orient("bottom")
.ticks(5)
//.tickFormat(formatPercent)
.scale(xScale);
//Set up X axis
legendsvg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (10) + ")")
.call(xAxis);
//--show/hide data---
function showData(evt)
{
var target=evt.target
target.setAttribute("opacity",".8")
//---locate dataDiv near cursor--
var x = evt.clientX;
var y = evt.clientY;
//---scrolling page---
var offsetX=window.pageXOffset
var offsetY=window.pageYOffset
dataDiv.style.left=10+x+offsetX+"px"
dataDiv.style.top=20+y+offsetY+"px"
//---data--
var data=target.getAttribute("data")
//---format as desired---
var html=data
dataDiv.innerHTML=html
dataDiv.style.visibility="visible"
}
function hideData(evt)
{
dataDiv.style.visibility="hidden"
var target=evt.target
target.removeAttribute("opacity")
}
<head>
<meta charset="utf-8">
<!-- D3.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<!-- Google Font -->
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400' rel='stylesheet' type='text/css'>
<style>
html { font-size: 62.5%; }
body {
font-size: 1rem;
font-family: 'Open Sans', sans-serif;
font-weight: 400;
fill: #8C8C8C;
text-align: center;
}
.timeLabel, .dayLabel {
font-size: 1.6rem;
fill: #AAAAAA;
font-weight: 300;
}
text.axis-workweek, text.axis-worktime {
fill: #404040;
font-weight: 400;
}
.title {
font-size: 2.8rem;
fill: #4F4F4F;
font-weight: 300;
}
.subtitle {
font-size: 1.4rem;
fill: #AAAAAA;
font-weight: 300;
}
.credit {
font-size: 1.2rem;
fill: #AAAAAA;
font-weight: 400;
}
.axis path, .axis tick, .axis line {
fill: none;
stroke: none;
}
text {
font-size: 1.2rem;
fill: #AAAAAA;
font-weight: 400;
}
.legendTitle {
font-size: 1.6rem;
fill: #4F4F4F;
font-weight: 300;
}
</style>
</head>
<body>
<div id="trafficAccidents"></div>
<div id=dataDiv style='box-shadow: 4px 4px 4px #888888;-webkit-box-shadow:2px 3px 4px #888888;padding:2px;position:absolute;top:0px;left:0px;visibility:hidden;background-color:linen;border: solid 1px black;border-radius:5px;'></div>
</body>
I think you may be making this too complex.
Try using foxToolTip.js
https://github.com/MichaelRFox/foxToolTip.jS
After you create your unique I'd just use the .each method to add a unique tooltip.

Adding Text to the End of My Bars - D3

I am currently making a Bar Graph which shows data in the form of a horizontal bar which grows based on the data put into the code. What I am trying to do here is make text appear next to the bars when they appear and change as the data does. I have already made a listener which changes the data appearing I just do not know how to make the data appear and change.
<!DOCTYPE html>
<html>
<head>
<meta>
<meta name="description" content="Drawing Shapes w/ D3 - " />
<meta charset="utf-8">
<title>Resources per Project</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
h1 {
font-size: 35px;
color: darkgrey;
font-family: Helvetica;
border-bottom-width: 3px;
border-bottom-style: dashed;
border-bottom-color: black;
}
h2 {
font-size: 20px;
color: black;
font-family: Helvetica;
text-decoration: underline;
margin-left: 350px;
margin-top: 0px;
}
</style>
</head>
<body>
<h1>Resources used per Project</h1>
<p>Choose Month:
<select id="label-option">
<option value="April">April</option>
<option value="May">May</option>
<option value="June">June</option>
<option value="July">July</option>
<option value="August">August</option>
<option value="September">September</option>
</select>
<script type="text/javascript">
var width = 800
var height = 500
var emptyVar = 0
var dataArrayProjects = ['2G', 'An', 'At', 'Au', 'AW', 'Ch', 'CI', 'CN']
var April = [0.35, 1.66, 3.04, 1.54, 3.45, 2.56, 2.29, 1.37]
var May = [0.36, 1.69, 3.08, 1.54, 3.62, 2.61, 2.22, 1.44]
var June = [0.34, 1.7, 3.08, 1.63, 3.66, 2.68, 2.24, 1.51]
var July = [0.3, 1.72, 3.17, 1.67, 3.56, 2.56, 2.17, 1.44]
var August = [0.28, 1.79, 3.18, 1.71, 3.62, 2.73, 2.26, 1.54]
var September = [1.23, 1.74, 3.12, 1.61, 3.66, 2.71, 2.2, 1.48]
d3.select("#label-option").on("change", change)
function change() {
var data = April;
if (this.selectedIndex == 1){
data = May;
} else if (this.selectedIndex == 2){
data = June;
} else if (this.selectedIndex == 3){
data = July;
} else if (this.selectedIndex == 4){
data = August;
} else if (this.selectedIndex == 5){
data = September;
}
canvas.selectAll("rect")
.data(data)
.attr("width", emptyVar)
.attr("height", 50)
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return i * 55
})
bars.transition()
.duration(1500)
.delay(200)
.attr("width", function(d) {
return widthScale(d);
})
}
var widthScale = d3.scale.linear()
.domain([0, 4])
.range([0, width - 60]);
var heightScale = d3.scale.ordinal()
.domain(dataArrayProjects)
.rangePoints([10, height - 85]);
var color = d3.scale.linear()
.domain([0, 4])
.range(["#000033", "#22cdff"])
var xAxis = d3.svg.axis()
.ticks("30")
.scale(widthScale);
var yAxis = d3.svg.axis()
.scale(heightScale)
.orient("left");
var canvas = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(40, 0)");
var bars = canvas.selectAll("rect")
.data(April)
.enter()
.append("rect")
.attr("width", emptyVar)
.attr("height", 50)
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return i * 55
})
canvas.append("g")
.attr("transform", "translate(0, 430)")
.attr("font-family", "Helvetica")
.attr("font-size", "15px")
.call(xAxis);
canvas.append("g")
.attr("font-family", "Helvetica")
.attr("font-size", "15px")
.style("fill", "black")
.attr("class", "y axis")
.call(yAxis);
bars.transition()
.duration(1500)
.delay(200)
.attr("width", function(d) {
return widthScale(d);
})
var yAxisLine = canvas.append("line")
.attr("x1", -3)
.attr("y1", 0)
.attr("x2", -3)
.attr("y2", 436)
.attr("stroke-width", 6)
.attr("stroke", "black");
canvas.selectAll("text")
.data(April)
.enter()
.append("text")
.text(function(d) {
return April;
})
.attr("x", function(d, i) {
return i * (width / April.length);
})
.attr("y", function(d) {
return height - (April * 4);
});
</script>
<h2>Resources</h2>
</body>
</html>
As you can see the data is not easily readable and hard to understand without knowing the precise number within the data. How do I make numbers appear next to the bars which say the exact amount of data being displayed. Please do not link other bar graphs with their own tooltips as I am not very good with d3.js and do not understand other graphs as well.
You can achieve that by first creating labels like below:
var texts = canvas.selectAll(".label")//select all DOMs with class label.
.data(April)
.enter()
.append("text")
.attr("class", "label")
.attr("x", function(d) {
return widthScale(d) + 10;//x location of the label
})
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return (i * 55) + 25; //y location of the label
})
.text(function(d, i) {
return d;
})
Finally in the update section do the following to update the labels.
texts = canvas.selectAll(".label")
.data(data)
.attr("x", function(d) {
return widthScale(d) + 10;
})
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return (i * 55) + 25
})
.text(function(d, i) {
return d;
})
working code here

Categories