2016-12-15 73 views
2

使用d3.js曲線圖的x座標在x = 0或在y軸上顯示。 x軸表示日期和時間,y軸表示溫度。但這只是在ipad或iphone上。在我自己的機器上,Linux,它顯示正確。d3.js的x座標顯示不正確的iOS

的圖表和所有文件可以在可見, http://shanespi.no-ip.biz

在iPad/iphone顯示

enter image description here

雖然正確圖表是,

enter image description here

這裏是javascript,

var xScale = d3.scaleTime() 
     .domain([new Date(datahourly[0].date), d3.max(datahourly, function(d) {return new Date(d.date)})]) 
    .range([0, (w-2*padding)]); // max x screen space is width - twice padding 


    var yScale = d3.scaleLinear() 
     .domain([0, d3.max(datahourly, function(d) {return d.temp})]) 
     .range([(h-2*padding), 0]); // max y screen space is height - twice padding 

    var xAxis = d3.svg.axis(xScale) // d3 v.4 
     .ticks(9) // specify the number of ticks 
    /*.ticks(d3.time.days, 1) */ 
     .tickFormat(d3.time.format('%H:00')) 
     .scale(xScale) 
     .orient("bottom"); 

    var yAxis = d3.svg.axis(yScale) 
     .ticks(7) 
     .scale(yScale) 
     .orient("left"); 

    var svg = d3.select('#hourly-readings') 
     .append('svg') // create an <svg> element 
    .attr('id', 'svgDaily') 
     .attr('width', w) // set its dimensions 
     .attr('height', h); 

    svg.append("g") 
    .attr("class", "axis") 
    .attr("transform", "translate(" + (2*padding - 15) + "," + (padding - 15) + ")") 
    .call(yAxis); 

svg.append('g')   // create a <g> element 
      .attr('class', 'axis') // specify classes 
    .attr("transform", "translate(" + (2*padding - 15) + "," + (h - padding - 15) + ")") 
     .call(xAxis);   // let the axis do its thing 

    var lineFunctionStart = d3.svg.line() 
    .x(function(d) {return xScale(new Date(d.date)); }) 
    .y(h - 2*padding - 5) 
    .interpolate("cardinal"); 

    var lineFunction = d3.svg.line() 
    .x(function(d) {return xScale(new Date(d.date)); }) 
    .y(function(d) {return yScale(d.temp); }) 
    .interpolate("cardinal"); 

    svg.append("path") 
     .attr('d', lineFunctionStart(datahourly)) 
    .attr('stroke', "grey") 
    .attr('stroke-width', 1) 
    .style('fill', "white") 
    .attr("transform","translate(" + (2*padding - 13) + "," + (padding - 10) + ")") 
    .transition() 
    .duration(3000) 
     .attr('d', lineFunction(datahourly)); 

    //var svg = d3.select('svg'); 
    var svg = d3.select('#svgDaily'); 


     svg.append("text")  // text label for the x axis 
    .attr("x", 310) 
.attr("y", h) 
.style("font-size", "12") 
    .style("text-anchor", "middle") 
    .text("Time (1 hr. intervals)"); 

svg.append("text")  // text label for the x axis 
.attr('transform', 'rotate(-90)') 
.attr("x", -85) // Because rotate is first x and y coordinates are transaposed 
.attr("y", padding-17) 
.style("font-size","10") 
    .style("text-anchor", "middle") 
    .text("Temp. Celcius"); 


    var rects = svg.selectAll('circle') 
     .data(datahourly); 

    var newRects = rects.enter(); 
     newRects.append('circle') 
     .attr('cx', function(d, i) { return (Math.random() * (w - 2*padding)) }) 
     //.attr('cx', function(d, i) { 
      //return (5 + xScale(new Date(d.date))); 
      //}) 
     .attr('cy', (h - (2*padding))) 
     .attr('r', 5) 
     .style('fill', "lightblue") 
     .attr("transform","translate(" + (2*padding - 18) + "," + (padding - 20) + ")") 
     .transition() 
     .duration(3000) 
     .delay(function(d, i) {return i * 300}) 
     .attr('cx', function(d, i) { 
      return (5 + xScale(new Date(d.date))); 
      }) 
     .attr('cy', function(d, i) { 
      return 10 + yScale(d.temp); 
    }); 

這裏是 'datahourly' 數據,

[ 
    { 
     "date":"2016-12-14 22:01:01.799830", 
     "temp":"24.04" 
    }, 
    { 
     "date":"2016-12-15 00:01:02.362875", 
     "temp":"23.03" 
    }, 

...................... 

    { 
     "date":"2016-12-15 21:01:01.868593", 
     "temp":"21.93" 
    }, 
    { 
     "date":"2016-12-15 22:01:02.278817", 
     "temp":"15.9" 
    }, 
    { 
     "date":"2016-12-15 23:01:01.963714", 
     "temp":"21.63" 
    } 
] 

我使用Chrome的Linux和Safari瀏覽器在iPad和iPhone。但我確實在iPhone上安裝了Chrome,並且圖形仍然不正確。

與iOS的SVG有問題?

編輯: 的主要問題是,時間數據,不能正確解析

這是正確的解決方案,

var data = []; 
     $.getJSON("data/data.json", 
     function(info){ 
     data = info[0].fiveMinReadings; 
     //console.log(data); 
     var parseTime = d3.timeParse("%Y-%m-%d %H:%M:%S.%L"); 
     data.forEach(function(d) { 
      d.date = d.date.slice(0,-3);// remove microseconds 
      d.date = parseTime(d.date); 
      d.temp = +d.temp; 
     }); 

     // Beginning of graph for 5 minute readings 
      var padding = 25; 
      var w = 600; 
     var h = 300; 

     var xScale = d3.scaleTime() 
     .domain(d3.extent(data, function(d) { return d.date; })) 
       .range([0, (w-2*padding)]); // max x screen space is width - twice padding 

     var yScale = d3.scaleLinear() 
      .domain([0,d3.max(data, function(d) {return d.temp})]) 
      .range([(h-2*padding), 0]); // max y screen space is height - twice padding 

     var xAxis = d3.axisBottom(xScale) // d3 v.4 
      .tickFormat(d3.timeFormat('%H:%M ')) 
       .scale(xScale); 

     var yAxis = d3.axisLeft(yScale) 
      .scale(yScale); 

     var svg = d3.select('#five-min-readings') 
      .append('svg') // create an <svg> element 
      .attr('id','svgHourly') 
      .attr("align","center") 
      .attr('width', w) // set its dimensions 
      .attr('height', h); 

     var valueline = d3.line() 
      .curve(d3.curveCardinal) 
      .x(function(d) { return xScale(d.date); }) 
      .y(h - 2*padding - 4); 

     var valueline2 = d3.line() 
      .curve(d3.curveCardinal) 
      .x(function(d) { return xScale(d.date); }) 
      .y(function(d) {return yScale(d.temp); }); 

     svg.append("text")  // text label for the x axis 
      .attr("x", 310) 
      .attr("y", h) 
      .style("font-size", "12") 
      .style("text-anchor", "middle") 
      .text("Time (5 min. intervals)"); 

     svg.append("text")  // text label for the x axis 
      .attr('transform', 'rotate(-90)') 
      .attr("x", -85) // Because rotate is first, x and y coordinates are transaposed 
      .attr("y", padding-17) 
      .style("font-size","10") 
      .style("text-anchor", "middle") 
      .text("Temp. Celcius"); 

      svg.append("g") 
      .attr("class", "axis") 
      .attr("transform", "translate(" + (2*padding-15) + "," + (padding-15) + ")") 
      .call(yAxis); 

     svg.append('g')   // create a <g> element 
      .attr('class', 'axis') // specify class 
      .attr("transform", "translate(" + (2*padding-15) + "," + (h - padding - 15) + ")") 
       .call(xAxis);   // let the axis do its thing 

     svg.append('path') 
      .data([data]) 
      .attr("class","line") 
      .attr('d', valueline) 
      .attr('stroke', "grey") 
      .attr('stroke-width', 1) 
      .style('fill', "white") 
      .attr("transform","translate(" + (2*padding - 13) + "," + (padding -10) + ")") 
      .transition() 
      .duration(3000) 
      .attr('d', valueline2);  

     var svg = d3.select('#svgHourly'); 

     var rects = svg.selectAll('circle') 
      .data(data); 

     var newRects = rects.enter(); 

     newRects.append('circle') 
      .attr('cx', function(d, i) { return (Math.random() * (w - 2*padding)) }) 
      .attr('cy', h - 2*padding)  
      .attr('r', 5) 
      .attr("id", function(d,i){return "circle" + i}) 
      .style('fill', "lightblue") 
      .attr("transform","translate(" + (2*padding - 18) + "," + (padding - 20) + ")") 
      .transition() 
      .duration(3000) 
      .delay(function(d, i) {return i * 300}) 
       .attr('cx', function(d, i) { return (5 + xScale(d.date)); }) 
      .attr('cy', function(d, i) { return 10 + yScale(d.temp); });   
     }); // closes getJSON() 

回答

3

你可以清楚地看到你的圈子越來越正確的Y( 「cy」)值,錯誤在於x(「cx」)值。

問題似乎是在Safari中使用此模式的new Date()yyyy-MM-dd

在您的代碼,給你的數據結構,你會最終擁有的線發生器是這樣的:

.x(function(d) { 
    return xScale(new Date("2016-12-15 23:01:01.963714")); 
})//the first date in your data ---^ 

與同爲你的圈子:

.attr('cx', function(d, i) { 
    return (5 + xScale(new Date("2016-12-15 23:01:01.963714"))); 
}) 

顯然, Chrome和Firefox支持此功能,但不支持Safari。奇怪的是,模式(yyyy-MM-dd)包含在ECMA standard中,所以這可能是一個Safari特定的問題。

this answer,它會工作,如果你包括T(我沒有測試):

.x(function(d) { 
    return xScale(new Date("2016-12-15T23:01:01.963714")); 
}) 

另外,除去new Date()和D3 4.x版使用D3(d3.timeParse()解析日期和d3 v3.x中的format.parse())。

編輯:彙總,你有兩個可能的解決方案:

解決方案1 ​​:刪除所有new Date功能(包括上線發生器和使用它的所有尺度),並使用D3解析日期。 You said您使用的是d3 v3.x,但代碼使用的是d3 v4.x。不過,這裏是如何使用D3 3.x版做到這一點:

var date = "2016-12-14 22:01:01.799830".slice(0,-3); 
 
var format = d3.time.format("%Y-%m-%d %H:%M:%S.%L"); 
 
var myDate = format.parse(date); 
 

 
console.log(myDate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

注:我取下最後3位數字,因爲D3可以解析在線訂購毫秒,微秒沒有。

解決方案2:保持你的new Date功能,但增加了一個T已經討論過上述:

var date = "2016-12-14 22:01:01.799830".replace(/\s/, 'T'); 
 
console.log(date); 
 
console.log(new Date(date));

+1

@ofey這是一個猜測,我無法測試它,因爲我在Windows上使用Chrome。如果這不是問題,請告訴我,以便我可以刪除答案。 –

+0

我也不使用iOS,所以我得找一個朋友來檢查它。如何在日期時間內獲得T? json數據是在python文件data [1] [「hourlyAverages」]中生成的。append({「date」:str(now),「temp」:str(temp)}) –

+0

我以前在這裏看到過評論有人建議使用d3時間格式。我可能會先嚐試d3.timeParse()。謝謝 –

0

似乎有一個問題與dc.js 1.7.5的之間的兼容性穩定版本和d3.js v4。 dc.js compatibility with v4 of d3.js和我的新帖https://stackoverflow.com/questions/41389307/dc-js-1-7-5-not-compatible-with-d3-js-v4

+3

dc.js與d3 v4.x不兼容,這是事實。但請停下來思考一下你的問題:你在質疑Chrome **,Firefox等**的代碼**,但是**在Safari中不起作用。如果這是一個dc.js兼容性問題,你如何解釋? DC。js與Chrome上的d3兼容,但突然它不在Safari上?你能否看到這是沒有道理的? –

+0

在所有使用d3 v4的瀏覽器中,Dc都會成爲問題。爲什麼我不能簡單地繪製這些日期? http://shanespi.no-ip.biz –

+1

那麼,你改變了你的代碼,這不僅使我的答案無用,而且整個問題成爲一個完全不同的問題。 *在您更改之前* *正在工作。 –