2017-09-26 129 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