I've been wrestling with this problem for quite a while now. I want to create an x-axis, so I used the following code:
var w = 1024,
h = 1024,
padding = 20,
fill = d3.scale.category20();
var vis = d3.select("#chart")
.append("svg:svg")
.attr("width", w)
.attr("height", h);
d3.json("force.json", function(json) {
//Create array of dates for the x-axis
var dates = json.nodes.map(function(d) {
return Date.parse(d.date);
});
console.log(dates)
// Create scale from the array of dates
var scale = d3.time.scale()
.domain(dates)
.range([padding, w - padding]);
console.log(scale(dates));
var axis = d3.svg.axis();
//more code below, but error gets called at the line above this comment.
}
However, I get the following error returned consistently:
Uncaught TypeError: Object #<Object> has no method 'axis'
This is very perplexing, as I was simply following the d3 API at https://github.com/mbostock/d3/wiki/SVG-Axes.
Would somebody kindly point out where I'm going wrong?
(for reference, force.json is the data I am working with)
Related
I am trying to make some features from a .geojson file render using D3 and D3geo and i am following this https://www.d3indepth.com/geographic/ as a guide. I don't really know what i am doing since i am not good at programing. It shows no errors on devtool console and when i inspect it in chrome it shows that the paths are created but the are not showing.
here is my code, the js part:
var width = Math.max(
document.documentElement.clientWidth,
window.innerWidth || 0
);
var height = Math.max(
document.documentElement.clientHeight,
window.innerHeight || 0
);
d3.json("2022.json").then(function (data) {
let geojson = data;
console.log(data);
let projection = d3
.geoMercator()
//.scale(1000)
//.center([20, 40])
//.translate([456, 250]);
projection.fitExtent([width, height], data);
let geoGenerator = d3.geoPath().projection(projection);
function update(geojson) {
let u = d3
.select("#content")
.data(geojson.features)
.enter()
u.append('path')
.join("path")
.attr("d", geoGenerator);
}
update(geojson);
});
enter image description here
I've built a line-graph in dimple.js that can be found here. http://jsfiddle.net/lukehtravis/0twgc2uL/
You'll notice on the y-axis, there is a little "m" that is automatically generated by dimple and placed next to the numbers as a quantity label.
I combed through the documentation, but couldn't find anything about that little m.
Anyone know how to remove it? Here's the code
// Create the canvas to draw on
var svg = d3.select("#charty")
.append("svg")
.attr("width", 800)
.attr("height", 500);
// Create the chart object | contents of data visible in fiddle link above
var chart = new dimple.chart(svg, data);
//Create the x axis
var x = chart.addCategoryAxis("x", "Day");
x.showGridlines = true;
// Create the y axis
var y = chart.addMeasureAxis("y", "Volume");
y.title = "Volume (AF)";
y.overrideMin = 300000;
y.overrideMax = 1450000;
y.showGridlines = true;
// Add location as data series
var series = chart.addSeries("Location", dimple.plot.line);
// Decorate the lines in the graph
series.lineWeight = 2;
series.lineMarkers = true;
// Create the legend
chart.addLegend(100, 50, 200, 200);
// Draw the chart
chart.draw(3100);
Small m is not but conversion of units into million..
0.3million is your value 300000 .. Its pretty normal and not an error ..
If you dont want that then just add this line y.tickFormat = "1f"; after
y.showGridlines = true;
I am following this tutorial for a fore-directed graph, http://bl.ocks.org/mbostock/1153292. I was wondering, how do you pass meta-data / user defined data to the d3 node and keep it around for later actions.
Example:
A user clicks on a node, and a table appears with the relevant meta-data attached to the node, such as label, alerts, comments, and other data that is not specifc to the d3 node/edge architecture.
You can pass whatever data you need to d3 and it will automatically store it on the node based on the nodes data function. Whether you use that data to populate nodes and edges is really up to you.
Here's a basic pie chart (note I'm leaving out the pie and arc definitions for brevity). In this example, data contains the information needed to build the pie chart. These get initially stored on the svg node and then each array element gets stored on the corresponding arc node. This data can contain whatever information you want. I use it to store a name and css class that I then apply to the pie wedges. However it can contain as rich of data as you need.
var data = [
{ name: 'Schedule slip', classname: 'c', value: 5},
{ name: 'Slightly behind', classname: 'b', value: 10},
{ name: 'On track', classname: 'a', value: 20}
];
// select the svg element if it exists
var svg = d3.selectAll('svg').data([data]);
// otherwise create the skeletal chart
var svgEnter = svg.enter().append('svg');
// chart skeleton
var gEnter = svgEnter.append('g').attr('class', 'donut');
gEnter.append('g').attr('class', 'arcs');
// Dimensions
var width = (2 * outerRadius) + margin.left + margin.right,
height = (2 * outerRadius) + margin.top + margin.bottom,
hCenter = width/2,
vCenter = height/2;
svg
.attr('width', width)
.attr('height', height)
.select('.donut')
.attr('transform', translate(hCenter, vCenter));
// draw the arcs
var arcs = svg.select('.arcs').selectAll('.arc')
.data(pie); // compute pie wedge info and store it in arc node
var gArc = arcs.enter().append('g').attr('class', 'arc');
gArc.append('path').each(function(d) { this._current = d; });
arcs.exit().remove();
arcs.select('path')
.attr('class', function(d) { return d.data.classname; })
.transition().duration(500)
.attrTween('d', arcTween);
I have edited this question a little bit from when I posted it. Here is the new code:
Here is my code:
var elementTags = ["Google", 4, "Wikipedia", "Yahoo!", "Cindy"];
var _s32 = (Math.sqrt(3)/2);
var A = 75;
var _counter = 0;
var xDiff;
var yDiff;
var pointData = [[A+xDiff, 0+yDiff], [A/2+xDiff, (A*_s32)+yDiff], [-A/2+xDiff, (A*_s32)+yDiff], [-A+xDiff, 0+yDiff],
[-A/2+xDiff, -(A*_s32)+yDiff], [A/2+xDiff, -(A*_s32)+yDiff], [A+xDiff, 0+yDiff]];
var svgContainer = d3.select("body") //create container
.append("svg")
.attr("width", 1000)
.attr("height", 1000);
var enterElements = svgContainer.selectAll("path.area") //draw elements
.data([pointData]).enter().append("path")
.style("fill", "#ff0000")
.attr("d", d3.svg.area());
What I want to do is create a new hexagon for each elementTags value. Each new hexagon should have a randomized xDiff and yDiff, and each time the value of _counter should go up by 1.
You need to use loop. Here is a modified code:
var elementTags = ["Google", 4, "Wikipedia", "Yahoo!", "Cindy"];
var _s32 = (Math.sqrt(3)/2);
var A = 75;
var svgContainer = d3.select("body") //create container
.append("svg")
.attr("width", 1000)
.attr("height", 1000);
for (index = 0; index < elementTags.length; index++) {
var xDiff = Math.random()*100+100;
var yDiff = Math.random()*100+100;
var pointData = [
[A+xDiff, 0+yDiff]
, [A/2+xDiff, (A*_s32)+yDiff]
, [-A/2+xDiff, (A*_s32)+yDiff]
, [-A+xDiff, 0+yDiff]
, [-A/2+xDiff, -(A*_s32)+yDiff]
, [A/2+xDiff, -(A*_s32)+yDiff]
, [A+xDiff, 0+yDiff]
];
var enterElements = svgContainer.selectAll("path.area") //draw element
.data([pointData]).enter().append("path")
.style("fill", "#ff0000")
.attr("d", d3.svg.area());
}
Is it doing what you want?
I had a similar situation, described in this question. I put together a code example which you can find here:
http://bl.ocks.org/explunit/4659227
The key idea is that the path-generating function can be called during the append of each data point:
svg.selectAll("path")
.data(nodes).enter().append("svg:path")
.attr("d", function(d) { return flow_shapes[d.NodeType](d.height, d.width);})
It's hard to tell from your code but it appears maybe you are trying to call .append in a loop rather than building your data and then letting D3 add all the notes in a single statement.
It might be helpful for you to put your complete code in a JSFiddle so we can see all of what you're trying.
I have been trying to use loop in order to prepare dataset for visualization with d3 but I got some problem when getting data back from loop.
Let's say I have 2 data set,
setX = [1,2 ,3, 4, 5] and setY = [10, 20, 30, 40, 50]
and I create for loop to get array of coordinate x and y from 2 dataset.
var point = new Object();
var coordinate = new Array();
for(var i=0; i < setX.length;i++){
point.x = setX[i];
point.y = setY[i];
coordinate.push(point);
}
and pulling back data from array to draw with
var d3line = d3.svg.line()
.x(function(d){return d.x;})
.y(function(d){return d.y;})
.interpolate("linear");
But the value of x and y data of d3line(coordinate) are always 5 and 50.
Is there a correct way to fix this?
Here is example of code
<div id="path"></div>
<script>
var divElem = d3.select("#path");
canvas = divElem.append("svg:svg")
.attr("width", 200)
.attr("height", 200)
var setX = [1,2 ,3, 4, 5];
var setY = [10, 20, 30, 40, 50];
var point = new Object();
var coordinate = new Array();
for(var i=0; i < setX.length;i++){
point.x = setX[i];
point.y = setY[i];
coordinate.push(point);
}
var d3line = d3.svg.line()
.x(function(d){return d.x;})
.y(function(d){return d.y;})
.interpolate("linear");
canvas.append("svg:path")
.attr("d", d3line(coordinate))
.style("stroke-width", 2)
.style("stroke", "steelblue")
.style("fill", "none");
</script>
You also see my example of this code on http://jsfiddle.net/agadoo/JDtqf/
There are two problems with your code. First (and this causes the behaviour you see), you're overwriting the same object in the loop that creates the points. So you end up with exactly the same object several times in your array and each iteration of the loop changes it. The output you're producing inside the loop prints the correct values because you're printing before the next iteration overwrites the object. This is fixed easily by moving the declaration of point inside the loop.
The second problem isn't really a problem but more of a style issue. You can certainly use d3 in the way that you're using it by simply passing the data in where you need it. A better way is to use d3s selections however where you pass in the data and then tell it what to do with it.
I've updated your js fiddle here with those changes made.