2016-12-15 74 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

那么,你改变了你的代码,这不仅使我的答案无用,而且整个问题成为一个完全不同的问题。 *在您更改之前* *正在工作。 –