So I am working with the d3 fisheye plugin, and I am having some pretty basic problems.
I implemented this very basic code, pretty much a direct copy from here https://github.com/d3/d3-plugins/tree/master/fisheye
fisheye = d3.fisheye.circular()
.radius(200)
.distortion(2);
//initialize fisheye
chart.on("mousemove", function() {
fisheye.focus(d3.mouse(this));
dataPoint.each(function(d) { d.fisheye = fisheye(d); })
.attr('y', function(d){ return d.fisheye.y; })
.attr('x', function(d){ return d.fisheye.x; });
});
But d.fisheye.x and d.fisheye.y are undefined. In fact, looking at fisheye(d), it returns:
{x: undefined, y: undefined, z: 1}
On the other hand, d3.mouse(this) is properly returning an array.
Does any one have suggestion on why this might be occurring?
More code: by the way, the code is like this because it is inside a ext-js panel, so each function (drawWords is a property of this object). It is kind of complicated which is why I hesitated to post it all, and this is still not all the code, but the relevant part I think. I didn't include the initialization of any of the other global variables, or helper functions.
//imagine some sort of onload function
onLoad: function () {
this.drawWords();
this.animateVis();
}
,drawWords: function () {
toolObject = this;
var h = this.body.getHeight(),
w = this.body.getWidth();
//initialize word text
this.dataPoint = this.chart.selectAll('text')
.data(toolObject.termometerData, function (d) {return d.word;})
.enter().append('text')
.attr('class', 'points')
.attr('id', function(d) {return d.word + '-point';})
.attr('x', function() {
return toolObject.xScale(toolObject.shiftCount);
})
.attr('y', function (d) {
return toolObject.fanVertical(d, toolObject.shiftCount);
})
.attr('transform', function (d) {
var thisXPosition = toolObject.xScale(toolObject.shiftCount),
thisYPosition = toolObject.fanVertical(d, toolObject.shiftCount);
return 'translate(0, 0) rotate(-20 ' + thisXPosition + ' ' + thisYPosition + ')';
})
.attr('text-anchor', 'middle')
.attr('fill-opacity', function (d) {return toolObject.opacityScale(0);})
.text(function(d) {return d.word;});
this.applyFisheye();
}
,fisheye: d3.fisheye.circular()
.radius(200)
.distortion(2)
,applyFisheye: function () {
var toolObject = this;
//initialize fisheye
this.chart.on("mousemove", function() {
fisheye.focus(d3.mouse(this));
toolObject.dataPoint.each(function(d) { d.fisheye = toolObject.fisheye(d); })
.attr('y', function(d){ return d.fisheye.y; })
.attr('x', function(d){ return d.fisheye.x; })
.attr('transform', function(d){
return 'translate(0, 0) rotate(-20 ' + d.fisheye.x + ' '+ d.fisheye.y + ')';
});
});
}
,animateVis: function () {
var toolObject = this;
var h = this.body.getHeight(),
w = this.body.getWidth();
var tick;
if(this.animationIdArray.length < 1){
tick = setInterval(function(){
animate();
}, this.duration);
this.animationIdArray.push(tick);
}
function animate() {
if(toolObject.shiftCount < toolObject.numDataPoints){
toolObject.shiftCount++;
//animate words
toolObject.dataPoint.transition()
.duration(toolObject.duration)
.ease('linear')
.attr('x', function(d){ return toolObject.xScale(toolObject.shiftCount - 1); })
.attr('y', function(d){ return toolObject.fanVertical(d, toolObject.shiftCount - 1); })
.attr('transform', function(d){
var thisXPosition = toolObject.xScale(toolObject.shiftCount - 1),
thisYPosition = toolObject.fanVertical(d, toolObject.shiftCount - 1);
return 'translate(0, 0) rotate(-20 ' + thisXPosition + ' '+ thisYPosition + ')';
})
.attr('fill-opacity', function(d){
return toolObject.opacityScale(d.series[toolObject.shiftCount - 1].freq);
});
toolObject.applyFisheye();
}else{
clearInterval(tick);
toolObject.animationIdArray.shift();
}
}
}
fisheye assumes that the x and y coordinates of your objects are defined by keys named "x" and "y". It's probably enough (but possibly overkill, depending how often this code is called) to use
this.dataPoint
.each(function(d) {
d.x = toolObject.xScale(toolObject.shiftCount);
d.y = toolObject.fanVertical(d, toolObject.shiftCount)
.attr('x', function(d) { return d.x; })
.attr('y', function(d) { return d.y; });
when you //initialize word text
Related
I am beginner in d3 v3. I created multiple donut charts. When I move my mouse over a slice, I get the tooltip that appears. But I would also like the slice to grow a little bit.
I have already tried several codes but I can't get there. I wonder if the problem may be related to d3 tip
this is my js file :
//Source : http://bl.ocks.org/mbostock/1305337
var m = 15,
r = 80,
z = d3.scale.ordinal()
.range(["#50FFC5", "#54E868", "#54CCE8", "#6395FF"]);
var pie = d3.layout.pie()
.value(function (d) {
return +d.count;
})
.sort(function (a, b) {
return b.count - a.count;
});
var arc = d3.svg.arc()
.innerRadius(r / 2)
.outerRadius(r);
var radius = d3.scale.linear()
.range([10, r])
var tip = d3.tip()
.attr('class', 'd3-tip')
.html(function (d) {
return d.data.genre + ": " + d.data.count;
})
.direction('s');
d3.csv("../CSV/genreHameau.csv", function (error, hameau) {
if (error) throw error;
var datas = d3.nest()
.key(function (d) {
return d.origine;
})
.entries(hameau);
datas.forEach(function (d) {
totalOrigin = d3.sum(d.values, function (d) {
return +d.count;
})
d.values.forEach(function (dd) {
dd.totalOrigin = totalOrigin
})
})
datas.sort(function (a, b) {
return d3.descending(a.values[0].totalOrigin, b.values[0].totalOrigin)
})
// définir le radius / rayon des arcs (rendre fonction de 'count')
var max = d3.max(datas, function (d) {
return d.values[0].totalOrigin
})
var min = d3.min(datas, function (d) {
return d.values[0].totalOrigin
})
radius.domain([min, max])
arc
.innerRadius(function (d) {
return radius(d.data.totalOrigin) / 2
})
.outerRadius(function (d) {
return radius(d.data.totalOrigin)
})
function size(d) {
return radius(d.values[0].totalOrigin) + m
}
var div = d3.select("body").selectAll("div")
.data(datas)
.enter().append("div") // http://code.google.com/p/chromium/issues/detail?id=98951
.style("display", "inline-block")
.style("width", function (d) {
return 2 * size(d) + "px"
})
.style("height", function (d) {
return 2 * size(d) + "px"
})
.style("min-width", "80px")
.style("min-height", "80px")
div.append("span")
.attr("class", "nomhameau")
.text(function (d) {
return d.key;
})
.append("span")
.attr("class", "nombrehameau")
.text(function (d) {
return " (" + d.values[0].totalOrigin + ")"
});
var svg = div.append("svg")
//.attr("width", (r + m) * 2)
//.attr("height", (r + m) * 2)
.attr("width", function (d) {
return 2 * size(d)
})
.attr("height", function (d) {
return 2 * size(d)
})
.append("g")
.attr("transform", function (d) {
return "translate (" + size(d) + "," + size(d) + ")"
});
svg.call(tip);
var g = svg.selectAll("g")
.data(function (d) {
return pie(d.values);
})
.enter().append("g")
.on("mouseover", tip.show)
.on("mouseout", tip.hide)
g.append("path")
.attr("d", arc)
.style("fill", function (d) {
return z(d.data.genre);
})
.append("title")
});
Thank you for your help
I would do it this way:
Just like you created the arc, create a new one with a greater radius, either inner, outer or both, something like:
var arcHighlight = d3.svg.arc()
.innerRadius(r / 2)
.outerRadius(r*1.1);
Then you add mouseover and mouseout events to the slice and modify the slice doing something like:
// Add a colored arc path, with a mouseover title showing the count.
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return z(d.data.carrier); })
// new code
.on('mouseover', function(d) {
d3.select(this)
.transition()
.attr('d', arcHighlight(d));
})
.on('mouseout', function(d) {
d3.select(this)
.transition()
.attr('d', arc(d));
})
.append("title")
.text(function(d) { return d.data.carrier + ": " + d.data.count; });
The transition is optional, but it looks fancier ;)
I am new to d3.js and please forgive me if this sounds like a naive question. I have plotted a line (d3 v4) which can be draggable by its end points. The end points are rectangle.
The current output looks as below :
This is how it looks
The challenge that i am facing is - when i start dragging the point, the line seems to take its origin from the top left corner. When i drag the second point of the same line, the line drags / moves as expected.
The sample data looks as below :
The sample data
Requesting your suggestions / inputs on how to fix the above issue.
Below is the attached code that i am using :
var margin = { top: 0, right: 0, bottom: 0, left: 0 },
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
// Creating the colour Category
var color = d3.scaleOrdinal(d3.schemeCategory10);
var y = d3.scaleLinear().range([390, 0]);
// Scale the range of the data
y.domain([0, d3.max(data, function (d) { return Math.max(d.nonpromotedprice, d.promotedprice)*1.2; })]).nice();
// Line for the 1st Block
var lines = svg.selectAll("line")
.data(data)
.enter()
.append('line')// attach a line
.style("stroke", "#E6EAEE")
.style("stroke-width", 8) // colour the line
.attr("x1", function (d) { return d.x_value; }) // x position of the first end of the line
.attr("y1", function (d) { return y(d.nonpromotedprice); }) // y position of the first end of the line
.attr("x2", function (d) { return d.x_value; }) // x position of the second end of the line
.attr("y2", function (d) { return y(d.promotedprice); });
// Add the Y Axis
svg.append("g")
.attr("class", "grid")
.attr("fill", "lightgrey")
.attr("stroke-width", 0.7)
.attr("stroke-opacity", 0.2)
.call(d3.axisLeft(y)
.tickSize(-400)
.tickFormat(""));
var topEndPoints = data.map(function (line, i) {
return {
'x': line.x_value,
'y': line.nonpromotedprice,
'marker': 'marker-start',
'lineIndex': i
};
});
var bottomEndPoints = data.map(function (line, i) {
return {
'x': line.x_value,
'y': line.promotedprice,
'marker': 'marker-end',
'lineIndex': i
};
});
var MiddleEndPoints = data.map(function (line, i) {
return {
'x': line.x_value,
'y': line.avgprice,
'marker': 'marker-middle',
'lineIndex': i
};
});
var endPointsData = topEndPoints.concat(bottomEndPoints, MiddleEndPoints);
// Pointer to d3 rectangles
var endPoints = svg
.selectAll('rect')
.data(endPointsData)
.enter()
.append('rect')
.attr("width", 12)
.attr("height", 8)
.attr("x", function (d) { return d.x - 6; })
.attr("y", function (d) { return y(d.y); })
//.attr("cx", function (d) { return d.x; })
//.attr("cy", function (d) { return d.y; })
//.attr('r',7)
.attr("fill", function (d) { return color(d.x); })
.call(d3.drag()
//.origin(function(d) { return y(d.y); })
.subject(function() {
var t = d3.select(this);
return {x: t.attr("x"), y: t.attr("y")};
})
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
// draw the logo
svg.selectAll("image")
.data(data)
.enter()
.append("svg:image")
.attr("xlink:href", function (d) { return d.logo; })
//.append("rect")
.attr("x", function (d) { return d.x_value - 13; })
.attr("y", function (d) { return y(d.nonpromotedprice + 35); })
.attr("height", 25)
.attr("width", 25);
function dragstarted() {
d3.select(this).classed("active", true).attr('y', d.y = y(d3.event.y));
}
function dragged(d, i) {
var marker = d3.select(this);
// Update the marker properties
marker
//.attr('cx', d.x = d3.event.x)
.attr('y', d.y = d3.event.y);
// Update the line properties
lines
.filter(function (lineData, lineIndex) {
return lineIndex === d.lineIndex;
})
.attr('x1', function (lineData) {
return d.marker === 'marker-start' ? lineData.x1 = d.x : lineData.x1;
})
.attr('y1', function (lineData) {
return d.marker === 'marker-start' ? lineData.y1 = d.y : lineData.y1;
})
.attr('x2', function (lineData) {
return d.marker === 'marker-end' ? lineData.x2 = d.x : lineData.x2;
})
.attr('y2', function (lineData) {
return d.marker === 'marker-end' ? lineData.y2 = d.y : lineData.y2;
});
}
function dragended() {
d3.select(this).classed("active", false);
Shiny.setInputValue("pricechanged",
{price: (d3.max(data, function (d) { return Math.max(d.nonpromotedprice, d.promotedprice); }) -(d3.event.y / 390)* d3.max(data, function (d) { return Math.max(d.nonpromotedprice, d.promotedprice); }))*1.19},
{priority: "event"}
);
}
Trying to add new nodes to existing graph with add function end up with all new graph. here is my code:
function Graph(elementId) {
var svg;
var simulation;
var mNodesData = [];
var mEdgesData = [];
var mNode = null;
var mLink = null;
var elementId;
var heightDelta = 100;
var width = window.innerWidth;
var height = window.innerHeight - heightDelta;
return {
init: function () {
svg = d3.select('#' + elementId)
.append("svg")
.attr("width", width)
.attr("height", height);
simulation = d3.forceSimulation()
.force(".edge", d3.forceLink())
.force("charge", d3.forceManyBody().strength(-600))
.force("center", d3.forceCenter(width / 2, height / 2));
},
clearGraph: function () {
$('#' + this.elementId).empty();
},
getNodes: function () {
return mNodesData;
},
getEdges: function () {
return mEdgesData;
},
addNodes: function (nodes) {
mNodesData = mNodesData.concat(nodes);
},
addEdges: function (edges) {
mEdgesData = mEdgesData.concat(edges);
},
draw: function () {
mLink = svg.selectAll(".edge")
.data(mEdgesData)
.enter()
.append("line")
.attr("class", "edge")
.style("stroke", "#ccc")
.style("stroke-width", function (e) {
return 1
/* e.width*/
});
mNode = svg.selectAll(".node")
.data(mNodesData)
.enter()
.append("g")
.attr("class", "node")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
mNode.on('mouseover', function (d) {
function removePopup() {
$("#nodePopup").remove();
}
function showPopup(d) {
removePopup();
if (!d['data']) {
return;
}
var data = d['data'];
var htmlStr = '';
htmlStr += '<div id="nodePopup" >';
htmlStr += ' <div><button id="nodePopupCloseButton" type="button" class="close" data-dismiss="alert"><span class="glyphicon glyphicon-remove" style="font-size: 13px;"> </span> </div>';
htmlStr += ' <div class="nodePopupName">' + data['name'] + '</div>';
if (data['desc']) {
if (data['desc'].startsWith("http")) {
htmlStr += ' <a class="nodePopupLink" href="' + data['desc'] + '" target="_blank">Go to post..</a>';
}
else {
htmlStr += ' <div class="nodePopupDesc">' + data['desc'] + '</div>';
}
}
htmlStr += ' <div class="nodePopupGroup">GROUP: ' + data['groupId'] + '</div>';
htmlStr += ' <div class="nodePopupLeader">LEADER: ' + data['leaderId'] + '</div>';
htmlStr += ' <div class="nodePopupImage"><img src="' + d['image'] + '" style="width: 130px;" /></div>';
htmlStr += '</div>';
$("body").append(htmlStr);
$("#nodePopupCloseButton").click(removePopup);
}
showPopup(d);
mNode.filter(function (d1) {
return (d !== d1 && d1.adjacents.indexOf(d.id) == -1);
}).select("image").style("opacity", 0.2);
mNode.filter(function (d1) {
return (d !== d1 && d1.adjacents.indexOf(d.id) == -1);
}).select("circle").style("stroke", "#f6f6f6");
mLink.filter(function (d1) {
return (d !== d1.source && d !== d1.target);
}).style("opacity", 0.2);
mNode.filter(function (d1) {
return (d == d1 || d1.adjacents.indexOf(d.id) !== -1);
}).select("image").style("opacity", 1);
mNode.filter(function (d1) {
return (d == d1 || d1.adjacents.indexOf(d.id) !== -1);
}).select("circle").style("stroke", "gray");
mLink.filter(function (d1) {
return (d == d1.source || d == d1.target);
}).style("opacity", 1);
})
.on('mouseout', function () {
// removePopup();
mNode.select("image").style("opacity", 1);
mNode.select("circle").style("stroke", "gray");
mLink.style("opacity", 1);
});
var nodeCircle = mNode.append("circle")
.attr("r", function (d) {
return 0.5 * Math.max(d.width, d.height)
})
.attr("stroke", "gray")
.attr("stroke-width", "2px")
.attr("fill", "white");
var nodeImage = mNode.append("image")
.attr("xlink:href", function (d) {
return d.image
})
.attr("height", function (d) {
return d.height + ""
})
.attr("width", function (d) {
return d.width + ""
})
.attr("x", function (d) {
return -0.5 * d.width
})
.attr("y", function (d) {
return -0.5 * d.height
})
.attr("clip-path", function (d) {
return "circle(" + (0.48 * Math.max(d.width, d.height)) + "px)"
});
simulation.nodes(mNodesData);
simulation.force(".edge").links(mEdgesData);
simulation.on("tick", function () {
mLink.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;
})
mNode.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")"
});
mNode.attr("cx", function (d) {
return d.x = Math.max(d.width, Math.min(width - d.width, d.x));
})
.attr("cy", function (d) {
return d.y = Math.max(d.height, Math.min(height - heightDelta - d.height, d.y));
});
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
}
}
}
function getData() {
return $.ajax({
url: 'api/v1/data.json',
type: "GET",
});
}
var graph = Graph('d3Graph');
graph.init();
$.when(getData()).then(function (data) {
graph.addNodes(data.nodes);
graph.addEdges(data.edges);
graph.draw();
});
function add() {
graph.addNodes([{
"id": 4,
"image": "images/4.jpeg",
"height": 20,
"width": 20,
"adjacents": [0],
"data": {
"name": "Number4",
"groupId": "Bla4",
"desc": "Desc4",
"leaderId": "1234-1234"
}
}]);
graph.addEdges([{
"source": 4,
"target": 3,
"width": 1
}])
graph.draw();
// graph.draw();
}
if i call to add the original graph stack on the page and a new one with another edge & node is added. How do I achieve that correct? (update the old one without creating all new..
What you currently have:
mLink = svg.selectAll("link")
.data(mEdgesData)
.enter()
.append("line")
Normally selectAll("link") means that you select all html elements which are links. But you append a line and not a link. Therefore the appended element is not part of your selectAll. There is no possibility to know that you just wanna add data to something which already exists.
The solution is to add merge to both links & nodes:
mLink = svg.selectAll(".edge")
.data(mEdgesData)
.enter()
.append("line")
.attr("class", "edge")
.style("stroke", "#ccc")
.style("stroke-width", function (e) {
return 1
/* e.width*/
}).merge(mLink);
mNode = svg.selectAll(".node")
.data(mNodesData)
.enter()
.append("g")
.attr("class", "node").merge(mNode);
I had a similar issue when I tried to create a general update procedure for my graph with dynamic data. When the nodes or links where updated, the redraw function was triggered.
The idea works as follows; on redrawing the graph, i.e. when the data has changed, all old nodes and links are removed and drawn again. Using .join() the nodes remain in their position.
Here is my working example:
redraw = () => {
simulation.nodes(nodes);
simulation.force('link')
.links(links)
.initialize(nodes);
d3.selectAll('g.node').remove(); // remove all old nodes
d3.selectAll('g.node').data(nodes).join();
d3.selectAll("line").data(links).join();
draw();
simulation.alpha(0.1)
simulation.restart();
}
In my draw() function, the nodes and links are created accordingly:
draw = () => {
container.selectAll('line').data(links).join('line');
// creates nodes with rectangles that contain text
container.selectAll('g.node').raise()
.data(nodes).join("g")
.each(function (d, i) {
d3.select(this).append("rect");
var text = d3.select(this).append("text").text(d => d.name)
// calculate text width for function tick() to adapt rect x position
d.width = text.filter(t => t.index == d.index).node()
.getBBox().width;
})
.call(drag(simulation));
}
Where container is a zoomable and draggable SVG element:
container = svg.append('g');
svg.call(d3.zoom()
.on('zoom', () => this.container.attr('transform', d3.event.transform))
.scaleExtent([0.25, 2]))
For completeness, here is my tick() function:
tick = () => {
container.selectAll('rect')
.attr('x', d => d.x - d.width / 2)
.attr('y', d => d.y);
container.selectAll('text')
.attr('x', d => d.x - d.width / 2)
.attr('y', d => d.y);
container.selectAll('line')
.attr('x1', d => d.source.x)
.attr('y1', d => d.source.y)
.attr('x2', d => d.target.x)
.attr('y2', d => d.target.y);
}
If I have time, I post a JSFiddle later.
I've constructed a D3 visualization that was working on my local machine. However, now i've exported to my server, the code breaks and throws several errors:
Error: invalid value for <circle> attribute transform="translate"(NaN,NaN)"
Error: invalid value for <text> attribute transform="translate"(NaN,NaN)"
Error: invalid value for <circle> attribute r="NaN"
I've had these errors before with similar code and was able to solve them. However, i cannot grasp what is going wrong. Any suggestions? Thanx!
function drawBubbles() {
var margin = 20,
diameter = 740;
var color = d3.scale.linear()
.domain([-1, 10])
.range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
.interpolate(d3.interpolateHcl);
var pack = d3.layout.pack()
.size([diameter - margin, diameter - margin])
.value(function (d) { return d.size; })
var svg = d3.select("form").append("svg")
.attr("width", 1280)
.attr("height", 800)
.append("g")
.attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
d3.json("../Resources/output.json", function (error, root) {
if (error) throw error;
var focus = root,
nodes = pack.nodes(root),
view;
var circle = svg.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("class", function (d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; })
.style("fill", function (d) { return d.children ? color(d.depth) : null; })
.on("click", function (d) { if (focus !== d) zoom(d), d3.event.stopPropagation(); });
var text = svg.selectAll("text")
.data(nodes)
.enter().append("text")
.attr("class", "label")
.style("fill-opacity", function (d) { return d.parent === root ? 1 : 0; })
.style("display", function (d) { return d.parent === root ? "inline" : "none"; })
.text(function (d) { return d.name; });
var node = svg.selectAll("circle,text");
d3.select("form")
.on("click", function () { zoom(root); });
zoomTo([root.x, root.y, root.r * 2 + margin]);
function zoom(d) {
var focus0 = focus; focus = d;
var transition = d3.transition()
.duration(d3.event.altKey ? 7500 : 750)
.tween("zoom", function (d) {
var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
return function (t) { zoomTo(i(t),d); };
});
transition.selectAll("text")
.filter(function (d) { return d.parent === focus || this.style.display === "inline"; })
.style("fill-opacity", function (d) { return d.parent === focus ? 1 : 0; })
.each("start", function (d) { if (d.parent === focus) this.style.display = "inline"; })
.each("end", function (d) { if (d.parent !== focus) this.style.display = "none"; });
}
function zoomTo(v) {
var k = diameter / v[2]; view = v;
console.log(d.x)
console.log(d.y)
console.log(d.r)
console.log(k)
node.attr("transform", function(d) { return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; });
circle.attr("r", function(d) { return d.r * k; });
}
});
d3.select(self.frameElement).style("height", diameter + "px"); }
I had exactly this issue - although most browsers seemed to treat NaN as zero and so not complain, but Chrome wasn't happy at all.
For me I found the packed nodes collection returned from the packer had NaNs for zero value items passed in (which my data could contain). I just looped all the nodes after the pack call and set them to zero. Something like this should do it (it should probably be a recursive call to avoid duplication, but you get the idea!)...
// Replace any zero value items with zero x/y/r values
nodes.forEach( function (currNode) {
if (!currNode.count) {
currNode.x = 0;
currNode.y = 0;
currNode.r = 0;
currNode.children.forEach( function (currChild) {
if (!currChild.count) {
currChild.x = 0;
currChild.y = 0;
currChild.r = 0;
}
});
}
});
Hope this helps you
I got an area that generated by the following functions
area = d3.svg.area.radial().interpolate('cardinal-closed').angle(function (d) {
return angle(d.index);
}).innerRadius(function (d) {
return radius(d.y0);
}).outerRadius(function (d) {
return radius(d.y0 + d.y);
});
and I want to put a point(circle) on my data points, this is what I did:
makePoints = function(){
points = svg.selectAll(".point").data(layers[0].values);
points.enter().append("circle")
.attr("stroke", z(0))
.attr("fill", function(d, i) { return z(0) })
.attr("r", function(d, i) { return 3 });
points.exit().remove();
};
updatePoints = function() {
points.data(layers[0].values);
points.transition().attr("transform",
function (d, i) {
var vals = area([d]).split(',');
return "translate(" + vals[0].split('M')[1] + "," + vals[1].split('M')[0] + ")";
}
);
};
It works, but I think my code is crappy, how can I get the translate data without parsing the area result?