我正在使用 D3 来设置利用可缩放行为的图表区域。该图表包括 x 轴和 y 轴。
调整窗口大小时,图表区域应该响应。在这种情况下,我需要在调整窗口大小时重置 x 和 y 轴域和范围。
问题发生在窗口大小调整上。在执行以下步骤后,我注意到缩放焦点不再与鼠标对齐:
之后,就出现了上面的问题。请参阅以下有此问题的 jsfiddle。
那么处理这个的正确方法是什么?我注意到一些关于这个问题的讨论,例如:
d3 Preserve scale/translate after resetting range
我尝试了这种方法,但我无法使用 D3 V4 API 使其工作。
最佳答案
主要思想是使用 window.addEventListener
更新情节:
window.addEventListener('resize', () => {
// obtain the current transformation by calling the `d3.zoomTransform` function
const t0 = d3.zoomTransform(
chart.node());
// obtain the client width by evaluating the `div` (class: `zoom-chart`)
width = document.getElementById('zoom-chart').clientWidth;
height = 480;
// update the base scale
baseX.range([0, width])
.interpolate(d3.interpolateNumber);
baseY.range([height, 0])
.interpolate(d3.interpolateNumber);
// update the view port
vb = [0,0, width,height];
chart
.attr('viewBox', vb);
// replot with the original transform
chart.call(zoom.transform, t0);
});
我还在这里添加了整个解决方案:const data = [
{x:1 , y:1},
{x:9 , y:1},
{x:9 , y:9},
{x:1 , y:9},
];
var width = document.getElementById('zoom-chart').clientWidth;
var height = 480;
var baseX = d3.scaleLinear().domain([0,10])
.range([0, width])
.interpolate(d3.interpolateNumber);
var baseY = d3.scaleLinear().domain([0,10])
.range([height, 0])
.interpolate(d3.interpolateNumber);
var scaleX = baseX;
var scaleY = baseY;
const zoom = d3.zoom()
.on('zoom', () => {
const transform = d3.event.transform;
scaleX = transform.rescaleX(baseX)
.interpolate(d3.interpolateNumber)
scaleY = transform.rescaleY(baseY)
.interpolate(d3.interpolateNumber)
render();
});
const chart = d3.select('#zoom-chart')
.append('svg')
.attr('class', 'chart')
.call(zoom);
const rect = chart
.append('rect')
.attr('rx', 10).attr('ry', 10)
.attr('x', 10).attr('y', 10)
.attr('fill', '#00222b')
.attr('width', width-20)
.attr('height', height-20);
const plot = chart
.append('g')
.attr('class', 'plot-area');
function render() {
plot.selectAll('.data')
.data(data)
.join(
enter => enter.append('circle')
.attr('class', 'data')
.attr('r', 10)
.attr('stroke', '#004455')
.attr('stroke-width', 5),
update => update,
exit => exit.remove()
)
.attr('cx', d => scaleX(d.x))
.attr('cy', d => scaleY(d.y));
}
window.addEventListener('resize', () => {
const t0 = d3.zoomTransform(
chart.node());
width = document.getElementById('zoom-chart').clientWidth;
height = 480;
baseX.range([0, width])
.interpolate(d3.interpolateNumber);
baseY.range([height, 0])
.interpolate(d3.interpolateNumber);
vb = [0,0, width,height];
chart
.attr('viewBox', vb);
rect
.attr('width', width-20)
.attr('height', height-20);
chart.call(zoom.transform, t0);
});
let vb = [0,0, width,height];
chart
.attr('viewBox', vb);
chart.call(zoom.transform, d3.zoomIdentity);
<script src="https://unpkg.com/d3@5.15.0/dist/d3.min.js"></script>
<div id="zoom-chart" class="chart large">
</div>
关于javascript - 调整窗口大小时的 d3 缩放行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39735367/