Adding fisheye to axes with D3 JS - javascript

I have this visualization and I'm trying to add fisheye view to the chart. I have tried adding it with the following lines in the plotData function but it doesn't happen:
var fisheye = d3.fisheye.circular()
.radius(120);
svg.on("mousemove", function () {
fisheye.focus(d3.mouse(this));
circle.each(function (d) {
d.fisheye = fisheye(d);
});
});
Any ideas on how to solve this?
Thanks!

First things first, your d3.timer never stops running. This is driving my machine crazy (cpu 100%) and killing the performance of the fishey. I'm really not sure what you are doing there, so ignoring that for a moment.
Your fisheye needs a little massaging. First, it expects your data pixel's positions to be stored in d.x and d.y attributes. You can fudge this in with when drawing your circles:
circle
.attr("cx", function(d, i) { d.x = X(d[0]); return d.x; })
.attr("cy", function(d, i){ d.y = Y(d[1]); return d.y; });
Second, you are plotting your data in multiple steps, so you need to select all the circles for the fisheye. And third, you forgot the code that actually makes the points grow and shrink:
svg.on("mousemove", function () {
fisheye.focus(d3.mouse(this));
// select all the circles
d3.selectAll("circle.data").each(function(d) { d.fisheye = fisheye(d); })
// make them grow and shrink and dance
.attr("cx", function(d) { return d.fisheye.x; })
.attr("cy", function(d) { return d.fisheye.y; })
.attr("r", function(d) { return d.fisheye.z * 4.5; });
});
Updated example.

Related

D3 JS - How to draw horizontal force graph

I am trying to create a force graph as shown in below image. I am checking the graph given at this link force tree. This tree is vertical. I want it horizontal so that I can achieve the graph shown in the image. I tried to play with the code but was not able to make it horizontal. Is there any way I can achieve the graph shown in the image.
desired force graph
Turning the tree horizontal is actually quite simple in the given example.
The tick function is responsible for assigning positions to each node, and it modifies the y value of the nodes between levels. Simply change it to modify the x value of the nodes.
Like so:
function tick(e) {
var k = 6 * e.alpha;
// Push sources up and targets down to form a weak tree.
link
// Swapped here from y to x
.each(function(d) { d.source.x -= k, d.target.x += k; })
.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; });
}

Making d3 v4 group react to simulation

jsfiddle https://jsfiddle.net/z7ju3z1q/3/
The problem is, I can't make titles stick with groups with working simulation.
Changing line 76 from simulation.nodes(nodes); to simulation.nodes(node); breaks simulation (apparently), but makes title stick to circles. As I understand, the problem is that dragging working with circles but not with groups, for some reason. And that's is the problem Iwe been facing whole day.
I tried describing title like this (line 38)
var title = g.selectAll("text");
And then adding it to tick (line 84)
function ticked() {
title.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
}
As I understand, the problem is that dragging working with circles but not with groups, for some reason
You are manipulating the nodes on drag with cx and cy properties. g elements do not have these, so this will not achieve what you want, even if node contained groups rather than circles:
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
As noted,node = g.append("circle") means that you aren't actually manipulating the g elements anyways, which is why your circles move on tick or drag.
Instead, keep node a selection of g elements, and manipulate the transform property:
// the group representing each node:
node = node.enter().append("g").merge(node);
// the circle for each group
node.append("circle")
.classed('node', true).attr('id', id)
.text(id)
.attr("r", 25).attr("fill", function(d) { return color(d.id); });
// the text for each group
node.append("text")
.classed('text', true)
.attr("text-anchor", "start")
.attr("dx", 6).text(id).merge(node);
Then, on click or drag events, just update the transform:
Tick:
node.attr("transform",function(d) { return "translate("+d.x+","+d.y+")" ;});
Drag:
d.x = d3.event.x;
d.y = d3.event.y;
d3.select(this).attr("transform",function(d) { return "translate("+d.x+","+d.y+")" ;});
Here's an updated fiddle.

Color specific point in beeswarm d3js (v.4 alpha)

guys, I am working with the most recent beeswarm visualization by Mike Bostock.
I wonder, in D3js v.4, how to change the color of one single specific point. In this case, I am talking about unemployment in more than 180 countries, and I would like to single out only "Brazil" with a different color.
How can I pick Brazil's dot and make it with a different color? As last resort, I suppose I could use SVG to single it out, but its to big a code, burden. I am fairly new to D3.
Here is the code: http://codepen.io/voltdatalab/pen/KzrNGo
var cell = g.append("g")
.attr("class", "cells")
.selectAll("g").data(d3.voronoi()
.extent([[-margin.left, -margin.top], [width + margin.right, height + margin.top]])
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.polygons(data)).enter().append("g");
cell.append("circle")
.attr("r", 5)
.attr("cx", function(d) { return d.data.x; })
.attr("cy", function(d) { return d.data.y; })
;
Here is what I want to do:
I did this manipulating the SVG, not D3 code
You need to add .attr("fill",function(d) { if(d.data.id === "Djibouti")return "red"; }) to circle. Following is the change you need to make:
cell.append("circle")
.attr("r", 5)
.attr("cx", function(d) { return d.data.x; })
.attr("cy", function(d) { return d.data.y; })
.attr("fill",function(d) { if(d.data.id === "Djibouti")return "red"; })
;
Replace Djibouti with Brazil.
Here is a bin. Let me know if you want something like this.

Old scaled data fail to disappear after axis rescale

Using D3 ver 3.5.5. I am using an example (https://gist.github.com/stepheneb/1182434) as a template: the example code to draw the data looks like this:
var circle = this.vis.select("svg").selectAll("circle")
.data(this.points, function(d) { return d; });
circle.enter().append("circle")
.attr("class", function(d) { return d === self.selected ? "selected" : null; })
.attr("cx", function(d) { return self.x(d.x); })
.attr("cy", function(d) { return self.y(d.y); })
.attr("r", 10.0)
.style("cursor", "ns-resize")
.on("mousedown.drag", self.datapoint_drag())
.on("touchstart.drag", self.datapoint_drag());
circle
.attr("class", function(d) { return d === self.selected ? "selected" : null; })
.attr("cx", function(d) {
return self.x(d.x); })
.attr("cy", function(d) { return self.y(d.y); });
circle.exit().remove();
I think of this as four sections: the first does selectAll("circles") and adds the data. The second tells where the data points are ("cx", "cy") and other attr(), and the third is a bit of mystery to me, because it appears to also set "cx" and "cy", but no other attributes. Finally, we do and exit().remove(), which the documentation says removes any data elements not associated with the data array. I dont see how this is happening in this example. When I set breakpoints into the code, both the "cx" steps get called for each data point in the this.points array.
In my code, I try to do the same steps:
hr_circles = self.graph_gps.svg.selectAll("hr_circles")
.data(self.graph_gps.datay1); // , function(d){return d;}
hr_circles.enter().append("circle")
.style("z-index", 3)
.attr("class", "y1")
.attr("r", 1)
.attr("cx", function (d, i) {
return xScale(d.time)
})
.attr("cy", function (d, i) {
return yScale(d.vy)
})
.on("mouseover",
function (d) {...displays a tooltip...})
.on("mouseout", function (d) {
});
hr_circles.attr("class", "y1")
.attr("cx", function (d, i) {
return xScale(d.time)
})
.attr("cy", function (d, i) {
return yScale(d.vy)
})
hr_circles.exit().remove();
When my graph initially displays, the data appear just fine, properly scaled, etc. When I try to re-scale by dragging on the x-axis (as in the example), the axis rescales itself just fine, and re-scaled data appears on the graph, but the original data is also still there (no longer scaled correctly), making a big mess! How do you erase or make the originally scaled data go away?
Tried to post images, but I guess my reputation is too low. Will send to anyone interested.

D3 Multiline Chart with Tooltip Transition Issue

I have been using d3 to create a multiline chart with focus and context brushing. Everything is going well except on the transition the dots at the data points with the tooltips are moving to a completely wrong position. I can't figure out what is causing this. Any help would be much appreciated. I attached the full code here and noted on the graph where I'm pretty sure the bug should be:
http://jsbin.com/osumaq/20/edit
When the button is clicked, a new json is passed to the graph to read.
The buggy block of code I think is this:
topicEnter.append("g").selectAll(".dot")
.data(function (d) { return d.values }).enter().append("circle").attr("clip-path", "url(#clip)")
.attr("stroke", function (d) {
return color(this.parentNode.__data__.name)
})
.attr("cx", function (d) {
return x(d.date);
})
.attr("cy", function (d) {
return y(d.probability);
})
.attr("r", 5)
.attr("fill", "white").attr("fill-opacity", .5)
.attr("stroke-width", 2).on("mouseover", function (d) {
div.transition().duration(100).style("opacity", .9);
div.html(this.parentNode.__data__.name + "<br/>" + d.probability).style("left", (d3.event.pageX) + "px").style("top", (d3.event.pageY - 28) + "px").attr('r', 8);
d3.select(this).attr('r', 8)
}).on("mouseout", function (d) {
div.transition().duration(100).style("opacity", 0)
d3.select(this).attr('r', 5);
});
Thank you very much.
What do you mean by tooltip ? Is it the window that appears when we hover on dots ? They seem fine. What I can see is that your dots are not moving while the lines are, and if I had to guess I would say your enter and update selections are mixed. If the dots are already on screen and you want to update their position (by calling your method update) you should have somthing along these lines :
// Bind your data
topicEnter.append("g").selectAll(".dot")
.data(function (d) { return d.values })
// Enter selection
topicEnter.enter().append("circle").attr("clip-path", "url(#clip)").attr("class", "dot");
// Update all the dots
topicEnter.attr("stroke", function (d) {
return color(this.parentNode.__data__.name)
})
.attr("cx", function (d) {
return x(d.date);
})
.attr("cy", function (d) {
return y(d.probability);
})
[...]

Categories