Invalid attribute value <circle> cx = "NaN" using D3.js

I am trying to create a scatter chart shape. I have a special X axis and a specific scale for the a axis. I also implemented a zoom function. So far, everything is in order, but when I finally try to build my data in the form of circles, I get two errors:

Errors when trying to draw circles .

My schedule can be viewed on this website: http://servers.binf.ku.dk/hemaexplorerbeta/ (circles are huge because I want to make sure I know where they are before I style them)

I am creating circles based on data read from the MYSQL server. I checked all my data and the numbers are correct. They either draw erroneously or scale / scale.

You can also notice that I first create my axis and scale with some values ​​and immediately change them to some functions. This is due to the fact that I plan to upload a blank graph to a website, where the user can decide which data set to load it, where the functions will need to set both scales and axes for the loaded data.

I pasted my source code below:

//Setting generic width and height values for our SVG. var margin = {top: 60, right: 0, bottom: 70, left: 40}, genWidth = 1024; genHeight = 768; width = genWidth - 70 - margin.left - margin.right, height = genHeight - 100 - margin.top - margin.bottom; //Other variable declarations. var valueY = 0; var graphData = Array(); //Creating scales used to scale everything to the size of the SVG. var xScale = d3.scale.linear() .domain([0, genWidth]) .range([0, width-margin.right]); var yScale = d3.scale.linear() .domain([0, genHeight]) .range([height, margin.bottom]); var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom"); var yAxis = d3.svg.axis() .scale(yScale) .orient("left"); //Zoom command ... var zoom = d3.behavior.zoom() .x(xScale) .y(yScale) .scaleExtent([1,10]) .on("zoom", zoomTargets); // The mark '#' indicates an ID. IF '#' isn't included argument expected is a tag such as "svg" or "p" etc.. var SVG = d3.select("#mainSVG") .attr("class", "SVG") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .attr("pointer-events", "all") .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); //This creates a body with a clippath inside the svg where all element in the graph will be. This prevents elemnts on the graph to go past the axis. var SVGbody = SVG.append("g") .attr("clip-path", "url(#clip)") .call(zoom); //Create background. The mouse must be over an object on the graph for the zoom to work. The rectangle will cover the entire graph. var rect = SVGbody.append("rect") .attr("width", width) .attr("height", height); //Showing the axis that we created earlier in the script for both X and Y. SVG.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("transform", function(d) { return "rotate(-30)" });; SVG.append("g") .attr("class", "y axis") .call(yAxis); d3.json("getdata.php?type=load&gene=CCL5&data=human", function(error, data) { var arrayValues = []; if(error){ return console.log(error); } data.forEach( function(d) { arrayValues.push(d.gene_name); valueY = getValueY(d.gene_data); var string = JSON.stringify(d.gene_data); graphData.push(string.split(" ")); }); //console.log(graphData); arrayValues = removeDuplicatesInPlace(arrayValues); updateScaleX(arrayValues.length); updateAxisX(arrayValues); //console.log(arrayValues); updateScaleY(valueY); //This selects 4 circles (non-existent, there requires data-binding) and appends them all below enter. //The amount of numbers in data is the amount of circles to be appended in the enter() section. for(var i = 0;i <= graphData.length;i++){ var circle = SVGbody .selectAll("circle") .data(graphData[i]) .enter() .append("circle") .attr("cx",function(d){return xScale((i*100)+100);}) .attr("cy",function(d){return yScale(d)}) .attr("r",20); } }); //Clipping is defined here used to prevent elements from the graph from going past the axis. var clip = SVG.append("defs").append("svg:clipPath") .attr("id", "clip") .append("svg:rect") .attr("id", "clip-rect") .attr("x", "0") .attr("y", "0") .attr("width", width) .attr("height", height); //Resets zoom when click on circle object. Zoom work now, should be changed to a button instead of click on circle though. SVG.selectAll("circle").on("click", function() { zoom.scale(1); zoom.translate([0,0]); zoomTargets(); }); //The function handleling the zoom. Nothing is zoomed automatically, every elemnt must me defined here. function zoomTargets() { var translate = zoom.translate(), scale = zoom.scale(); tx = Math.min(0, Math.max(width * (1 - scale), translate[0])); ty = Math.min(0, Math.max(height * (1 - scale), translate[1])); //This line applies the tx and ty which prevents the graphs from moving out of the limits. This means it can't be moved until zoomed in first. zoom.translate([tx, ty]); SVG.select(".x.axis").call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("transform", function(d) { return "rotate(-30)" }); SVG.select(".y.axis").call(yAxis); SVG.selectAll("circle").attr("cx",function(d){return xScale(d)}).attr("cy",function(d){return yScale(d)}); } function resetZoom() { zoom.scale(1); zoom.translate([0,0]); zoomTargets(); } function updateAxisX(arr) { var formatAxis = function(d, i) { return arr[i]; } xAxis = d3.svg.axis() .scale(xScale) .orient("bottom") .tickValues(createTickValuesArray(arr.length)) .tickFormat(formatAxis); SVG.select(".x.axis") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("transform", function(d) { return "rotate(-30)" }); } function updateScaleX(newWidth){ genWidth = newWidth; xScale = d3.scale.linear() .domain([0, (newWidth*100)+50]) .range([0, width-margin.right]); SVG.selectAll("circle").attr("cx",function(d){return xScale(d)}).attr("cy",function(d){return yScale(d)}); zoom.x(xScale); } function updateScaleY(newHeight){ console.log(newHeight); var yScale = d3.scale.linear() .domain([0, newHeight]) .range([height, margin.bottom]); yAxis = d3.svg.axis() .scale(yScale) .orient("left"); SVG.select(".y.axis").call(yAxis); SVG.selectAll("circle").attr("cx",function(d){return xScale(d)}).attr("cy",function(d){return yScale(d)}); zoom.y(yScale); } function createTickValuesArray(amountOfTicks){ var tickValuesArr = []; for(var i = 1;i<=amountOfTicks;i++){ tickValuesArr[i-1] = 100*i; } return tickValuesArr; } function getValueY(coordinates){ return d3.max(coordinates, Number); } //Custom functions used for specific uses. var removeDuplicatesInPlace = function (arr) { var i, j, cur, found; for (i = arr.length - 1; i >= 0; i--) { cur = arr[i]; found = false; for (j = i - 1; !found && j >= 0; j--) { if (cur === arr[j]) { if (i !== j) { arr.splice(i, 1); } found = true; } } } return arr; }; 
+7
javascript nan circle
source share
1 answer

The first and last element of each array in graphData cause errors when parsing numbers as due to an additional quote
For example, the seventh graphData array looks like this:

 console.log(graphData[6]) // [""5.149230", "4.965121""] 

The reason for this is an unnecessary JSON.stringfiy() call when retrieving data

 d3.json("getdata.php?type=load&gene=CCL5&data=human", function(error, data) { var arrayValues = []; if(error){ return console.log(error); } data.forEach( function(d) { arrayValues.push(d.gene_name); valueY = getValueY(d.gene_data); var string = JSON.stringify(d.gene_data); // <-- this one graphData.push(string.split(" ")); }); 

d.gene_data already a string, so it should work as expected when you remove JSON.stringify()

+4
source share

All Articles