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);
}
Related
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?
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>
I am trying a simple pie chart with labels inside the slices. I can display the labels but all not all. e.g. in the sample code I have Rick 5%, Paul 4% and Steve 3% are not displayed because of the small size of the slices. How can I overcome the problem?
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Testing Pie Chart</title>
<!--<script type="text/javascript" src="d3/d3.v2.js"></script>-->
<script src="../js/d3.min.js" type="text/javascript"></script>
<style type="text/css">
#pieChart {
position:absolute;
top:10px;
left:10px;
width:400px;
height: 400px;
}
#lineChart {
position:absolute;
top:10px;
left:410px;
height: 150px;
}
#barChart {
position:absolute;
top:160px;
left:410px;
height: 250px;
}
.slice {
font-size: 8pt;
font-family: Verdana;
fill: white; //svg specific - instead of color
font-weight: normal ;
}
/*for line chart*/
.axis path, .axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges; //The shape-rendering property is an SVG attribute, used here to make sure our axis and its tick mark lines are pixel-perfect.
}
.line {
fill: none;
/*stroke: steelblue;*/
stroke-width: 3px;
}
.dot {
/*fill: white;*/
/*stroke: steelblue;*/
stroke-width: 1.5px;
}
.axis text {
font-family: Verdana;
font-size: 11px;
}
.title {
font-family: Verdana;
font-size: 15px;
}
.xAxis {
font-family: verdana;
font-size: 11px;
fill: black;
}
.yAxis {
font-family: verdana;
font-size: 11px;
fill: white;
}
table {
border-collapse:collapse;
border: 0px;
font-family: Verdana;
color: #5C5558;
font-size: 12px;
text-align: right;
}
td {
padding-left: 10px;
}
#lineChartTitle1 {
font-family: Verdana;
font-size : 14px;
fill : lightgrey;
font-weight: bold;
text-anchor: middle;
}
#lineChartTitle2 {
font-family: Verdana;
font-size : 72px;
fill : grey;
text-anchor: middle;
font-weight: bold;
/*font-style: italic;*/
}
</style>
</head>
<body>
var formatAsPercentage = d3.format("%"),
formatAsPercentage1Dec = d3.format(".1%"),
formatAsInteger = d3.format(","),
fsec = d3.time.format("%S s"),
fmin = d3.time.format("%M m"),
fhou = d3.time.format("%H h"),
fwee = d3.time.format("%a"),
fdat = d3.time.format("%d d"),
fmon = d3.time.format("%b")
;
function dsPieChart() {
var dataset = [
{category: "Tom", measure: 0.30},
{category: "John", measure: 0.30},
{category: "Martin", measure: 0.30},
{category: "Sam", measure: 0.30},
{category: "Peter", measure: 0.25},
{category: "Johannes", measure: 0.15},
{category: "Rick", measure: 0.05},
{category: "Lenny", measure: 0.18},
{category: "Paul", measure: 0.04},
{category: "Steve", measure: 0.03}
]
;
var width = 400,
height = 400,
outerRadius = Math.min(width, height) / 2,
innerRadius = outerRadius * .999,
// for animation
innerRadiusFinal = outerRadius * .5,
innerRadiusFinal3 = outerRadius * .45,
color = d3.scale.category20() //builtin range of colors
;
var vis = d3.select("#pieChart")
.append("svg:svg")
.data([dataset])
.attr("width", width)
.attr("height", height)
.append("svg:g")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
;
var arc = d3.svg.arc()
.outerRadius(outerRadius).innerRadius(innerRadius);
// for animation
var arcFinal = d3.svg.arc().innerRadius(innerRadiusFinal).outerRadius(outerRadius);
var arcFinal3 = d3.svg.arc().innerRadius(innerRadiusFinal3).outerRadius(outerRadius);
var pie = d3.layout.pie()
.value(function (d) {
return d.measure;
});
var arcs = vis.selectAll("g.slice")
.data(pie)
.enter()
.append("svg:g")
.attr("class", "slice")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("click", up)
;
arcs.append("svg:path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc)
.append("svg:title")
.text(function (d) {
return d.data.category + ": " + formatAsPercentage(d.data.measure);
});
d3.selectAll("g.slice").selectAll("path").transition()
.duration(750)
.delay(10)
.attr("d", arcFinal)
;
arcs.filter(function (d) {
return d.endAngle - d.startAngle > .2;
})
.append("svg:text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.attr("transform", function (d) {
return "translate(" + arcFinal.centroid(d) + ")rotate(" + angle(d) + ")";
})
.text(function (d) {
return d.data.category;
})
;
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
// Pie chart title
vis.append("svg:text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text("Revenue Share 2012")
.attr("class", "title")
;
function mouseover() {
d3.select(this).select("path").transition()
.duration(750)
//.attr("stroke","red")
//.attr("stroke-width", 1.5)
.attr("d", arcFinal3)
;
}
function mouseout() {
d3.select(this).select("path").transition()
.duration(750)
//.attr("stroke","blue")
//.attr("stroke-width", 1.5)
.attr("d", arcFinal)
;
}
function up(d, i) {
updateBarChart(d.data.category, color(i));
updateLineChart(d.data.category, color(i));
}
}
dsPieChart();
</script>
</body>
This line of your code determines which slices get label text appended to them:
arcs.filter(function (d) {
return d.endAngle - d.startAngle > .2;
})
.append("svg:text")...
So slices where the total arc angle is less than 0.2 radians will be filtered out, and label text will not be added.
You could just reduce the filter value, to display the labels on thinner slices (e.g. change .2 in this example to .05) to get the effect you want:
your very small data is not being displayed because it is being filtered out by this code. if you remove this piece of code, then those small data will also be displayed.
arcs.filter(function (d) {
return d.endAngle - d.startAngle > .2;
})
However label will not be displayed clearly in small data. Displaying labels outside pie chart will display labels a bit clear.
I am embarking on a journey to learn to visualize data using d3.js, and so far I am finding the "Interactive Data Visualization" by Scott Murray very helpful. I was following through some of the example codes in book chapter 11, and was wondering how I would add the tooltip to the pie chart (the book already describes this procedure using the bar chart). Anyways, just been tinkering around with the codes for past couple of hours and would like to see if anyone can lend me a hand on this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Pie layout</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style type="text/css">
text {
font-family: sans-serif;
font-size: 12px;
fill: white;
}
#tooltip {
position: absolute;
width: 200px;
height: auto;
padding: 10px;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-mox-box-shadow: 4px 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rbga(0, 0, 0, 0.4)
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
font-family: sans-serif;
font-size: 16px;
line-height: 20px;
}
</style>
</head>
<body>
<div id="tooltip" class="hidden">
<p><strong>Important Label Heading</strong></p>
<p><span id="value">100</span>%</p>
</div>
<script type="text/javascript">
//Width and height
var w = 300;
var h = 300;
var dataset = [ 5, 10, 20, 45, 6, 25 ];
var outerRadius = w / 2;
var innerRadius = 0;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.layout.pie();
// Easy colors accessible via a 10-step ordinal scale
var color = d3.scale.category10();
// Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
// Set up groups
var arcs = svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "arc")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
.on("mouseover", function(d){
d3.select("#tooltip")
.select("#value")
.text(d);
d3.select("tooltip").classed("hidden",false);
})
.on("mouseout", function() {
// Hide the tooltip
d3.select("#tooltip").classed("hidden", true);
});
// Draw arc paths
arcs.append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
// Labels
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.value;
});
</script>
</body>
</html>
I know this is bit to digest, but what I want to know more specifically is how to set the x and y value for the tool-tip. Thank you in advance.
I prefer to use the opacity to show/hide the tooltip. Here is the FIDDLE. This should get you going.
d3.select("#tooltip")
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + "px")
.style("opacity", 1)
.select("#value")
.text(d.value);
I'm adding mouse move event on FernOfTheAndes's answer, This will makes it more pretty usecase. Hope this will be helpful
.on("mouseover", function(d) {
d3.select("#tooltip").style('opacity', 1)
.select("#value").text(d.value);
})
.on("mousemove", function(d) {
d3.select("#tooltip").style("top", (d3.event.pageY - 10) + "px")
.style("left", (d3.event.pageX + 10) + "px");
})
.on("mouseout", function() {
d3.select("#tooltip").style('opacity', 0);
});
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;
}