Why does my d3 force-directed graph not display edges? - javascript

I created a simple force-directed graph using d3: http://goo.gl/afHTD
Why are the edges of the graph not showing? Here is my entire HTML file. You could also see it and tinker with it by going to view source on my linked page of course. It is based on the example from the d3 website.
<!DOCTYPE html>
<html>
<head>
<title>Force-Directed Layout</title>
<script type="text/javascript" src="d3.v2.js"></script>
<style type="text/css">
div.node {
border-radius: 6px;
width: 12px;
height: 12px;
margin: -6px 0 0 -6px;
position: absolute;
}
div.link {
position: absolute;
border-bottom: solid #999 1px;
height: 0;
-webkit-transform-origin: 0 0;
-moz-transform-origin: 0 0;
-ms-transform-origin: 0 0;
-o-transform-origin: 0 0;
transform-origin: 0 0;
}
</style>
</head>
<body>
<div id="chart"></div>
<script type="text/javascript">
var width = 960,
height = 500;
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-120)
.linkDistance(30)
.size([width, height]);
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("newJson.json", function(json) {
force
.nodes(json.nodes)
.links(json.links)
.start();
var link = svg.selectAll("line.link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.selectAll("circle.node")
.data(json.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 5)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);
node.append("title")
.text(function(d) { return d.name; });
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
});
</script>
</body>
</html>
Shouldn't var link... display the edges? My JSON file is also pretty simple:
{"nodes":
[{"name":"Myriel","group":1},
{"name":"Napoleon","group":1},
{"name":"Napoleon","group":2}],
"links":
[{"source":1,"target":0,"value":1},
{"source":1,"target":0,"value":1},
{"source":1, "target":2, "value":1}]}

You need to apply a stroke style via CSS. Your current node and link styles are restricted to HTML DIV elements, while the nodes and links are actually represented as SVG circle and line elements, respectively. Try this:
.node {
fill: #000;
stroke: #fff;
stroke-width: 1.5px;
}
.link {
stroke: #aaa;
stroke-width: 1.5px;
}

Related

Log scale was not plotting for line graph with domains (min:0.97,max:0.99)

I was trying to plot linechart with the linear scale for x-axis and log scale for y-axis, I was able to get ticks on x-axis and unable to get ticks on y-axis, approximate domain for y-axis for which I was trying to plot is (min:0.97, max:0.99).
For more information
I am sharing the code snippet for what I was trying to implement using d3js.
<div class="chart">
<svg id="lineChart" width="700" height="400"></svg>
</div>
var data =[{"x":0,"y":0.9978130459785461},{"x":0.008500000461935997,"y":0.9978128337965614},{"x":0.017000000923871994,"y":0.9978125548636445},{"x":0.025499999523162842,"y":0.9978121495279796},{"x":0.03400000184774399,"y":0.9978114984883847},{"x":0.042500000447034836,"y":0.9878106612451595},{"x":0.050999999046325684,"y":0.9878096376589295},{"x":0.05950000137090683,"y":0.9878084275193106},{"x":0.06800000369548798,"y":0.9878070306571847},{"x":0.07649999856948853,"y":0.9878055064026502},{"x":0.08500000089406967,"y":0.987803675684732},{"x":0.09350000321865082,"y":0.9778017168930565},{"x":0.10199999809265137,"y":0.9777995106789062},{"x":0.11050000041723251,"y":0.9777972353041961},{"x":0.11900000274181366,"y":0.9777947712404012},{"x":0.1274999976158142,"y":0.9777920584884845},{"x":0.13600000739097595,"y":0.9777892157479598},{"x":0.1445000022649765,"y":0.9777860636906962},
];
var lineChart = d3.select("#lineChart");
var WIDTH = 700;
var HEIGHT = 400;
var MARGINS = {top: 30,right:50, bottom:30, left:50};
var xMin = d3.min(data, function(d) {
return d.x;
});
var xMax = d3.max(data, function(d) {
return d.x;
});
var yMin = d3.min(data, function(d) {
return d.y;
});
var yMax = d3.max(data, function(d) {
return d.y;
});
var xScale = d3.scale.linear().range([MARGINS.left, WIDTH-MARGINS.right]).domain([xMin,xMax]);
var yScale = d3.scale.log().range([HEIGHT-MARGINS.top, MARGINS.bottom]).domain([yMin,yMax]);
var xAxes = d3.svg.axis().scale(xScale);
var yAxes = d3.svg.axis().scale(yScale).orient("left");
lineChart.append("g")
.attr("transform", "translate(0," + (HEIGHT-MARGINS.bottom) + ")")
.attr("class","x")
.call(xAxes);
lineChart.append("g")
.attr("transform", "translate(" + (MARGINS.left) + ",0)")
.attr("class","y")
.call(yAxes);
var line = d3.svg.line()
.x(function(d){return xScale(d.x);})
.y(function(d){return yScale(d.y);});
lineChart.append("path")
.attr("d", line(data))
.attr("stroke", "green")
.attr("stroke-width", 2)
.attr("fill", "none");
.chart {
width:700px;
height:400px;
margin: 0 auto;
}
#lineChart {
margin: 0 auto;
background-color: #ffffff;
box-shadow: 0px 0px 20px #000000;
}
.x, .y {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x text, .y text {
stroke: none;
fill: #000;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 13px;
}
codepen snippet:- https://codepen.io/shanmuks/pen/ZEQBpYm

d3js: display tips coorectly after zoom

I'm trying to write an example using D3.js where images lay on a static background. I can move the background and zoom and I can also move separate images (something like this but with images). Also, I need to display a tooltip when the mouse is over an image.
Here what I have tried with d3js v4:
Problems:
When zooming the tooltip is displayed at an incorrect location (The problem is obviously in handleMouseOver where d.x,d.y is just the initial position of the image, but I don't know how to get translate and scale parameters of the current view)
Width of tip is not resized automatically to the text width (should I change div.tooltip somehow?).
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script type="text/javascript" src="data.json"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
div.tooltip {
position: absolute;
text-align: center;
width: 120px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
</head>
<body>
<script>
IS_DRAGGING = false
var svg = d3.select("body")
.append("svg")
.attr("width", "100%")
.attr("height", "100%")
.style("background-color", "#E59400") // orange
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}))
.append("g");
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
function handleMouseOver(d, i) {
if(!IS_DRAGGING) {
div.transition()
.duration(100)
.style("opacity", .9);
div.html(d.url)
.style("left", (d.x+32) + "px")
.style("top", (d.y-28) + "px");
}
}
function handleMouseOut(d, i) {
div.transition()
.duration(100)
.style("opacity", 0);
}
function drag_strart(d) {
d3.select(this).raise().classed("active", true);
div.transition()
.duration(100)
.style("opacity", 0);
}
function dragging(d) {
d3.select(this).select("image")
.attr("x", d.x = d3.event.x)
.attr("y", d.y = d3.event.y);
IS_DRAGGING = true
}
function drag_end(d) {
d3.select(this).classed("active", false);
IS_DRAGGING = false
}
var arr = JSON.parse(data);
arr.forEach(function(d) {
d.x = getRandom(0, document.body.clientWidth);
d.y = getRandom(0, document.body.clientHeight);
})
var group = svg.selectAll('g')
.data(arr)
.enter().append("g").call(d3.drag()
.on("start", drag_strart)
.on("drag", dragging)
.on("end", drag_end))
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut)
group.append("image")
.attr("xlink:href", function(d) { return d.img_path; })
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.attr("width", 32)
.attr("height", 32)
</script>
</body>
Also, I have tried d3js v3 and the d3-tip library:
They work, but have some side effects:
For some reason, I can't move images separately.
When I zoom I want the tooltip to disappear (now it just stays at the same location and is even not redrawn at a new position and at the scale of the image)
Sometimes something like 'blinking' of the tooltip is happening (looks like it turns on and switch off many times when the cursor is near the edge of the image).
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="d3.tip.js"></script>
<script type="text/javascript" src="data.json"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
div.tooltip {
position: absolute;
text-align: center;
width: 120px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
.d3-tip {
line-height: 1.5;
font-weight: normal;
font-family: Helvetica, Arial, sans-serif;
font-size:13px;
padding: 10px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 3px;
position:relative;
z-index:101;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 20px;
width: 100%;
line-height: .5;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
</style>
</head>
<body>
<script>
var svg = d3.select("body")
.append("svg")
.attr("width", "100%")
.attr("height", "100%")
.style("background-color", "#E59400") // orange
.call(d3.behavior.zoom().on("zoom", function () {
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
}))
.append("g");
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function dragging_start(d) {
d3.select(this).raise().classed("active", true);
}
function dragging(d) {
d3.select(this).select("image")
.attr("x", d.x = d3.event.x)
.attr("y", d.y = d3.event.y);
}
function dragging_end(d) {
d3.select(this).classed("active", false);
}
var arr = JSON.parse(data);
arr.forEach(function(d) {
d.x = getRandom(0, document.body.clientWidth);
d.y = getRandom(0, document.body.clientHeight);
})
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) { return d.url; });
var drag = d3.behavior.drag()
.on("dragstart", dragging_start)
.on("drag", dragging)
.on("dragend", dragging_end);
var group = svg.selectAll('g')
.data(arr)
.enter().append("g").call(drag)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
group.append("image")
.attr("xlink:href", function(d) { return d.img_path; })
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.attr("width", 32)
.attr("height", 32)
.call(tip);
</script>
</body>
Update:
I figured out that adding d3.event.sourceEvent.stopPropagation(); were crucial, now I can move images separately. But the problem that looks like mouse cursor is moving faster than the image itself and also I subtracted half of image w,h (in my case 32/2) to drag the image at the center (by default it was the upper left corner).
function dragging_start(d) {
d3.event.sourceEvent.stopPropagation();
d3.select(this).raise().classed("active", true);
}
function dragging(d) {
d3.select(this).select("image")
.attr("x", d.x = d3.event.x-16)
.attr("y", d.y = d3.event.y-16);
}

How can I resize my d3.js script? is there a way to put this into a div tag where I can resize my bar chart smaller?

i am unable to resize my bar chart within a script tag. Currently the bar chat is showing up massive on the page and I would like to resize the chart into a smaller size on the page.
Is there a way to resize this using CSS or JavaScript or put it into a Div? I tried to give the script tag a 'id' or 'value' but no luck.
Could someone help me resize my chart please.
this is me d3.js:
<script>
data = [
{label:"Jan Sales", value:35},
{label:"XMAS", value:5},
];
var div = d3.select("body").append("div").attr("class", "toolTip");
var axisMargin = 20,
margin = 40,
valueMargin = 4,
width = parseInt(d3.select('body').style('width'), 10),
height = parseInt(d3.select('body').style('height'), 10),
barHeight = (height-axisMargin-margin*2)* 0.2/data.length,
barPadding = (height-axisMargin-margin*2)*0.6/data.length,
data, bar, svg, scale, xAxis, labelWidth = 0;
max = d3.max(data, function(d) { return d.value; });
svg = d3.select('body')
.append("svg")
.attr("width", width)
.attr("height", height);
bar = svg.selectAll("g")
.data(data)
.enter()
.append("g");
bar.attr("class", "bar")
.attr("cx",0)
.attr("transform", function(d, i) {
return "translate(" + margin + "," + (i * (barHeight + barPadding) + barPadding) + ")";
});
bar.append("text")
.attr("class", "label")
.attr("y", barHeight / 2)
.attr("dy", ".35em") //vertical align middle
.text(function(d){
return d.label;
}).each(function() {
labelWidth = Math.ceil(Math.max(labelWidth, this.getBBox().width));
});
scale = d3.scale.linear()
.domain([0, max])
.range([0, width - margin*2 - labelWidth]);
xAxis = d3.svg.axis()
.scale(scale)
.tickSize(-height + 2*margin + axisMargin)
.orient("bottom");
bar.append("rect")
.attr("transform", "translate("+labelWidth+", 0)")
.attr("height", barHeight)
.attr("width", function(d){
return scale(d.value);
});
bar.append("text")
.attr("class", "value")
.attr("y", barHeight / 2)
.attr("dx", -valueMargin + labelWidth) //margin right
.attr("dy", ".35em") //vertical align middle
.attr("text-anchor", "end")
.text(function(d){
return (d.value+"%");
})
.attr("x", function(d){
var width = this.getBBox().width;
return Math.max(width + valueMargin, scale(d.value));
});
bar
.on("mousemove", function(d){
div.style("left", d3.event.pageX+10+"px");
div.style("top", d3.event.pageY-25+"px");
div.style("display", "inline-block");
div.html((d.label)+"<br>"+(d.value)+"%");
});
bar
.on("mouseout", function(d){
div.style("display", "none");
});
svg.insert("g",":first-child")
.attr("class", "axisHorizontal")
.attr("transform", "translate(" + (margin + labelWidth) + ","+ (height - axisMargin - margin)+")")
.call(xAxis);
</script>
This is my CSS:
svg {
width: 100%;
height: 100%;
position: center;
}
.toolTip {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
position: absolute;
display: none;
width: auto;
height: auto;
background: none repeat scroll 0 0 white;
border: 0 none;
border-radius: 8px 8px 8px 8px;
box-shadow: -3px 3px 15px #888888;
color: black;
font: 12px sans-serif;
padding: 5px;
text-align: center;
}
text {
font: 15px sans-serif;
color: white;
}
text.value {
font-size: 100%;
fill: white;
}
.axisHorizontal path{
fill: none;
}
.axisHorizontal .tick line {
stroke-width: 1;
stroke: rgba(0, 0, 0, 0.2);
}
.bar {
fill: steelblue;
fill-opacity: .9;
font-size: 120%;
}
#search {
position:absolute;
top: -2%;
}
.tablebad thead tr {
background-color: #eee;
}
.tablegood thead tr th {
background-color: #eee;
}
Add a viewBox attribute to the svg element. This will allow you to lock the svg to the exact dimensions of your graph using the min-x, min-y, width and height parameters.
Then you can resize the svg element and you're graph will stretch to grow bigger or smaller.
https://www.w3.org/TR/SVG11/coords.html#ViewBoxAttribute
Edit:
Here is your js fiddle updated to use viewBox. I've commented out the width and height attributes so that it resizes as you make the page wider or narrower.
https://jsfiddle.net/cexLbfnk/1/
Is this the sort of thing you're looking for?

How to change the names of provinces on the map?

I have a map created using D3 and JavaScript. I want to translate the names of Spain's provinces to another language, for example, to English. By default it is Spanish.
I would prefer to make these changes manually, however, I don't know which file should I edit. I tried to edit hdi.json and provincias.json, but it does not work (I get the provinces colored in black without any title, like it is not recognized).
Any help is highly appreciated.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.nombre{
stroke: #000;
stroke-width: 0.5px
}
.graticule {
fill: none;
stroke: #777;
stroke-width: .5px;
stroke-opacity: .5;
}
.provinceNames
{
font-size: 0.9em;
font-family: "Lato";
}
.legendLinear
{
font-family: "Lato";
fill:#000000;
}
.legendTitle {
font-size: 1em;
}
#tooltip {
position: absolute;
top: 0;
left: 0;
z-index: 10;
margin: 0;
padding: 10px;
width: 200px;
height: 70px;
color: white;
font-family: sans-serif;
font-size: 1.0em;
font-weight: bold;
text-align: center;
background-color: rgba(0, 0, 0, 0.55);
opacity: 0;
pointer-events: none;
border-radius:5px;
transition: .2s;
}
</style>
<body>
<div id="container">
<div id="tooltip">
</div>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.7.0/d3-legend.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-composite-projections/0.3.5/conicConformalSpain-proj.min.js"></script>
<script>
var width = 1000,
height = 800;
var projection = d3.geo.conicConformalSpain().scale(width*5).translate([200+width/2, 100+height/2]);
var graticule = d3.geo.graticule().step([2, 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("#container").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
//var g = svg.append("g");
d3.json("provincias.json", function(error, provincias) {
d3.json("hdi.json", function(error, hdi) {
var land = topojson.feature(provincias, provincias.objects.provincias);
var color = d3.scale.threshold()
.domain([1, 10, 100, 1000, 10000, 100000, 300000])
.range(["#feebe2","#e5d1ff","#ba93ef", "#8D4CE5","#6100E5","#4d00b7","#C94D8C"]);
svg.selectAll(".nombre")
.data(land.features)
.enter()
.append("path")
.attr("d", path)
.attr("class","nombre")
.style("fill",function(d){ return color(hdi[d.properties.nombre]) })
.on("mouseover", function(d){
//Show the tooltip
var x = d3.event.pageX;
var y = d3.event.pageY - 40;
d3.select("#tooltip")
.style("left", x + "px")
.style("top", y + "px")
.style("opacity", 1)
.text( "... " + d.properties.nombre + " ... " + hdi[d.properties.nombre]);
})
.on("mouseout", function(){
//Hide the tooltip
d3.select("#tooltip")
.style("opacity", 0);
});
svg
.append("path")
.style("fill","none")
.style("stroke","#000")
.attr("d", projection.getCompositionBorders());
svg.append("g")
.attr("class", "provinceNames")
.selectAll("text")
.data(land.features)
.enter()
.append("svg:text")
.text(function(d){
return d.properties.nombre;
})
.attr("x", function(d){
return path.centroid(d)[0];
})
.attr("y", function(d){
return path.centroid(d)[1];
})
.attr("text-anchor","middle")
.attr('fill', 'black');
d3.select("svg").append("g")
.attr("class", "legendLinear")
.attr("transform", "translate(240,700)");
var logLegend = d3.legend.color()
.title("...")
.shapeHeight(20)
.shapeWidth(90)
.shapeRadius(10)
.labels([0, 10, 100, 1000, 10000, 100000, 300000])
.orient("horizontal")
.labelFormat(d3.format(".00f"))
.labelAlign("start")
.scale(color);
svg.select(".legendLinear")
.call(logLegend);
});
});
</script>
It seems that you're using this JSON for the provinces in Spain.
If that's correct, the file is "provincias.json" and this is the path for the names:
provincias.objects.provincias.geometries[index].properties.nombre
Where index is the index you want in the geometries array.
Check this demo:
d3.json("https://cdn.rawgit.com/rveciana/5919944/raw//provincias.json", function(provincias) {
provincias.objects.provincias.geometries.forEach(function(d) {
console.log(d.properties.nombre)
})
})
<script src="https://d3js.org/d3.v4.min.js"></script>

d3 - arrowhead not showing up

I have a bar chart where in I need to point an arrow at a specific bar and giving it a short label. I was able to get the arrow line, but the arrow head is not showing up.
What is that I am doing wrong?
MY code is below:
<!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: orange;
}
.bar:hover {
fill: orangered ;
}
.x.axis path {
display: none;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
line {
stroke: black;
}
path.marker {
fill: black;
}
path {
stroke: black;
fill: none;
}
</style>
<body>
<div class="container">
<div class="jumbotron">
<h2 style="text-align:center;">Head And Neck Therapy </h2>
</div>
<nav role="navigation" class="navbar navbar-default">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" data-target="#navbarCollapse" data-toggle="collapse" class="navbar-toggle">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collection of nav links and other content for toggling -->
<div id="navbarCollapse" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active">Data OverView</li>
<li>Profile</li>
<li>Messages</li>
</ul>
</div>
</nav>
<div id=chartId style="margin-top:50px; margin-left:50px;"></div>
</div>
</body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="http://cameronspear.com/downloads/bootstrap-hover-dropdown/bootstrap-hover-dropdown.js"></script>
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<style>
.jumbotron {
padding: 0.5em 0.6em;
h1 {
font-size: 2em;
}
p {
font-size: 1.2em;
.btn {
padding: 0.5em;
}
}
}
</style>
<script>
var margin = {top: 10, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .2);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(function(d) { return d + "%"; });
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>" + d.letter + " constitute : </strong> <span style='color:red'> " + d3.format(".2f")(d.frequency) + "% out of total population size</span>";
})
var svg = d3.select("#chartId").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 + ")");
svg.call(tip);
d3.tsv("data.tsv", type, function(error, data) {
var sum = d3.sum(data, function(d){return +d.frequency;});
//this will convert teh frequency into percent
data.forEach(function(d){ d.frequency = (d.frequency/sum)*100});
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, 100]);
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")
.text("Frequency");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
svg.selectAll("text.label")
.data(data.filter(function(d) { return d.frequency == ((441/sum)*100); }))
.enter().append("text")
.attr("class", "label")
.attr("x", function (d) {
return x(d.letter) + x.rangeBand()/2;
}).attr("y", function (d) {
return y(d.frequency) - 70;
})
.style("text-anchor", "middle")
.text("Your Patient");
svg.selectAll("line.arrow")
.data(data.filter(function(d) { return d.frequency == ((441/sum)*100); }))
.enter().append("line")
.attr("class", "arrow")
.attr("x1", function (d) {
return x(d.letter) + x.rangeBand()/2;
})
.attr("x2", function (d) {
return x(d.letter) + x.rangeBand()/2;
})
.attr("y1", function (d) {
return y(d.frequency) - 67;
})
.attr("y2", function (d) {
return y(d.frequency) - 10;
})
.attr("marker-end", "url(#arrow)");
});
function type(d) {
d.frequency = +d.frequency;
d.frequency = d3.format(".2f")(d.frequency)
return d;
}
</script>
</html>
The data.tsv file is as follows:
letter frequency
Asian 4
African-American 96
White 441
Hispanic 81
Other 11
The problem is here:
.attr("marker-end", "url(#arrow)");
There is no marker in the svg defs with Id arrow.
Refer:
http://bl.ocks.org/tomgp/d59de83f771ca2b6f1d4
https://developer.mozilla.org/en/docs/Web/SVG/Element/marker

Categories