d3.js多线图渲染:相同的数据集但不同的曲线

时间:2017-08-09 13:54:14

标签: d3.js svg charts rendering line

我是d3.js的新手,目前在d3.js中处理多线图,因此准备了两个不同的数据集(“数据集”,“datasetIndividual”)。我注意到单个曲线(绿色)的曲线与重新加载后绘制的点不同。

因此,为了确定问题是曲线或点我开始对每条曲线使用相同的数据集,问题肯定似乎是单个曲线的渲染。每次重新加载后,曲线可能完全重叠,其他时间不同。我无法确定这个特定问题的原因和解决方案。我假设它与代码的嵌套/序列有关。我承认,整个代码有点“行人”。

折线图的代码:

/*create svg element*/
var svg = d3.select('.linechart')
  .append('svg')
  .attr('width', w)
  .attr('height', h)
  .attr('id', 'chart');

/*x scale*/
var xScale = d3.scale.linear()
  .domain([0, d3.max(dataset, function(d) {
    return d[0];
  })])
  .range([padding, w - padding]);

/*y scale*/
var yScale = d3.scale.linear()
  .domain([0, d3.max(dataset, function(d) {
    return d[1];
  })])
  .range([h - padding, padding]);

/*x axis*/
var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient('bottom')
  .ticks(20)
  .tickSize(0, 0)
  //.tickPadding(padding);

/*append x axis*/
svg.append('g')
  .attr({
    'class': 'xaxis',
    //'transform': 'translate(0,' + (h - padding) + ')'
    'transform': 'translate(0,' + 0 + ')'
  })
  .call(xAxis);

/*y axis*/
var yAxis = d3.svg.axis()
  .scale(yScale)
  .orient('left')
  .tickSize(0, 0)
  .tickValues([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]);

/*append y axis*/
svg.append('g')
  .attr({
    'class': 'yaxis',
    'transform': 'translate(' + padding + ',0)'
  })
  .call(yAxis);


/*define line*/
var lines = d3.svg.line()
  .x(function(d) {
    return xScale(d[0])
  })
  .y(function(d) {
    return yScale(d[1])
  })
  .interpolate('monotone');


/*append line*/
var path = svg.append('path')
  .attr({
    'd': lines(dataset),
    'fill': 'none',
    'class': 'lineChart'
  });

/*get length*/
var length = svg.select('.lineChart').node().getTotalLength();

/*animate line chart*/
svg.select('.lineChart')
  .attr("stroke-dasharray", length + " " + length)
  .attr("stroke-dashoffset", length)
  .transition()
  .ease('linear')
  .delay(function(d) {
    return dataset.length * 100;
  })
  .duration(3000)
  .attr("stroke-dashoffset", 0);

/*add points*/
var points = svg.selectAll('circle')
  .data(dataset)
  .enter()
  .append('circle');

/*point attributes*/
points.attr('cy', function(d) {
    return yScale(d[1])
  })
  .style('opacity', 0)
  .transition()
  .duration(1000)
  .ease('elastic')
  .delay(function(d, i) {
    return i * 100;
  })
  .attr({
    'cx': function(d) {
      return xScale(d[0]);
    },
    'cy': function(d) {
      return yScale(d[1]);
    },
    'r': 5,
    'class': 'datapoint',
    'id': function(d, i) {
      return i;
    }
  })


.style('opacity', 1);

//  LINES INDIVIDUAL

//function drawIndividualLines (){

/*x scale*/
var xScaleIndividual = d3.scale.linear()
  .domain([0, d3.max(datasetIndividual, function(d) {
    return d[0];
  })])
  .range([padding, w - padding]);

/*y scale*/
var yScaleIndividual = d3.scale.linear()
  .domain([0, d3.max(datasetIndividual, function(d) {
    return d[1];
  })])
  .range([h - padding, padding]);

/*define line*/
var linesIndividual = d3.svg.line()
  .x(function(d) {
    return xScaleIndividual(d[0])
  })
  .y(function(d) {
    return yScaleIndividual(d[1])
  })
  .interpolate('monotone');

/*append line*/
var pathIndividual = svg.append('path')
  .attr({
    //'d': linesIndividual(datasetIndividual),
    'd': linesIndividual(dataset),
    'fill': 'none',
    'class': 'lineChartIndividual'
  });

/*get length*/
var lengthIndividual = svg.select('.lineChartIndividual').node().getTotalLength();

/*animate line chart*/
svg.select('.lineChartIndividual')
  .attr("stroke-dasharray", lengthIndividual + " " + lengthIndividual)
  .attr("stroke-dashoffset", lengthIndividual)
  .transition()
  .ease('linear')
  .delay(function(d) {
    return datasetIndividual.length * 100;
  })
  .duration(3000)
  .attr("stroke-dashoffset", 0);

/*add points*/
var pointsIndividual = svg.selectAll('circleIndividual')
  .data(dataset)
  .enter()
  .append('circle');

/*point attributes*/
pointsIndividual.attr('cy', function(d) {
    return yScale(d[1])
  })
  .style('opacity', 0)
  .transition()
  .duration(1000)
  .ease('elastic')
  .delay(function(d, i) {
    return i * 100;
  })
  .attr({
    'cx': function(d) {
      return xScale(d[0]);
    },
    'cy': function(d) {
      return yScale(d[1]);
    },
    'r': 5,
    'class': 'datapointIndividual',
    'id': function(d, i) {
      return i;
    }
  })


.style('opacity', 1);

我准备了一个小提琴,希望有人能够确定问题的根源:

https://jsfiddle.net/4vf6s6e9/

我会帮助你。我不经常发帖提问,并试图结合我上次经历中的建议。如果您需要我的任何内容来改进这篇文章,请随时告诉我。

提前多多感谢。

1 个答案:

答案 0 :(得分:1)

您正在绘制具有两个略微不同比例的线条。

var xScale = d3.scale.linear()
  .domain([0, d3.max(dataset, function(d) {
    return d[0];
  })])
  .range([padding, w - padding]);

/*y scale*/
var yScale = d3.scale.linear()
  .domain([0, d3.max(dataset, function(d) {
    return d[1];
  })])
  .range([h - padding, padding]);

/*x scale*/
var xScaleIndividual = d3.scale.linear()
  .domain([0, d3.max(datasetIndividual, function(d) {
    return d[0];
  })])
  .range([padding, w - padding]);

/*y scale*/
var yScaleIndividual = d3.scale.linear()
  .domain([0, d3.max(datasetIndividual, function(d) {
    return d[1];
  })])
  .range([h - padding, padding]);

这使得每条线的位置计算略有不同,并且该差异取决于两个数据集的范围之间的随机差异。

将相同的数据传递到两个比例(或者仅对两个线使用相同的比例)可以解决问题。这是一个更新的小提琴:https://jsfiddle.net/oa0rsvgc/