我正在尝试创建一种散点图形式.我有一个自定义的x轴和两个a轴的特定比例.我也为它实现了缩放功能.到目前为止一切都很好,但是当我最终尝试将数据绘制为圆圈时,我得到两个错误:
.
我的图表可以在这个网站上查看:http://servers.binf.ku.dk/hemaexplorerbeta/
(圈子很大,因为我想确保在我设计它们之前大致知道它们的位置)
我根据从MysqL服务器读取的数据创建我的圈子.我检查了所有数据,数字是正确的.他们要么错误地绘图,要么我的刻度/缩放有问题.
您也可能会注意到我创建了我的轴并最初使用某些值进行缩放,并在之后的某些函数中更改它们.这是因为我计划在网站上加载一个空图表,用户可以决定加载它的数据集,其中函数必须自定义要加载的数据的比例和轴.
我在下面粘贴了我的源代码:
- //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",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",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",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 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 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;
- };
解决方法
由于附加引用,graphData中每个数组的第一个和最后一个元素在解析为数字时会导致错误
例如,第七个graphData数组如下所示:
例如,第七个graphData数组如下所示:
- console.log(graphData[6]) // [""5.149230","4.965121""]
造成这种情况的原因似乎是在获取数据时不必要的JSON.stringfiy()调用
- d3.json("getdata.PHP?type=load&gene=CCL5&data=human",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已经是一个字符串,所以当你删除JSON.stringify()时它应该按预期工作