Related
Heading ##Trying to get cola.js "Layout with hierarchical grouping" Set up.
Trying to create the following in my browser:
http://marvl.infotech.monash.edu/webcola/examples/gridifiedSmallGroups.html
I get the error:
d[a.type] is not a function
cola.min.js:2023 Uncaught TypeError: d[a.type] is not a function
return a.d3adaptor = function() {
var d = d3.dispatch("start", "tick", "end"),
e = a.adaptor({
trigger: function(a) {
d[a.type](a)
},
on: function(a, b) {
return d.on(a, b), e
},
kick: function(a) {
d3.timer(a)
},
drag: function() {
var a = d3.behavior.drag().origin(function(a) {
return a
}).on("dragstart.d3adaptor", b).on("drag.d3adaptor", function(a) {
a.px = d3.event.x, a.py = d3.event.y, e.resume()
}).on("dragend.d3adaptor", c);
return arguments.length ? void this.call(a) : a
}
});
return e
},
HTML
<html lang="en">
<head>
<meta charset="utf-8" />
<style>
.node {
stroke: #fff;
stroke-width: 1.5px;
cursor: move;
}
.group {
stroke: #fff;
stroke-width: 1.5px;
cursor: move;
opacity: 0.7;
}
.link {
stroke: #7a4e4e;
stroke-width: 3px;
stroke-opacity: 1;
}
.label {
fill: white;
font-family: Verdana;
font-size: 25px;
text-anchor: middle;
cursor: move;
}
</style>
</head>
<body>
<script src="./d3.min.js" charset="utf-8" type="text/javascript"></script>
<script src="./cola.min.js"></script>
<script>
var width = 960,
height = 500;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var cola = cola.d3adaptor(d3)
.linkDistance(80)
.avoidOverlaps(true)
.handleDisconnected(false)
.size([width, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("smallgrouped.json", function (error, graph) {
graph.nodes.forEach(function (v) {
v.width = v.height = 95;
})
graph.groups.forEach(function (g) { g.padding = 0.01; });
cola
.nodes(graph.nodes)
.links(graph.links)
.groups(graph.groups)
.start(100, 0, 50, 50);
var group = svg.selectAll(".group")
.data(graph.groups)
.enter().append("rect")
.attr("rx", 8).attr("ry", 8)
.attr("class", "group")
.style("fill", function (d, i) { return color(i); });
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link");
var pad = 20;
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("rect")
.attr("class", "node")
.attr("width", function (d) { return d.width - 2 * pad; })
.attr("height", function (d) { return d.height - 2 * pad; })
.attr("rx", 5).attr("ry", 5)
.style("fill", function (d) { return color(graph.groups.length); })
.call(cola.drag)
.on('mouseup', function (d) {
d.fixed = 0;
cola.alpha(1); // fire it off again to satify gridify
});
var label = svg.selectAll(".label")
.data(graph.nodes)
.enter().append("text")
.attr("class", "label")
.text(function (d) { return d.name; })
.call(cola.drag);
node.append("title")
.text(function (d) { return d.name; });
cola.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("x", function (d) { return d.x - d.width / 2 + pad; })
.attr("y", function (d) { return d.y - d.height / 2 + pad; });
group.attr("x", function (d) { return d.bounds.x; })
.attr("y", function (d) { return d.bounds.y; })
.attr("width", function (d) { return d.bounds.width(); })
.attr("height", function (d) { return d.bounds.height(); });
label.attr("x", function (d) { return d.x; })
.attr("y", function (d) {
var h = this.getBBox().height;
return d.y + h/4;
});
});
});
</script>
</body>
</html>
JSON
{
"nodes":[
{"name":"a","width":60,"height":40},
{"name":"b","width":60,"height":40},
{"name":"c","width":60,"height":40},
{"name":"d","width":60,"height":40},
{"name":"e","width":60,"height":40},
{"name":"f","width":60,"height":40},
{"name":"g","width":60,"height":40}
],
"links":[
{"source":1,"target":2},
{"source":2,"target":3},
{"source":3,"target":4},
{"source":0,"target":1},
{"source":2,"target":0},
{"source":3,"target":5},
{"source":0,"target":5}
],
"groups":[
{"leaves":[0], "groups":[1]},
{"leaves":[1,2]},
{"leaves":[3,4]}
]
}
I meet the same issue. If you use d3v4 or later version, you will get this error. If you use d3v3, it works well.
I want to make a force graph with permanently visible text on the nodes and text on the links.
This snippet provides labels on the nodes.
The 2nd snippet from an answer to Show tool-tip on links of force directed graph in d3js provides mouseover labels on links and nodes.
I'm currently trying to extend the second to make the mouseover node labels permanent.
var width = 400;
var height = 125;
var margin = 20;
var pad = margin / 2;
var graph = { "nodes":[ { "name": "A"}, { "name": "B"}] };
drawGraph(graph);
function drawGraph(graph) {
var svg = d3.select("#force").append("svg")
.attr("width", width)
.attr("height", height);
// create an area within svg for plotting graph
var plot = svg.append("g")
.attr("id", "plot")
.attr("transform", "translate(" + pad + ", " + pad + ")");
var layout = d3.layout.force()
.size([width - margin, height - margin])
.charge(-120)
.nodes(graph.nodes)
.start();
drawNodes(graph.nodes);
// add ability to drag and update layout
d3.selectAll(".node").call(layout.drag);
layout.on("tick", function() {
d3.selectAll(".node")
.attr("cx", d => { return d.x; })
.attr("cy", d => { return d.y; });
});
}
// Draws nodes on plot
function drawNodes(nodes) {
d3.select("#plot").selectAll(".node")
.data(nodes)
.enter()
.append("circle")
.attr("class", "node")
.attr("id", (d, i) => { return d.name; })
.attr("cx", (d, i) => { return d.x; })
.attr("cy", (d, i) => { return d.y; })
.attr("r", 4)
.style("fill", "#EE77b4")
.on("mouseover", function(d, i) {
var x = d3.mouse(this)[0];
var y = d3.mouse(this)[1];
var tooltip = d3.select("#plot")
.append("text")
.text(d.name)
.attr("x", x)
.attr("y", y)
.attr("id", "tooltip");
})
.on("mouseout", function(d, i) {
d3.select("#tooltip").remove();
});
}
body {
font-family: 'Source Sans Pro', sans-serif;
font-weight: 300;
}
b {
font-weight: 900;
}
.outline {
fill: none;
stroke: #888888;
stroke-width: 1px;
}
#tooltip {
font-size: 10pt;
font-weight: 900;
fill: #000000;
stroke: #ffffff;
stroke-width: 0.25px;
}
.node {
stroke: #ffffff;
stroke-weight: 1px;
}
.highlight {
stroke: red;
stroke-weight: 4px;
stroke-opacity: 1.0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div align="center" id="force"></div>
I've tried replacing the mouseover function with:
.each( function(d, i) {
var x = d.x; //d3.mouse(this)[0];
var y = d.y; //d3.mouse(this)[1];
var tooltip = d3.select("#plot")
.append("text")
.text(d.name)
.attr("x", x)
.attr("y", y)
.attr("id", "tooltip");
})
but now the labels don't move so I added
d3.selectAll("text").attr( "x", d => { return d.x; })
.attr( "y", d => { return d.y; });
in layout.on("tick", function() ...
But now it's all in one place doesn't move and I get TypeError: d is undefined
Rewrite your code this way (pay attention on the comments):
layout.on("tick", function() {
tooltips // here we set new position for tooltips on every tick
.attr("x", (d, i) => { return d.x; })
.attr("y", (d, i) => { return d.y; });
d3.selectAll(".node")
.attr("cx", d => { return d.x; })
.attr("cy", d => { return d.y; });
});
...
function drawNodes(nodes) {
tooltips = d3.select("#plot").selectAll(".node")
.data(nodes)
.enter()
.append("circle")
.attr("class", "node")
.attr("id", (d, i) => { return d.name; })
.attr("cx", (d, i) => { return d.x; })
.attr("cy", (d, i) => { return d.y; })
.attr("r", 4)
.style("fill", "#EE77b4")
.select(function() { return this.parentNode }) // returns to parent node
.append('text') // append svg-text elements for tooltip
.data(nodes)
.text(function(d) { return d.name; }) // set text
.attr("x", (d, i) => { return d.x; }) // set initial x position
.attr("y", (d, i) => { return d.y; }) // set initial y position
.attr("id", function(d,i) { return "tooltip-" + i; }) // set unique id
.attr("class", "d3-tooltip");
}
Working demo:
var width = 400;
var height = 125;
var margin = 20;
var pad = margin / 2;
var tooltips = null;
var graph = { "nodes":[ { "name": "A"}, { "name": "B"}] };
drawGraph(graph);
function drawGraph(graph) {
var svg = d3.select("#force").append("svg")
.attr("width", width)
.attr("height", height);
// create an area within svg for plotting graph
var plot = svg.append("g")
.attr("id", "plot")
.attr("transform", "translate(" + pad + ", " + pad + ")");
var layout = d3.layout.force()
.size([width - margin, height - margin])
.charge(-120)
.nodes(graph.nodes)
.start();
drawNodes(graph.nodes);
// add ability to drag and update layout
d3.selectAll(".node").call(layout.drag);
layout.on("tick", function() {
tooltips
.attr("x", (d, i) => { return d.x; })
.attr("y", (d, i) => { return d.y; });
d3.selectAll(".node")
.attr("cx", d => { return d.x; })
.attr("cy", d => { return d.y; });
});
}
// Draws nodes on plot
function drawNodes(nodes) {
tooltips = d3.select("#plot").selectAll(".node")
.data(nodes)
.enter()
.append("circle")
.attr("class", "node")
.attr("id", (d, i) => { return d.name; })
.attr("cx", (d, i) => { return d.x; })
.attr("cy", (d, i) => { return d.y; })
.attr("r", 4)
.style("fill", "#EE77b4")
.select(function() { return this.parentNode })
.append('text')
.data(nodes)
.text(function(d) { return d.name; })
.attr("x", (d, i) => { return d.x; })
.attr("y", (d, i) => { return d.y; })
.attr("class", "d3-tooltip")
.attr("id", function(d,i) { return "tooltip-" + i; });
}
body {
font-family: 'Source Sans Pro', sans-serif;
font-weight: 300;
}
b {
font-weight: 900;
}
.outline {
fill: none;
stroke: #888888;
stroke-width: 1px;
}
.d3-tooltip {
font-size: 20pt;
font-family: 'Comic Sans MS';
font-weight: 900;
fill: #000000;
stroke: #ffffff;
stroke-width: 0.25px;
}
.node {
stroke: #ffffff;
stroke-weight: 1px;
}
.highlight {
stroke: red;
stroke-weight: 4px;
stroke-opacity: 1.0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div align="center" id="force"></div>
I have a parallel coordinates visualization and I've added a table below that represents all the data in the visualization.
I want to filter the table based on the selection of the parallel coordinates visualization. So, just showing the data highlighted in the parallel coordinates visualization.
Any ideas on how to do that?
I've tried in the brush section to highlight the cells in the table in red adding a style in for the tags, but it doesn't seem to work. See code below:
// Add and store a brush for each axis.
g.append("g")
.attr("class", "brush")
.each(function(d) {
d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brushstart", brushstart).on("brush", brush));
d3.selectAll("td").style('bgcolor', 'red');
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
I've tried to add the highlight of the cells in the brush function. Here I achieve for all the cells to turn red, but I don't know how to highlight only the ones selected in the selection.
function brush() {
var actives = dimensions.filter(function(p) {
return !y[p].brush.empty();
}),
extents = actives.map(function(p) {
return y[p].brush.extent();
});
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
d3.selectAll("td").style('background-color', 'red');
}
See code below, which you can find also in the following link GitHub:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
}
.background path {
fill: none;
stroke: #ddd;
shape-rendering: crispEdges;
}
.foreground path {
fill: none;
stroke: steelblue;
stroke-width: 2;
}
.brush .extent {
fill-opacity: .3;
stroke: #fff;
shape-rendering: crispEdges;
}
.axis line,
.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
cursor: move;
}
.tooltip {
background-color: rgba(220,220,220,0.5);
color: #333;
margin: 10px;
height: 25px;
padding-right: 10px;
padding-left: 10px;
padding-top: 10px;
-webkit-border-radius:10px;
-moz-border-radius:10px;
border-radius:10px;
}
td, th {
padding: 1px 4px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Fuente original: https://bl.ocks.org/jasondavies/1341281
var margin = {
top: 30,
right: 10,
bottom: 10,
left: 10
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangePoints([0, width], 1),
y = {},
dragging = {};
var line = d3.svg.line(),
axis = d3.svg.axis().orient("left"),
background,
foreground;
var svg = d3.select("body").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 + ")");
var notas = [
{
"Nombre": "Emily",
"Matematicas": "10",
"Ciencias": "10",
"Historia": "8",
"Geografia": "8",
"Lengua": "10"
},
{
"Nombre": "Cooper",
"Matematicas": "10",
"Ciencias": "7",
"Historia": "2",
"Geografia": "8",
"Lengua": "10"
}];
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip")
.attr("class","tooltip");
// Extract the list of dimensions and create a scale for each.
x.domain(dimensions = d3.keys(notas[0]).filter(function(d) {
return d != "Nombre" && (y[d] = d3.scale.linear()
.domain(d3.extent(notas, function(p) {
return +p[d];
}))
.range([height, 0]));
}));
// Add grey background lines for context.
background = svg.append("g")
.attr("class", "background")
.selectAll("path")
.data(notas)
.enter().append("path")
.attr("d", path);
// Add blue foreground lines for focus.
foreground = svg.append("g")
.attr("class", "foreground")
.selectAll("path")
.data(notas)
.enter().append("path")
.attr("d", path)
.on("mouseover", function(n){
d3.select(this)
.transition().duration(100)
.style({'stroke' : '#F00'});
tooltip.text(n.Nombre);
return tooltip.style("visibility", "visible");
})
.on("mousemove", function(){
return tooltip
.style("top", (event.pageY-10)+"px")
.style("left",(event.pageX+10)+"px");
})
.on("mouseout", function(d){
d3.select(this)
.transition().duration(100)
.style({'stroke': 'steelblue' })
.style({'stroke-width' : '2'});
return tooltip.style("visibility", "hidden");
});
// Add a group element for each dimension.
var g = svg.selectAll(".dimension")
.data(dimensions)
.enter().append("g")
.attr("class", "dimension")
.attr("transform", function(d) {
return "translate(" + x(d) + ")";
})
.call(d3.behavior.drag()
.origin(function(d) {
return {
x: x(d)
};
})
.on("dragstart", function(d) {
dragging[d] = x(d);
background.attr("visibility", "hidden");
})
.on("drag", function(d) {
dragging[d] = Math.min(width, Math.max(0, d3.event.x));
foreground.attr("d", path);
dimensions.sort(function(a, b) {
return position(a) - position(b);
});
x.domain(dimensions);
g.attr("transform", function(d) {
return "translate(" + position(d) + ")";
})
})
.on("dragend", function(d) {
delete dragging[d];
transition(d3.select(this)).attr("transform", "translate(" + x(d) + ")");
transition(foreground).attr("d", path);
background
.attr("d", path)
.transition()
.delay(500)
.duration(0)
.attr("visibility", null);
}));
// Add an axis and title.
g.append("g")
.attr("class", "axis")
.each(function(d) {
d3.select(this).call(axis.scale(y[d]));
})
.append("text")
.style("text-anchor", "middle")
.attr("y", -9)
.text(function(d) {
return d;
});
// Add and store a brush for each axis.
g.append("g")
.attr("class", "brush")
.each(function(d) {
d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brushstart", brushstart).on("brush", brush));
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
function position(d) {
var v = dragging[d];
return v == null ? x(d) : v;
}
function transition(g) {
return g.transition().duration(500);
}
// Returns the path for a given data point.
function path(d) {
return line(dimensions.map(function(p) {
return [position(p), y[p](d[p])];
}));
}
function brushstart() {
d3.event.sourceEvent.stopPropagation();
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function(p) {
return !y[p].brush.empty();
}),
extents = actives.map(function(p) {
return y[p].brush.extent();
});
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
}
// The table generation function
function tabulate(data, columns) {
var table = d3.select("body").append("table")
.attr("style", "margin-left: 250px"),
thead = table.append("thead"),
tbody = table.append("tbody");
// append the header row
thead.append("tr")
.selectAll("th")
.data(columns)
.enter()
.append("th")
.text(function(column) { return column; });
// create a row for each object in the data
var rows = tbody.selectAll("tr")
.data(notas)
.enter()
.append("tr");
// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {column: column, value: row[column]};
});
})
.enter()
.append("td")
.attr("style", "font-family: Courier") // sets the font style
.html(function(d) { return d.value; });
return table;
}
// render the table
var peopleTable = tabulate(notas, ["Nombre", "Matematicas","Ciencias", "Historia","Geografia", "Lengua"]);
</script>
</body>
</html>
I've added also the code in JSFiddle but it doesn't display anything. I'm not sure what I'm doing wrong. I'm not familiar with JSFiddle, so I might be doing something wrong.
I've tried also to use divgrid (DivGrid) and with the following code I can see how when I attempt to brush the table gets updated. The problem is that it doesn't get updated with the data I need. I just have it to show 5 records.
<script src="divgrid.js"></script>
...
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function(p) {
return !y[p].brush.empty();
}),
extents = actives.map(function(p) {
return y[p].brush.extent();
});
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
//d3.selectAll("td").style('background-color', 'red');
var grid = d3.divgrid();
d3.select('body')
.datum(notas.slice(0,5))
.call(grid);
}
The problems I have (I think) is that (1) the update of the table is not really in the right place as it is only updating when starting to brush, not when brushing over the lines and (2) I need to find a way to pickup the data from the lines that are selected. I've added to code in github as a reference (GitHub)
Any ideas?
Thanks
I know it is possible to display an image in a D3 tooltip. What I am trying to do is to display a bar graph in a tooltip (i.e when the mouse hovers over the object a bar graph appears). I have adapted code from http://bl.ocks.org/jarobertson/1483052#gistfile1.html and combined it with the bar graph code by Robert Lewand. And well, it doesn't work. I dont even get any errors in the console that could perhaps put me on the right path. Is it possible to do? Here is my code:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.27.1"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
div.tooltip {
position: absolute;
text-align: center;
width: 500px;
height: 550px;
padding: 8px;
font: 10px sans-serif;
background: #ddd;
border: solid 1px #aaa;
border-radius: 8px;
pointer-events: none;
}
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: middle;
}
</style>
</head>
<body>
<script type="text/javascript">
var w = 960,
h = 500;
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
svg.append("svg:g")
.attr("transform", "translate(480,50)rotate(60)scale(2)")
.append("svg:rect")
.attr("width", 140)
.attr("height", 140)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseout", mouseout);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
function mouseover() {
div.transition()
.duration(500)
.style("opacity", 1);
}
// where the tooltip previosly contained an image
function mousemove() {
div
.html("<h1>Bar Graph</h1><br> <svg class='chart'></svg>")
.style("left", (d3.event.pageX - 34) + "px")
.style("top", (d3.event.pageY - 12) + "px");
}
function mouseout() {
div.transition()
.duration(500)
.style("opacity", 1e-6);
}
// make bar graph
var width = 300,
height = 300;
var y = d3.scale.linear()
.range([height, 0]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", height);
d3.tsv("data.tsv", type, function(error, data) {
y.domain([0, d3.max(data, function(d) { return d.value; })]);
var barWidth = width / data.length;
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.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) { return y(d.value) + 3; })
.attr("dy", ".75em")
.text(function(d) { return d.value; });
});
function type(d) {
d.value = +d.value; // coerce to number
return d;
}
</script>
</body>
</html>
Thanks in advance!
apologies, the data.tsv file contains the following:
Sentiment value
Strongly positive 211
Positive 222
Neutral 654
Negative 618
Strongly negative 343
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.27.1"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
div.tooltip {
position: absolute;
text-align: center;
width: 500px;
height: 550px;
padding: 8px;
font: 10px sans-serif;
background: #ddd;
border: solid 1px #aaa;
border-radius: 8px;
pointer-events: none;
}
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: middle;
}
</style>
<script type="text/javascript">
var w = 960,
h = 500;
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
svg.append("svg:g")
.attr("transform", "translate(480,50)rotate(60)scale(2)")
.append("svg:rect")
.attr("width", 140)
.attr("height", 140)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseout", mouseout);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
function mouseover() {
div.transition()
.duration(500)
.style("opacity", 1);
}
// where the tooltip previosly contained an image
function mousemove() {
div
.html("<h1>Bar Graph</h1><br> <svg class='chart'></svg>")
.style("left", (d3.event.pageX - 34) + "px")
.style("top", (d3.event.pageY - 12) + "px");
}
function mouseout() {
div.transition()
.duration(500)
.style("opacity", 1e-6);
}
// make bar graph
var width = 300,
height = 300;
var y = d3.scale.linear()
.range([height, 0]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", height);
d3.tsv("data.tsv", type, function(error, data) {
y.domain([0, d3.max(data, function(d) { return d.value; })]);
var barWidth = width / data.length;
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.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) { return y(d.value) + 3; })
.attr("dy", ".75em")
.text(function(d) { return d.value; });
});
function type(d) {
d.value = +d.value; // coerce to number
return d;
}
</script>
'data.tsv' file is not with us,
and we have written only
function mousemove() {
div
.html("<h1>Bar Graph</h1><br> <svg class='chart'></svg>")
.style("left", (d3.event.pageX - 34) + "px")
.style("top", (d3.event.pageY - 12) + "px");
}
above function will place 'Bar Graph' text and one svg element in tooltip.
Hope you will get it.
If not ask for more......
I have trouble to add paths to a g element created by the nodes with selectAll:
// define the nodes
var node = svg.selectAll(".node").data(force.nodes()).enter()
.append("g").attr("id", function(d) {
return d.id;
}).attr("class", "node").style("fill", function(d) {
return color(d.group);
}).call(force.drag);
// add the nodes
...
// add the links and the arrows
var path = node.selectAll("g").data(force.links(), function(d) {
return d.id
}).append("path")
// .attr("class", function(d) { return "link " + d.type; })
.attr("class", "link").attr("marker-end", "url(#end)");
The input data looks like this:
{
"nodes": [
{
"id": 0,
"name": "N1",
"group": 4
},
{
"id": 1,
"name": "N2",
"group": 1
},
{
"id": 2,
"name": "N3",
"group": 1
}
],
"links": [
{
"id": 0,
"source": 0,
"target": 1
},
{
"id": 0,
"source": 0,
"target": 2
}
]
}
I'm trying to modify this example
My goal is that a node has a mouse over (.node:hover) including all the out-going links. With my simple data it would look like that node N1 would have a mouse over including the two links.
Thanks for your help!
Here is all the code:
<!DOCTYPE html>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.js"></script>
<style>
.node {
opacity: 0.8;
stroke: #fff;
stroke-width: 1.5px;
}
.node text {
pointer-events: none;
font: 10px sans-serif;
stroke-width: 0px;
}
.node:hover {
opacity: 1;
}
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
</style>
<body>
<script>
// get the data
d3.json("data2.json", function(error, graph) {
var color = d3.scale.category20();
var width = 960, height = 500;
var force = d3.layout.force().nodes(graph.nodes).links(graph.links)
.size([ width, height ]).linkDistance(300).charge(-300).on(
"tick", tick).start();
var svg = d3.select("body").append("svg").attr("width", width)
.attr("height", height);
// build the arrow.
svg.append("svg:defs").selectAll("marker").data([ "end" ]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String).attr("viewBox", "0 -5 10 10").attr("refX", 15)
.attr("refY", -1.5).attr("markerWidth", 6).attr(
"markerHeight", 6).attr("orient", "auto").append(
"svg:path").attr("d", "M0,-5L10,0L0,5");
// define the nodes
var node = svg.selectAll(".node").data(force.nodes()).enter()
.append("g").attr("id", function(d) {
return d.id;
}).attr("class", "node").style("fill", function(d) {
return color(d.group);
}).call(force.drag);
// add the nodes
node.append("circle").attr("r", function(d) {
return 3 * d.group
});
// add the text
node.append("text").attr("x", 12).attr("dy", ".35em").style(
"color", "black").text(function(d) {
return d.name;
});
// add the links and the arrows
var path = node.selectAll("g").data(force.links(), function(d) {
return d.id
}).append("path")
// .attr("class", function(d) { return "link " + d.type; })
.attr("class", "link").attr("marker-end", "url(#end)");
// add the curvy lines
function tick() {
path.attr("d", function(d) {
var dx = d.target.x - d.source.x, dy = d.target.y
- d.source.y, dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + ","
+ dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
});
</script>
</body>
</html>
I solved my issue with mouseover and mouseout:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="author" content="myborobudur">
<meta name="date" content="2014-09-02T00:00:00+01:00">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Job Recommender: d3js Graph Study</title>
<script src="http://d3js.org/d3.v3.js"></script>
<style>
.node {
opacity: 0.8;
stroke: #fff;
stroke-width: 1.5px;
}
.text {
pointer-events: none;
font: 12px sans-serif;
stroke-width: 0px;
color: #000;
}
.node:hover {
opacity: 1;
}
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<h2>Job Recommender: d3js Graph Study</h2>
<script>
function selectLinks(thisObject) {
changeLinkStyle(thisObject, function(node, link) {
link.style("stroke", node.attr("fillColor"));
link.style("stroke-width", "10px");
link.style("opacity", "0.5");
link.attr("marker-end", "");
});
}
function deSelectLinks(thisObject) {
changeLinkStyle(thisObject, function(node, link) {
link.style("stroke", "#666");
link.style("stroke-width", "1.5px");
link.style("opacity", "1");
link.attr("marker-end", "url(#end)");
});
}
function changeLinkStyle(thisObject, changeStyle) {
var source = d3.select(thisObject);
var sourceId = d3.select(thisObject).attr('id');
d3.selectAll('.link').each(function(d, i) {
var link = d3.select(this);
var linkSourceId = link.attr('source');
if (linkSourceId === sourceId) {
changeStyle.call(undefined, source, link);
}
});
}
// get the data
d3.json("data.json", function(error, graph) {
var color = d3.scale.category20();
var width = 1200, height = 800;
var force = d3.layout.force().nodes(graph.nodes).links(graph.links)
.size([ width, height ])
.linkDistance(300)
.charge(-300)
.on("tick", tick)
.start();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// build the arrow.
svg.append("svg:defs").selectAll("marker")
.data([ "end" ]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
// add the links and the arrows
var path = svg.append("svg:g").selectAll("path")
.data(force.links())
.enter().append("svg:path")
.attr("class", "link")
.attr("source", function(d) { return d.source.id })
.attr("marker-end", "url(#end)");
// define the nodes
var node = svg.selectAll(".node").data(force.nodes())
.enter().append("g").call(force.drag);
// add the nodes
node.append("circle").attr("id", function(d) { return d.id })
.attr("fillColor", function(d) { return color(d.group); })
.attr("onmouseover", "selectLinks(this)")
.attr("onmouseout", "deSelectLinks(this)")
.attr("class", "node")
.attr("r", function(d) { return 3 * d.group })
.style("fill", function(d) { return color(d.group); });
// add the text
node.append("text").attr("x", 12)
.attr("dy", ".35em")
.attr("class", "text")
.text(function(d) { return d.name; });
// add the curvy lines
function tick() {
path.attr("d", function(d) {
var dx = d.target.x - d.source.x, dy = d.target.y - d.source.y, dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
});
</script>
</body>
</html>