d3.js - translating multiple labels without rotation - javascript

I'm relatively new to d3 and am attempting to augment a radar diagram such that it rotates on click and the next axis points directly upwards.
The example in which I am working from is found here.
Problem
Currently, when the svg is clicked, I rotate the entire svg by a specified angle based on the number of axis there are in the graph. Since I am rotating the entire svg the labels that are appended to each axis will rotate also (as shown in the following image).
The text is currently unreadable and I want to achieve a solution which is more similar to the following image:
I would like each label to stay with their respective axis and also stay upright after the svg has been rotated, but I am finding it hard to achieve this.
JSFIDDLE
This JSFIDDLE is the stripped down code of the current implementation (I left out the numerous failed attempts) and the following code, which would be in the 'rotateOnClick' function is the closest I have came to a solution so far (I haven't used the index i variable so far but my intention was to swap the position of labels with each other when clicked).
g.selectAll(".legend")
.transition()
.duration(cfg.rotateDuration)
.attr("transform", function(d, i){
if (i<total) i++;
else i = 0;
return "rotate("+newAngle*-1+", "+(cfg.w/2)+",0 )"
})]
.ease(cfg.easeFunction);
I need to manipulate each label individually and stay aligned with its respective axis and also for it to work with a dynamic number of axis.
I greatly appreciate any help and insight.

Related

Updating D3.js graph on mouseover event

I’m new to to d3 and have combined mbostock’s stacked bar graph example ( http://bl.ocks.org/mbostock/3886208 ) with a map to show data (canada.json)
I would like the graph to display an updated chart on the d3.mouseover event of the province:
http://gao8a.github.io/ (something like this)
Unfortunately, I was only able to get the axises to display. It's showing either multiple or the same axis overlapping:
(These will take ~ 3 seconds to load)
Multiple:
http://bl.ocks.org/GAO8A/566e238a72e5ebd1e2c1
Same Axis overlap
http://bl.ocks.org/GAO8A/64f94bb494c4a73f2bf6
I understand I probably need a ‘mouseout’ event to delete the previous but I’m not quite sure how to design that either.
Can anyone point out what I’m doing wrong and how I should be loading the data?
PS:
I was going to make a jsfiddle but can’t seem to get it to get it to work with my hosted canada.json data.
https://raw.githubusercontent.com/GAO8A/GAO8A.github.io/master/canada.json
Thanks
Your issue is that you keep adding the axes in the tooltip element. Unfortunately this creates the overlaps. What you could do is add the axes once, and the readjust their domain with the new values that correspond to the element being hovered.
So in essence if you could add the following lines:
var X_AXIS = tooltip.append("g").attr("class", "x axis x-axis").attr("transform", "translate(0," + height + ")");
X_AXIS.call(xAxis)
X_AXIS.append("text").attr("dy", "3em").attr("dx", "50em").style("text-anchor", "end").text("Month");
var Y_AXIS = tooltip.append("g").attr("class", "y axis y-axis")
Y_AXIS.call(yAxis)
Y_AXIS.append("text").attr("transform", "rotate(-90)").attr("dy", "-3em").attr("dx", "-8em").style("text-anchor", "end").text("Temperature (Celcius)");
just before adding your map, this would in a sense 'initialize' the axes.
So further, in your mouseover handler, you could add the following lines, just after you determine your x and y domains.
X_AXIS.call(xAxis)
Y_AXIS.call(yAxis)
or better still, to add some transition:
X_AXIS.transition().duration(400).call(xAxis)
Y_AXIS.transition().duration(400).call(yAxis)
This way, you don't keep adding axes, you just readjust the ones currently intialized.
Hope this helps.

D3 Focus+Context via Brushing not displaying scatterplot

I'm trying to replicate this Focus+Context via Brushing example. I'm including the same layout, but with a scatterplot instead of a line/area plot.
I started working off this example I found which combines the area plot and a scatterplot. However, when I scrap the area plot, I lose the zoom/focus capability.
My last step (thus far unsuccessful) is to make the brush (small focus bar on the bottom) actually respond to the main panel (make it adjust/zoom in when smaller time periods are selected in the brush). The brush adjusts the axis as it should, but I just haven't been able to make the brush actually adjust/zoom the points on the main scatterplot. I'm not trying plot anything in the brush - there will be a lot of points, so keeping the brush with a grey background and no points is fine.
here's my fiddle: http://jsfiddle.net/fuqzp580/3/
Sidenote: I can't quite get the jsfiddle to work with the way I'm using d3.csv, so I coded up a slightly altered version with dummy data in lieu of using d3.csv. However, I included the d3.csv code (commented out), just in case that could be a cause for my problem.
I'm new to d3 so any pointers or ideas welcome!
Here's an updated fiddle with the dots zooming on the points in the main panel: http://jsfiddle.net/henbox/3uwg92f8/1/
You were very close, I just made 3 small changes:
Firstly, uncommented the code you already had in function brushed() for selecting the dots
Secondly, defined mydots globally (since you were only doing it inside initialize() and it needs to be used beyond this scope). Added this on line 55:
var mydots = focus.append("g");
And last (and most importantly), I changed the definition for xMap from
xMap = function(d) { return x2(d.time); }
to
xMap = function(d) { return x(d.time); }
When brushing, it's the x scale that gets updated, not the x2

Tipsy tooltip attached on circle's upper left corner using d3

When I use tipsy on my d3 force directed graph I have a problem: when I set the tipsy gravity to west, the tipsy begins at the upper left corner of my circle. How can I make it begin on the right side of my circle?
Here is the sample of the code I use in d3:
var node = vis.selectAll("g.node")
.data(json.nodes)
.enter().append("svg:g");
node.append("svg:circle")
.attr("r", function(d){return d.credits *5+"px";})
.style("fill", "orange");
$('svg circle').tipsy({
gravity: 'w',
html: true,
title: function() {
var d = this.__data__,
name = d.name;
return name;
}
});
Edit In this question: https://stackoverflow.com/a/10806220/1041692 they say the following:
You could try adding the tooltip to an svg:g that you overlay with the
actual circle, but give zero width and height. Currently it's taking
the bounding box and putting the tooltip at the edge. Playing around
with tipsy's options might help as well.
But either I do it wrong or it doesn't work, it didn't solve my problem.
EDIT 2 This problem also depends on the browser, in chrome the tipsy element is attached on the top left corner of the circle whereas I would like it to be attached on the middle of the right side of the circle. In Firefox, the tipsy appears on the top left of the whole webpage.
The D3 tipsy tutorial actually uses a modified version of tipsy:
http://bl.ocks.org/1373263
It is slightly tweaked to correctly calculate bounding boxes of SVG elements. So copy that source code, rather than using tipsy downloaded from the tipsy site.

How do i properly get attributes from another object? Trying to create a tooltip for my raphael animation

So, basically I have a piechart drawn with Raphael. Each segment corresponds to a different value and I want to have a unique tooltip popup for each segment. In this example I am trying to draw a circle every time one of the segments are hovered, but I can't figure out a way to do it dynamically so that I can set the position point relative to the segment that is being hovered. Sorry for poor and convoluted explanation, but you can see the example of my code here:
http://jsfiddle.net/DgrgC/2/
Thanks for your help!
Inside the hover callback, this refers to the current path you're drawing. So this.attrs contains the path attributes. Note that paths don't have cx and cy attributes, as you're trying to access in you example.
I'm not sure what you're trying to accomplish, but you can check my example on how to draw some circles based on path data:
http://jsfiddle.net/DgrgC/3/
Basically:
this.attrs.path[1] //second point of the path
this.attrs.path[1][1] //x coordinate of this point
this.attrs.path[1][2] //y coordinate of this point

gRaphael line chart shade changes

I'm currently implementing a line chart in gRaphael which requires the x axis to move up the y-axis such that it lies on zero (which I have already accomplished by drawing my own axes).
However, I'm now encountering a problem when attempting to shade the area above/under the x-axis; gRaphael's shade function only shades from the bottom of the graph to Y-height (as opposed to being from 0 on the y-axis to the y-height). The result is the following:
http://i.stack.imgur.com/ZuPhw.png
I have found a couple of lines in g.line.js which look suspiciously like they would help, but I have no idea what the "L", "C", and "M" values mean (I assume they are to tell a part of the program to draw a line etc?)
Any help from anybody more informed than me would be greatly appreciated!
I solved this by overriding the g.line.js file and creating an offset to add to the Y values. The offset was calculated by considering the maximum and minimum values on the Y axis, the height of the SVG itself and the "gutter" - a value which adds padding to the SVG itself (so that values on the axes can be displayed better). The formula looks like this (and is, incidentally, identical to how the axes were moved to zero):
(height - 2*gutter)*(miny/(maxy-miny))

Categories

Resources