2017-09-26 126 views
0

我制作的scatterplot有一个正确的y轴,从0到5000左右,但是正在绘制的节点没有达到它们的值。y在散点图中比例缩放y轴与y值不同y D3.js

问题(我认为)是y尺度的领域。我尝试过使用extent(),min和max以及硬编码值(这些尝试在那里并且注释掉)。我已经调整了进入y范围的值,他们似乎没问题,他们应该达到这个图表的顶部,但他们几乎没有到一半。

去图表的顶部节点的唯一方法是,如果我硬编码Y比例域的最大是3000,这是不甚至接近最大值为y值约为4600 picture of chart

<!-- STACK OVERFLOW This code at the top is simple HTML/HTTP request stuff, you can 
scroll down till my other comments to start looking at the problem. 
I left this code here so people can run the chart on their browser.--> 

<meta charset="utf-8"> 
<title>Template Loading D3</title> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.min.js"></script> 

<style media="screen"> 
    .axis path, 
    .axis line { 
     fill: none; 
     stroke: black; 
     shape-rendering: crispEdges; 
    } 
</style> 

</head> 
<body> 

<h1>Bitcoin BTC</h1> 

<script type="text/javascript"> 

var xhr = new XMLHttpRequest(); 

function makeRequest(){ 
    xhr.open("GET", "https://api.coindesk.com/v1/bpi/historical/close.json?start=2010-07-17&end=2017-09-11", true); 
    xhr.send(); 
    xhr.onreadystatechange = processRequest; 
} 

function processRequest(){ 
    console.log("testing, state: ", xhr.readyState) 
    if(xhr.readyState == 4 && xhr.status == 200){ 
     let response = JSON.parse(xhr.responseText); 
     makeChart(response); 
    } 
} 

// STACK OVERFLOW -- code above this can be ignored since it's just making HTTP request. 
// I'm leaving it here so people can serve this code on their own machine and 
// see it working in their browser. D3 code is below 

// When the HTTP request is finished, this function gets called to draw my chart, 
// this is where D3.js starts. 
function makeChart(response){ 
    var w = window.innerWidth - 100; 
    var h = window.innerHeight - 100; 
    var padding = 20; 
    var Lpadding = 45; 

// makeDatesAndValues is not part of my problem, this formats the dates 
// coming from HTTP request into something easier to feed into D3.js X Scale 
    var makeDatesAndValues = function(input){  
     let dates = []; 
     let values = []; 
     let returnData = []; 

     for(prop in input){ 
      values.push(input[prop]) 

      let counter = 0; 
      let year = []; 
      let month = []; 
      let day = []; 

      for(var j = 0; j < prop.length; j++){ 
       if(lastDate[j] !== "-" && counter == 0){ 
        year.push(prop[j]); 
       } else if(prop[j] == "-"){ 
        counter++; 
       } else if(prop[j] !== "-" && counter == 1){ 
        month.push(prop[j]) 
       } else if(prop[j] !== "-" && counter == 2){ 
        day.push(prop[j]) 
       } 
      } 
      dates.push([Number(year.join("")), Number(month.join("")), Number(day.join(""))]); 

      returnData.push(
       { 
        date: [Number(year.join("")), Number(month.join("")), Number(day.join(""))], 
        value: input[prop] 
       } 
      ) 
     } 
     return returnData; 
    } 

    var inputData = makeDatesAndValues(response.bpi); 

// HERE WE GO, this is where I think the problem is, drawing the actual chart. 
    var svg = d3.select("body") 
       .append("svg") 
       .attr("width", w) 
       .attr("height", h); 

// Here is the problem child, both "y" and the commented out "yScale" are attempts to 
// get the correct y-coordinates for values fed into the scale 
// Both of these will make a correct y Axis, but then screw up the y-coordinates of my data 
// getting fed in, as described on SO 
    var y = d3.scale.linear() 
        .domain([d3.min(inputData, function(d){ return d.value; }), d3.max(inputData, function(d){ return d.value; })]) 
        // .domain([d3.extent(d3.values(inputData, function(d){ return d.value}))]) 
        // .domain([0, 3000]) 
        .range([h - padding, padding]) 

    // var yScale = d3.scale.linear() 
    //     // .domain([0, 5000]) 
    //     .domain([d3.min(inputData, function(d){ return d.value; }), d3.max(inputData, function(d){ return d.value; })]) 
    //     // .domain([d3.extent(d3.values(inputData, function(d){ return d.value}))]) 
    //     .range([0, h]) 

// X scale works fine, no problems here 
    var x = d3.time.scale() 
         .domain([new Date(2010, 7, 18), new Date(2017, 7, 18)]) 
         .range([Lpadding, w]); 

// Both Axes seem to be working fine 
    var xAxis = d3.svg.axis() 
        .scale(x) 
        .orient("bottom") 
        .ticks(8) 

    var yAxis = d3.svg.axis() 
        .scale(y) 
        .orient("left") 
        // .tickSize(-w, 0, 0) 
        .ticks(8) 


    svg.selectAll("circle") 
        .data(inputData) 
        .enter() 
        .append("circle") 
        .attr("cx", function(d){ 
         let thisDate = x(new Date(d.date[0], d.date[1], d.date[2])) 
         return thisDate; 
        }) 
// And here is the other side of the problem. There are different attempts 
// to plot they y-coordinate of my values commented out. 
// None of these are working and I don't understand why it works correctly 
// for the Y Axis, but my plotted values come way short of where they should be. 
        .attr("cy", function(d, i){ 
         console.log("this is with yScale: ", y(d.value)) 
         console.log("Without: ", d.value) 
         // return y((d.value) - padding) 
         // return y(d.value); 
         // return y(d.value) - (h - padding) 
         return h - padding - y(d.value); 
        }) 
        .attr("r", function(d){ 
         return 1; 
        }) 
        .attr("fill", "red") 

    svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(" + 0 + ", " + (h - padding) + ")") 
     .call(xAxis); 

    svg.append("g") 
     .attr("class", "y axis") 
     .attr("transform", "translate(" + Lpadding + ", 0)") 
     .call(yAxis); 
} 

makeRequest(); 

</script> 

</body> 

回答

0

我建议你可能需要考虑人们的感受,当你张贴这样长的代码与可怜的评论。

你的问题是你没有意识到SV指向底部的坐标系。以下是一些修改:

svg.selectAll("circle") 
    .data(inputData) 
    .enter() 
    .append("circle") 
    .attr("cx", function(d){ 
     let thisDate = x(new Date(d.date[0], d.date[1], d.date[2])); 
     return thisDate; 
    }) 

    // this is the KEY part you should change: 
    .attr("cy", function(d, i){ return h - padding - y(d.value); }) 

    .attr("r", 1) 
    .attr("fill", "red"); 

由于您不提供详细数据,我无法检查它。希望它会有所帮助!

+0

感谢您的帮助,您的建议会产生同样的问题,我已经越过了。 对不起,没有评论,我认为这是非常标准的D3.js代码,但我现在要添加评论。 我很惊讶你说你不能检查它,你可以复制粘贴我的代码,静态地提供它而不用改变任何东西,并在浏览器上查看图表。 – iggirex

+0

如你所愿,我更改了你的代码。对于普通的JavaScript和基本的SVG技巧你有很多工作要做。 [这里](http://jsbin.com/natikab/edit?html,js,output)是jsbin代码,它的工作原理。 – 1Cr18Ni9

+0

非常感谢你的代码!是的,我一直在忽略JS框架,因为我确实想在语言上变得更好。你非常先进,我感谢你花时间向我展示这一点。我现在正在学习能够像你一样链接更高级的功能,太酷了!对于这些基本的JS和D3技巧的学习资源的任何建议? – iggirex