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
Post a Comment