obtaining data values on two different places within a webpage - javascript

I have a chart in this jsfiddle link
var data = [
[2,2],
[3,3],
[4,4],
[5, 4],
[5.5, 5],
[6, 6],
[6, 7],
[4,5],
[7,9],
[7,10]
];
How do I put the datapoints above the chart and create a link between the chart above and the chart below. I want to link the datapoints on the chart below with those on the chart above. i.e. one data source plotting data on two quadrants above and below. The first chart(chart above) must have only datapoints without lines. How do I achieve this ?

Here is a FIDDLE that implements what I mentioned in my comments with minimal changes to the code. However, I strongly suggest that you re-arrange the current code. Basically, you want to find what is common in the construction of both charts and factor out the code. (Also, the current code order is inverted because you first started with the lower chart and then decided on a second one to be located above the first.)
var chart2 = d3.select('#nolines')
.append('svg:svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom/4)
.attr('class', 'chart');

Related

d3.geoPath().projection is rendering black rectangle instead of map

I want to create a US map based on county data. I'm using this JSON topology data to create the graph: https://cdn.freecodecamp.org/testable-projects-fcc/data/choropleth_map/counties.json
In the first step, I created the map like this, and it works fine:
var path = d3.geoPath();
svgContainer.selectAll("path")
.data(topojson.feature(countyData, countyData.objects.counties).features)
.enter()
.append("path")
.attr("d", path)
Picture: US map renders OK but too large
However, it is too large for my purpose so I'm trying to scale it down. I tried projections which I saw in several other projects (for example here: https://www.d3-graph-gallery.com/graph/choropleth_basic.html). Unfortunately it just renders a black rectangle. I also tried geoAlbersUsa() and some other projections, but it did not help. How can I get the map data to scale?
var projection = d3.geoAlbersUsa() // geoMercator() also does not work
.scale(200)
.translate([width / 2, height / 2]);
var path = d3.geoPath().projection(projection);
svgContainer.selectAll("path")
.data(topojson.feature(countyData, countyData.objects.counties).features)
.enter()
.append("path")
.attr("d", path)
Picture: projection renders black rectangle
What am I doing wrong here?
Everything looks good in the second block of code (using d3.geoAlbersUSA()) except I think you are zoomed in too close with .scale(200) and only seeing the middle of a county. As explained in this post, if you zoom out with smaller scale value you may start to see more of your map.(What does it mean to scale a projection in d3?)
You may be better off using .fitSize() instead of .scale since you seem to be trying to fit the whole topojson data set inside an area rather than zooming into part of it. Updated your example below using a variable margin.
var margin = 20; //amount of whitespace you want around the map
var projection = d3.geoAlbersUsa()
.translate([width / 2, height / 2]);
var path = d3.geoPath().projection(projection);
var countiesFeatureCollection = topojson.feature(countyData, countyData.objects.counties);
//make the map projection fit into size of screen minus margin on all sides
projection.fitSize([width - margin*2, height - margin*2], countiesFeatureCollection);
svgContainer.selectAll("path")
.data(countiesFeatureCollection.features)
.enter()
.append("path")
.attr("d", path)

Legend colors do not always correspond to the values

This is the fiddle.
For some reason, the colors of some groups do not match the value of size.
For instance, I checked "name":"flare.analytics.cluster.AgglomerativeCluster","size"‌​:3938. In the drawing it's marked in "pink-red" color which corresponds to the legend > 5000 (scroll right to see the legend). According to my understanding it should be marked in the color of the legend 2000.
For some reason, the colors of some groups do not match the value of size.
Well, the explanation is simple: you're not using size as the variable to paint your links. Instead of that, you're using the length of the imports array inside each node:
.style("stroke", function(d){
return colorScale(d.target.imports.length)
})
And this is your domain:
[0, 2, 4, 6, 8, 10, 12]
Besides that, you're colouring by the length of the importarray of the target, not by the length of the import array of the node itself.

D3 pie chart transition

I'm studying transitions in D3js, trying to get them working with a simple pie chart that is derived from a Mike Bostock example.
I want to transition the data in the pie from data to data2, but the chart does not update.
This is the transition statement:
path.selectAll("path").data(pie(data2)).transition().duration(2000);
What am I missing?
EDIT
I've got it working with the below. Now I'd like to understand why this is working. I understand the .attr("d",arc) part, but why do I need to selectAll("path")?
path.selectAll("path").data(pie(data2)).transition().duration(2000).attr("d",arc);
END EDIT
The complete code (JSFiddle here):
var width = 200,
height = 200,
radius = Math.min(width, height) / 2;
var color = d3.scale.category20();
var data = [2, 19, 18, 99, 100];
var data2 = [100, 1200, 20, 88, 12];
var pie, arc, svg, path, data;
var chartCanvas = d3.select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
var path = chartCanvas
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
function setupPieChart() {
pie = d3.layout.pie()
.value(function (d) {
return d;
})
.sort(null);
arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 20)
path
.selectAll("path")
.data(pie(data))
.enter()
.append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc)
.each(function (d) {
this._current = d;
}); // store the initial angles
console.log(path);
}
setupPieChart();
console.log(path);
path.selectAll("path").data(pie(data2)).transition().duration(2000);
.transition starts a transition for the attributes change(s) declared after it. You don't set / do anything after .transition, so there is nothing to interpolate over. In the original example from Mike, you'll see he sets the d attribute after starting the transition, specifying a custom interpolator (arcTween)
I immediately see you are missing some important part of the update process. You copied the original code, but you forgot the update part :-). I can tell, because I see in your code you store the initial angles.
Look again at the code here and try to understand the function arcTween. More information can be found here. You need an arc tween function to calculate the new angles based on the initial angles (which is why you stored the initial angles in the first place :-).
I won't do the fiddle at the moment, cause in my experience, you learn more if you try to understand the arc tween function (as I did here . This is a link to a personal project of mine, but feel free to copy code as you see fit).
You need to .selectAll("path") as those are the actual elements that will update. When doing d3, try to think of the chart elements as following: Elements that are not visible yet (which is enter collection), elements that are visible now (which can be seen as the update collection) and elements that can be removed (the exit collection).
You need to see those elements based on the data you want to visualize. D3 is data driven documents, so everything is in relation to the data you want to show on the screen: if you have data but no elements yet, you do an "enter" of elements. So you do a selection of elements that are not in the DOM yet, but will soon be, because you will bind them to the data you have.
If you already have elements on the screen, and the number of elements matches the data you need to show (for example: var data = [20 ,30 , 40], you got 3 pieces of data here for 3 div's on the screen, you got a matching amount), then d3 will update your selection (hence the update collection or update selection) so the elements properties match the data.
If you have more elements on the screen then there is data to show, then you can do an exit of elements (again, hence the exit selection or collection). I hope that made it a bit more clear and that it made sense as well :-)

Get values from D3 line interpolator functions

I am building a D3 graph which contains a shaded region in the middle of it. The shaded regions top part matches the line graph.
The data looks something like this:
line = [
{x: 0, y:1},
{x: 1, y:2},
{x: 2, y:4},
{x: 3, y:6},
{x: 4, y:3},
{x: 5, y:1}]
And the graph uses a 'cardinal' interpolation function:
g = d3.svg.line()
.interpolate('cardinal')
In order to shade the area under the graph, I just create a d3.svg.area() and provide it with the equivalent data for the shaded area, e.g (to shade between x=2 and x=4):
area = [
{x: 2, y:4},
{x: 3, y:6},
{x: 4, y:3}]
a = d3.svg.area()
.interpolate('cardinal')
, but my problem is that I want to shade the area under the graph between 1.5 and 3.5 for which I dont know the values after the 'cardinal' interpolation has taken place.
So, I need to work out how to either a) apply a cardinal interpolation over the data and then pick out the values for 1.5 and 3.5 or b) extract the line data from d3 and use that to build up the data for the area graph.
for a) I have looked at d3.interpolate, but it looks like its different from d3.line.interpolate() and does not allow you to pass the interpolation method.
for b) I cant work out how to extract the data from the line once it has been interpolated... its not documented anywhere in D3.
Consider approaching this in a different way: you can use svg clipPath elements to arbitrarily clip a path, allowing you to forego any calculation of interpolated values.
Draw two versions of your area, one with the background styling, the other with the foreground, then create a rectangle clipPath element to bound the 'foreground' area:
js:
svg.append("clipPath")
.attr("id", "clipRect")
.append("rect")
.attr("x", x(1.5))
.attr("width", x(2))
.attr("height", height);
css:
.foreArea {clip-path: url(#clipRect);}
See, for example: http://bl.ocks.org/jsl6906/89ef40de1d8808d04f42

JS:Specific weight chart

Firstly to understand my issue you should see the pricture in the link below :
http://www.hostfile.nl/fpimages/03bkr5tq46/16043/screenshot.jpeg.html
The idea and my issue is to create a chart of weight such as the picture or the site http://www.loseit.com/#Goals , the description is like this :
1- the chart contain two lines : 1 - Record Today's Weight , 2- My goal weight.
2- so I can record everyday my today's weight and when I click "record" button directly I see new line is added in chart in the space of today (you can see the picture )
what I need is an example or code of chart do almost the same fonctionality,really I'm not professional in javascript code?
You can use Flot (JavaScript library for jQuery to generate charts)
// a null signifies separate line segments
var myData = [[0, 12], [7, 12], null, [7, 2.5], [12, 2.5]];
var myGoal = [[0, 20], [12, 20]]
$.plot($("#myChart"), [ myData, myGoal ]);
check out this example : https://refork.codicode.com/xa2e

Categories