d3.js x-coord显示错误的iOS

时间:2016-12-15 23:50:19

标签: javascript d3.js

使用d3.js,图形的x坐标显示在x = 0或y轴上。 x轴表示日期和时间,y轴表示温度。但这只是在ipad或iphone上。在我自己的机器Linux上,它显示正确。

图表和所有文件都可以在, 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"
   }
]

我在ipad和iphone上使用Linux上的Chrome和Safari。但我确实在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 个答案:

答案 0 :(得分:3)

您可以清楚地看到您的圈子正在获得正确的y(&#34; cy&#34;)值,错误在于x(&#34; cx&#34;)值。

问题似乎是使用这种模式在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(d3 v4.x中的d3.timeParse()和d3 v3.x中的format.parse())解析日期。

编辑:总结一下,您有两种可能的解决方案:

解决方案1 ​​:删除所有new Date函数(在行生成器和使用它的所有比例中)并使用d3解析日期。 You said您使用的是d3 v3.x,但您的代码使用的是 d3 v4.x 。不过,以下是使用 d3 v3.x

的方法

&#13;
&#13;
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);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;

注意:我删除了最后3位数,因为d3可以解析onli miliseconds,而不是微秒。

解决方案2 :保留new Date个功能,但如上所述添加T

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

答案 1 :(得分: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

上的新帖子

答案 2 :(得分:0)

哇,这个方法在 android 和 iOS 上都有效,节省了我浏览这个问题的时间

var commonDate = item.created_at.replace(/\s/, "T");
var date = new Date(commonDate);

长话短说:我在 ionic angular 版本中使用了 d3,仅在 iOS 中也遇到了同样的问题