Ungültiger Wert für <Kreis> Attribut cx="NaN" mit D3.js
Ich versuche zu schaffen, eine form des Punktdiagramms. Ich habe eine benutzerdefinierte x-Achse und eine spezifische Skala für beide a-Achse. Ich habe implementiert eine zoom-Funktionalität für Sie als gut. So weit ist alles gut, aber wenn ich endlich versuchen, mein Grundstück Daten als Kreise, bekomme ich zwei Fehler:
.
Meinem Diagramm angezeigt werden können, die auf dieser Webseite: http://servers.binf.ku.dk/hemaexplorerbeta/
(die Kreise sind riesig, weil ich möchte sicherstellen, dass ich ungefähr weiß, wo Sie sind, bevor ich style Sie)
Ich meine Kreise basierend auf den ausgelesenen Daten von einem MYSQL-server. Ich habe alle meine Daten und die zahlen korrekt sind. Sie sind entweder Plotten falsch, oder meine Waage/zoom fehlerhaft sind.
Auch Sie vielleicht bemerkt, dass ich meine Achse und die Skala mit einige Werte zunächst und ändern Sie Sie in einigen Funktionen Recht nach. Dies ist aufgrund der Tatsache, dass ich ' m Planung auf das laden eines leeren Graphen auf der website, wo der Benutzer entscheiden kann, was dataset zu laden, wo die Funktionen anpassen beide Skalen und Achsen, um die Daten, die geladen werden.
Habe ich meine eingefügten source-code unter:
//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;
};
- Es sieht aus wie Sie sind übergabe-Zeichenfolgen zu Ihrem
yScale
, welche eingerichtet ist als eine lineare Skala für zahlen. - Ich habe versucht, mit
parseint()
aber es macht keinen Unterschied. Ich bekomme immer noch den gleichen Fehler.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das erste und Letzte element jeder Reihe in
graphData
Fehler verursachen, wenn analysiert, wie zahlen, weil ein zusätzliches AngebotZum Beispiel die siebte Reihe von
graphData
sieht wie folgt aus:Die Ursache HIERFÜR scheint zu sein, die unnötige
JSON.stringfiy()
Anruf beim abrufen der Datend.gene_data
ist bereits ein string, also sollte es wie erwartet funktionieren, wenn Sie entfernen dieJSON.stringify()
gene_data[0]
bekomme ich eine ganze Zahl variierend von rund 4-9. Warum passiert das?? Zum Beispiel, wenn ich drucken Sied.gene_data[0]
es nur schreibt EINE ganze Zahl :SUncaught TypeError: Cannot read property 'length' of undefined
ich kann wirklich nicht verstehen, wo zum Teufel er kommt aus...i<=arr.length
zui<arr.length
behoben, das problem.. Aber es immer noch nicht zeichnen Sie die Kreise korrekt. aus irgendeinem Grund..d.gene_data
ist eine Reihe von zahlen, getrennt durch ein Leerzeichen. Sod.gene_data[0]
geben Sie das erste Zeichen des Strings. Das zweite: entfernen Sie einfach dieJSON.stringify()
wie gesagt - oder viel besser: beseitige diegetdata.php
Skript zurück gültiges JSON. Zum Dritten Kommentar: JavaScript-arrays sind null-indiziert: das erste element des Arrays mit dem index 0 und das Letzte element ist der index gleich dem Wert der array mit der length-Eigenschaft minus 1. Mit<= arr.length
der letzten iteration ist out of bounds