D3js纵向和横向自定义行显示在可缩放图表中溢出

时间:2016-07-21 16:04:32

标签: d3.js

对于我的项目,我不得不创建一个带有两组线的点图(第一条线对应于图表中的d3js轴坐标作为基本信息,另一条是具有特定十进制偏移的自定义线。

所以我在图中创建了我的轴X和Y以及相应的线,第二组线具有相应的X和Y坐标,最后是缩放。

结果,尽管我缩放/平移时第二组线条溢出图表,但一切正常。看起来线条只有在走出整个SVG元素时才会消失。

以下是代码:

let margin = { top: 8, right: 50, bottom: 22, left: 70 },
  width = 1140 - margin.left - margin.right,
  height = 560 - margin.top - margin.bottom;

let xScale = d3.scale.linear()
  .domain([0, this.area.length])
  .range([0, width]);

let yScale = d3.scale.linear()
  .domain([+(this.area.width / 2), -(this.area.width / 2)])
  .range([height, 0]);

let formatAxis = d3.format('.0f');

let xAxis = d3.svg.axis()
  .scale(xScale)
  .orient('bottom')
  .ticks(10)
  .tickFormat(formatAxis)
  .innerTickSize(-height)
  .outerTickSize(0)
  .tickPadding(10);

let yAxis = d3.svg.axis()
  .scale(yScale)
  .orient('left')
  .ticks(6)
  .tickFormat(formatAxis)
  .innerTickSize(-width)
  .outerTickSize(0)
  .tickPadding(10);

  // create the svg
let svg = d3.select('.chart').append('svg')
  .attr('width', width + margin.left + margin.right)
  .attr('height', height + margin.top + margin.bottom)
  .append('g')
  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

  // add X axis
svg.append('g')
  .attr('class', 'x axis')
  .attr('transform', 'translate(0,' + height + ')')
  .call(xAxis);

  // add Y axis
svg.append('g')
  .attr('class', 'y axis')
  .call(yAxis);

// function to create X lines
let make_x_line = (i: number) => {
  svg.append('line')
    .attr('y1', yScale(+(this.area.width / 2)))
    .attr('y2', yScale(-(this.area.width / 2)))
    .attr('x1', xScale(this.xValueData[i]))
    .attr('x2', xScale(this.xValueData[i]))
    .attr('class', 'xline' + i)
    .attr('stroke-dasharray', '5,5')
    .attr('stroke', 'black')
    .attr('stroke-width', 2.5)
    .attr('fill', 'none');
};

// function to create Y lines
let make_y_line = (i: number) => {
  svg.append('line')
    .attr('y1', yScale(this.yValueData[i]))
    .attr('y2', yScale(this.yValueData[i]))
    .attr('x1', xScale(0))
    .attr('x2', xScale(this.area.length))
    .attr('class', 'yline' + i)
    .attr('stroke-dasharray', '5,5')
    .attr('stroke', 'black')
    .attr('stroke-width', 2.5)
    .attr('fill', 'none');
};

// function zoom
let zoom = d3.behavior.zoom()
  .x(xScale)
  .y(yScale)
  .scaleExtent([1, 8])
  .on('zoom', () => {
    d3.select('.x.axis').call(xAxis);
    d3.select('.y.axis').call(yAxis);
    for (let i = 0; i < this.xValueData.length; i++) {
      d3.select('.xline' + i).attr('y1', yScale(+(this.area.width / 2)))
        .attr('y2', yScale(-(this.area.width / 2)))
        .attr('x1', xScale(this.xValueData[i]))
        .attr('x2', xScale(this.xValueData[i]));
    }
    for (let i = 0; i < this.yValueData.length; i++) {
      d3.select('.yline' + i).attr('y1', yScale(this.yValueData[i]))
        .attr('y2', yScale(this.yValueData[i]))
        .attr('x1', xScale(0))
        .attr('x2', xScale(this.area.length));
    }
  });

// lines for the grid selection and point creation in X
for (let i = 0; i < this.xValueData.length; i++) {
  make_x_line(i);
}

// // // lines for the grid selection and point creation in Y
for (let i = 0; i < this.yValueData.length; i++) {
  make_y_line(i);
}

svg.append('rect')
  .attr('width', width)
  .attr('height', height)
  .attr('fill', 'transparent')
  .attr('class', 'pane')
  .call(zoom)
  });

结果如下: normal chart

这是我缩放时的显示: zoomed chart

1 个答案:

答案 0 :(得分:0)

您应该使用clip path,将这些行添加到group也是一个好主意,因此处理它们会更容易。

所以我要做的是创建一个剪辑路径和垂直和水平线的新组,并设置clip-path属性。像这样:

svg.append('clipPath').attr('id', 'clip').append('rect').attr('x', 0).attr('y',0).attr('width', width).attr('height', height);
let verticalLines = svg.append('g').attr('clip-path', 'url(#clip)').attr('class', 'verticalLines');
let horizontalLines= svg.append('g').attr('clip-path', 'url(#clip)').attr('class', 'horizontalLines');

最后在你的循环中,你会将这些行添加到上面的组中,如下所示:

  let make_x_line = (i: number) => {
  verticalLines.append('line')
    .attr('y1', yScale(+(this.area.width / 2)))
    .attr('y2', yScale(-(this.area.width / 2)))
    .attr('x1', xScale(this.xValueData[i]))
    .attr('x2', xScale(this.xValueData[i]))
    .attr('class', 'xline' + i)
    .attr('stroke-dasharray', '5,5')
    .attr('stroke', 'black')
    .attr('stroke-width', 2.5)
    .attr('fill', 'none');
};