javascript - Constrain zoom and pan in d3 -


i'm trying correctly contrain zooming , scaling on d3-chart using d3's zoom behaviour. i've reduced problem following minimal runnable example. want user not able zoom in way allow him see below 0-line on y axis.

the sample works when in non-zoomed state, setting translateextent full height of svg, of course breaks user zooms in little. in fact, further zoom in, further you're able negative area.

what need set translateextent to?

the reason i'm redrawing line , axes on each zoom event i'm using react render svg , use d3 calculcations - have removed dependency on react provide more concise example.

const data = [ 0, 15, 30, 32, 44, 57, 60, 60, 85];    // set dimensions , margins  const full = { w: 200, h: 200 };  const pct = { w: 0.7, h: 0.7 };  const dims = { w: pct.w * full.w, h: pct.h * full.h };  const margin = { w: (full.w - dims.w)/2, h: (full.h - dims.h)/2 };    // scales  const x = d3.scalelinear()    .rangeround([0, dims.w])    .domain([0, data.length]);      const y = d3.scalelinear()    .rangeround([dims.h, 0])    .domain(d3.extent(data));    // axes  const axes = {    x: d3.axisbottom().scale(x).ticksize(-dims.w),    y: d3.axisleft().scale(y).ticksize(-dims.h)  }      const g = d3.select('.center');    // actual "charting area"  g    .attr('transform', `translate(${margin.w}, ${margin.h})`)    .attr('width', dims.w)    .attr('height', dims.h)      // x-axis  g.append('g')  .attr('transform', `translate(0, ${dims.h})`)  .attr('class', 'axis x')  .call(axes.x)    // y-axis  g.append('g')  .attr('class', 'axis y')  .call(axes.y)      // generator line  const line = d3.line()    .x( (_, i) => x(i) )    .y( d => y(d) );    // actual data path  const path = g    .append('path')    .attr('class', 'path')    .attr('d', line(data))    .attr('stroke', 'black')    .attr('fill', 'none')    const zoombehaviour = d3.zoom()    .scaleextent([1, 10])    .translateextent([[0,0], [infinity, full.h]])    .on('zoom', zoom);      d3.select('svg.chart').call(zoombehaviour);      function zoom() {    const t = d3.event.transform;        const scaledx = t.rescalex(x);    const scaledy = t.rescaley(y);    axes.x.scale(scaledx);    axes.y.scale(scaledy);    d3.select('.axis.x').call(axes.x);    d3.select('.axis.y').call(axes.y);        line      .x( (_, i) => scaledx(i) )      .y( d => scaledy(d) );        const scaledpath = path.attr('d', line(data));  }
body {    width: 200px;    height: 200px;  }    svg.chart {    width: 200px;    height: 200px;    border: 1px solid black;  }    .axis line, .axis path {    stroke: grey;  }
<script src="https://d3js.org/d3.v4.js"></script>  <body>  <svg class="chart">    <g class="center"></g>  </svg>  </body>

check out zoomed function in this example mike bostock believe want, key part mutation of t.x and/or t.y if there's breach of constraints:

function zoomed() {     var t = d3.event.transform;     if (t.invertx(0) > x0) t.x = -x0 * t.k;     else if (t.invertx(width) < x1) t.x = width - x1 * t.k;     if (t.inverty(0) > y0) t.y = -y0 * t.k;     else if (t.inverty(height) < y1) t.y = height - y1 * t.k;     g.attr("transform", t); } 

Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

.htaccess - ERR_TOO_MANY_REDIRECTS htaccess -