title: Chart content overlaps axes with d3.js
body: <p>I'm using d3.js to create a graphical grid with 2 axis. Data is displayed using cells whose color will change based on the data value. An simple example is visible <a href="https://plnkr.co/edit/0xPTvK?p=preview" rel="nofollow">here</a>. The chart is created as an svg image. I have a problem with the clipping of the data area : when zooming and panning, the data overlaps the axes. You can see this in the provided example, by clicking on the chart content and dragging up or left.</p>
  
  <p>Does someone know how I can make the data to disappear under the axes?</p>
  
  <p>Here is the typescript code I used to create the chart:</p>
  
  <pre><code>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 &lt; 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) =&gt; item.line);
      let lineMax = d3.max(markers, (item) =&gt; item.line);
      let pointMin = d3.min(markers, (item) =&gt; item.point);
      let pointMax = d3.max(markers, (item) =&gt; 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', () =&gt; {
          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) =&gt; `cell${marker.line}-${marker.point}`)
        .attr('class', 'cell')
        .attr('transform', (marker) =&gt; `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) =&gt; `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);
  }
  </code></pre>