图表内容与d3.js重叠轴

时间:2016-09-13 08:34:10

标签: d3.js svg

我正在使用d3.js创建一个2轴的图形网格。使用其颜色将根据数据值改变的单元格显示数据。一个简单的例子是可见here。该图表创建为svg图像。剪切数据区时遇到问题:缩放和平移时,数据与轴重叠。您可以在提供的示例中看到此信息,方法是单击图表内容并向上或向左拖动。

有人知道如何让数据在轴下消失吗?

以下是我用来创建图表的打字稿代码:

let cellSize = 49;
let borderSize = 5;
let margin = { top: 40, right: 40, bottom: 40, left: 40 };

function createChart() {
    // Create test data
    let count = 500;
    let perLine = 50;
    let markers = [];
    for (let i = 0; i < count; i++) {
        let id = i + 1;
        let line = Math.floor(i / perLine) + 1;
        let point = i % perLine + 1;
        markers.push({id: id, line: line, point: point});
    }
    //---

    let lineMin = d3.min(markers, (item) => item.line);
    let lineMax = d3.max(markers, (item) => item.line);
    let pointMin = d3.min(markers, (item) => item.point);
    let pointMax = d3.max(markers, (item) => item.point);

    let chart = document.querySelector('.chart');

    let viewWidth = chart.clientWidth - 2;
    let viewHeight = 400;
    let chartWidth = cellSize * (pointMax - pointMin + 1);
    let chartHeight = cellSize * (lineMax - lineMin + 1);

    let point = d3.scale.linear()
          .domain([pointMin, pointMax])
          .range([cellSize / 2, chartWidth - cellSize / 2]);

    let line = d3.scale.linear()
      .domain([lineMin, lineMax])
      .range([cellSize / 2, chartHeight - cellSize / 2]);

    let pointAxis = d3.svg.axis()
      .scale(point)
      .tickSize(0)
      .tickValues(d3.range(pointMin, pointMax + 1))
      .orient('top');

    let lineAxis = d3.svg.axis()
      .scale(line)
      .tickSize(0)
      .tickValues(d3.range(lineMin, lineMax + 1))
      .orient('left');

    let zoom = d3.behavior.zoom()
      .x(point)
      .y(line)
      .scaleExtent([0.1, 1])
      .on('zoom', () => {
        let width = Math.min(viewWidth - margin.left - margin.right, chartWidth);
        let height = Math.min(viewHeight - margin.top - margin.bottom, chartHeight);
        let t = zoom.translate();
        let tx = Math.min(t[0], 0);
        tx = Math.max(tx, width - chartWidth);
        let ty = Math.min(t[1], 0);
        ty = Math.max(ty, height - chartHeight);
        zoom.translate([tx, ty]);
        let scale = zoom.scale();

        svg.select('.x.axis').call(pointAxis).selectAll('text')
          .attr('x', -3)
          .attr('y', 5)
          .attr('transform', 'rotate(90)')
          .style('text-anchor', 'end');
        svg.select('.y.axis').call(lineAxis);

        grid.attr('transform', `translate(${[tx, ty]})scale(${scale})`);
      });

    let svg = d3.select('.chart').append('svg')
      .attr('id', 'svg')
      .attr('width', viewWidth)
      .attr('height', viewHeight)
      .append('g')
      .attr('transform', `translate(${margin.left}, ${margin.top})`)
      .call(zoom);

    let grid = svg.append('g')
        .attr('id', 'grid');

    // Add the grid background
    grid.append('rect')
      .attr('class', 'grid')
      .attr('x', 0)
      .attr('y', 0)
      .attr('width', chartWidth)
      .attr('height', chartHeight);

    // Create the cells
    let cell = grid.selectAll('.cell')
      .data(markers).enter()
      .append('g')
      .attr('id', (marker) => `cell${marker.line}-${marker.point}`)
      .attr('class', 'cell')
      .attr('transform', (marker) => `translate(${point(marker.point) - cellSize / 2}, ${line(marker.line) - cellSize / 2})`);

    cell.append('rect')
      .attr('class', 'border')
      .attr('x', 0)
      .attr('y', 0)
      .attr('width', cellSize)
      .attr('height', cellSize);

    cell.append('rect')
      .attr('class', (marker) => `fill valid`)
      .attr('x', borderSize)
      .attr('y', borderSize)
      .attr('width', cellSize - 2 * borderSize)
      .attr('height', cellSize - 2 * borderSize);

    cell.append('rect')
      .attr('class', 'selection')
      .attr('x', 0)
      .attr('y', 0)
      .attr('width', cellSize)
      .attr('height', cellSize);

    // Add the axes
    svg.append('g')
      .attr('class', 'x axis')
      .call(pointAxis)
      .selectAll('text')
      .attr('x', -3)
      .attr('y', 5)
      .attr('transform', 'rotate(90)')
      .style('text-anchor', 'end');

    svg.append('g')
      .attr('class', 'y axis')
      .call(lineAxis);
}

1 个答案:

答案 0 :(得分:1)

如果你不需要实际使用clipPath,你可以在添加轴之前为这样的x轴添加一个简单的bg。

  // Add bg for x axis
  svg.append('rect')
    .attr('height', 30)
    .attr('y', -25)
    .attr('fill', 'white')
    .attr('width', chartWidth);

Plunkr:https://plnkr.co/edit/tVZb7YEaDTMZaFX4Nod3?p=preview