Plotting points using d3.geo.tile - d3.js

I've been extending the code in this example:
http://bl.ocks.org/mbostock/5914438
But I can't seem to figure out how to place points on this map in a manner in which they can be integrated in the zoom. Paths work fine but it seems like the modified projection can't be used to project the coordinates of the points, and in the zoomed function, the scale() addition to the transform() when applied to the element containing the points seems to scale the points so large that they fill the entire screen. Here's my additional points:
var sitesG = svg.append("g").attr("id","sitesG");
var osites = sitesG.selectAll(".sites")
.data(sites)
.enter()
.append("g")
.attr("transform", function(d) {return "translate(" + projection([d.x,d.y]) + ")scale(" + projection.scale() + ")"})
osites.append("circle").attr("r", 10)
And here's the function in zoomed():
d3.select("#sitesG")
.attr("transform", "translate(" + zoom.translate() + ")scale(" + zoom.scale() + ")")
I've tried this with individual elements for the sites as well, but with no success. Does anyone have an example that puts points on geo.tile?

I managed to figure it out. My main problem was that I was not scaling the "r" attribute of the circles to match the zoom.scale() when I was properly projecting the points, which caused them to have 13,000px+ radii.
You can see it working here:
http://bl.ocks.org/emeeks/6147081

Related

d3.js Attributes, Transform, Translate when using polylines

My code is safely stored on my bl.ocks site
I've effectively converted a scatter plot into a hexagon plot by defining a polyline shape with 6 edges and referencing HEX in the code instead of circle. However, my scatter plot started neatly at (0,0) on the origin of my graph scales. My hex plot starts offset by -50,-20 and I can't find a way around it to revert it back to (0,0).
Here is the scatter plot code for info
You need to remove the transform on this line.
svg.append("g")
.attr("class", "path.hex")
.attr("transform", "translate(50, 20)")
.call(hex);
And potentially the 50,20 translating on this line (I think you may still need the scales)
hexs.attr("transform", function(d) {
return "translate(" + xScale(d.Board) + 50 + "," + yScale(d.Alight) + 20 + ")" + " scale(" + rScale(d.Totals) + ")"
})

How to create Stacked Line Chart D3, Multiple Y Axis and common X Axis

I am triying to create a line chart which will have multiple y axis but a common x axis using d3, can somebod provide me the example how to create it with D3 library. It should be something like as shown below
Quite simply: Just draw 2 charts but only append one x-axis, here's a fiddle to get you started: http://jsfiddle.net/henbox/fg18eru3/1/
In this example, I've assumed that the two different datasets have different y-domains but the same x-domain. If that's not the case, you should just get the max and min from the combined x-domains of both sets.
If you start by defining 2 g elements that will contain the two charts, and transforming the bottom chart down so they don't overlap:
var topchart = svg.append("g").attr("class", "topchart");
var bottomchart = svg.append("g").attr("class", "bottomchart")
.attr("transform", "translate(0," + height/2 + ")");
... then append the path and y-axis to the appropriate g, but only add the x-axis to the bottom chart:
bottomchart.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + (height/2 - padding) + ")")
.call(xAxis);

Graph ~ axis alignment issue

I'm currently working on a quite basic graph using 2 ordinal axes. X axis shows 4 categories, Y axis shows 3. For some reason, the plotted circles don't align with the plotted axes.
An example can be seen at http://jsfiddle.net/SrdY6/. Problem seems to be translation-related, but the only translation in there is applied to the large containing <g> element:
var lunchgraph = svg.append("g")
.attr("class", "lunchgraph")
.attr("transform", "translate(" + lunchmargin.left + "," + lunchmargin.top + ")");
I've been looking at this for some time now, but can't spot where things go wrong... Anyone with more insight?
Nothing like putting a question out there and risking public shame, only to find out the answer within minutes after posting.
For ordinal axes configured with rangeBands or rangeRoundBands, the scale function returns the lower value of the given input. To have the plot align with the exact categorical labels, you need to add half of the rangeBand to the calculated coordinate.
So: no problem with the translations or anything, but with the computation of cx and cy coordinates for placing the circles in the graph.
Correct code:
.attr("cx", function(d) { return x(d.label) + x.rangeBand()/2 ;} )
.attr("cy", function(d) { return y(d.sqid) + y.rangeBand()/2 ; } )

d3 issues with entering elements after pan

I use a transform when panning, copied from several examples.
zoom = d3.behavior.zoom()
.x(this.xScale)
.scaleExtent([0.5, 2])
.on("zoom", zoomFunction(this))
.on("zoomend", zoomEndFunction(this));
svg = histogramContainer.append("svg")
.attr('class', 'chart')
.attr('width', width)
.attr('height', height)
.call(zoom)
.append('g')
.attr('transform', 'translate(' + this.margin.left + ' , ' +
(height - this.margin.bottom) + ')');
function zoomFunction(scope) {
return function() {
var that = scope;
that.xDelta = d3.event.translate[0];
that.zoomScale = d3.event.scale;
// some other code removed for simplicity
svg.selectAll(".stackedBar").attr("transform", "translate(" +
that.xDelta + ",0)scale(" +
that.zoomScale + ", 1)");
};
}
The problem is that since new elements enter after the pan then 'old' elements have the transform attribute applied but the new elements don't.
This breaks future panning because the old elements will be transformed from where the pre-zoom xScale drew them while the new elements will be transformed from the zoom-adjusted xScale.
It seems to me that I could redraw the old elements with the zoom-adjusted xScale, though I'm unsure when and how to do that "behind the scenes".
Alternatively I could draw the new elements with the old xScale and apply the same transform on them that the old elements have. This seems messier since elements will come and go and I'll have to keep track of the 'current transform'. My gut tells me "too much state".
Usually if you're attaching a scale to the zoom behaviour, you use the modified scale to redraw the bars using the exact same code as how you position the bars initially, letting the scales do all the work.
I linked to this discussion in my previous answer, so you might have read it by now; if not, it might be a good start for getting your head around the different ways of approaching zooming in d3; it breaks down the each method step-by-step. You're currently using a mix of two approaches (transforms versus scales), and I think that's causing problems keeping track.

How to scale and translate together?

I want to scale and translate D3 force graph, both at the same time. E.g. On clicking a button it shoud scale to 400% and then make itself center on the screen. This should all happen with a smooth animation effect.
//animate vis to visible area
vis.transition()
.duration(2000)
.attr("transform", "scale(" + someScaleValue + ")" + "center("0,0)");
Doing this, scaling works fine, but graph is not centered. It shifts towards right-bottom corner.
vis.transition()
.duration(2000)
.attr("transform", "scale(" + someScaleValue + ")");
Why is scale is getting reset to 100% when I translate it second time.
I also tried using:
vis.transition()
.duration(2000)
.attr("transform", "scale(" + scaleValue + ")" + "translate(0,0)");`
This is not working too. Please help me.
center(0,0) is not a valid transform-definition to be used with transform, as per the spec.
If you want translate(0, 0) to take the object to the center of the screen (usually the top-left corner of vis), then you might want to set viewBox of the outer svg element to be: "-width/2 -height/2 width height". This would set the co-ordinate system inside the svg element such that the center lies at (0, 0). Alternatively, you can use translate(width/2, height/2).
Also, each time you call .attr('transform', ...), you overwrite the old value of the transform attribute. This is the possible reason why you are losing the original scaling on translating. The best solution would be to put the vis element inside a g which has the scaling in the transform attribute which remains constant.

Resources