我尝试使用d3的缩放行为正确地在d3图表上缩放缩放和缩放。我已将问题减少到以下最小的可运行示例。我希望用户无法放大,这样他就可以看到y轴上的0线以下。
当处于非缩放状态时,通过将translateExtent
设置为svg的完整高度,该示例可以正常工作,但是当用户放大一点时,该示例当然会中断。实际上,您放大的距离越远,您就可以进一步查看负面区域。
我需要将translateExtent
设置为?
我在每个缩放事件上重新绘制直线和轴的原因是我通常使用react来渲染我的svg并仅使用d3进行计算 - 但我已经删除了对反应提供的依赖性一个更简洁的例子。
const data = [ 0, 15, 30, 32, 44, 57, 60, 60, 85];
// set up dimensions and 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 for the line
const line = d3.line()
.x( (_, i) => x(i) )
.y( d => y(d) );
// the 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>
&#13;
答案 0 :(得分:4)
我能够根据罗伯特提出的建议让它发挥作用。我必须调整条件以适应我的用例:
const dims = /* object holding svg width and height */;
const [xMin, xMax] = this.scales.x.domain().map(d => this.scales.x(d));
const [yMin, yMax] = this.scales.y.domain().map(d => this.scales.y(d));
if (t.invertX(xMin) < 0) {
t.x = -xMin * t.k;
}
if (t.invertX(xMax) > dims.width) {
t.x = xMax - dims.width * t.k;
}
if (t.invertY(yMax) < 0) {
t.y = -yMax * t.k;
}
if (t.invertY(yMin) > dims.height) {
t.y = yMin - dims.height * t.k;
}
答案 1 :(得分:1)
查看this example by Mike Bostock中的zoomed
功能,我认为该功能符合您的要求,关键部分是t.x
和/或t.y
的变异,如果有的话#39} ;违反约束条件:
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);
}