【发布时间】:2021-12-04 02:20:44
【问题描述】:
我正在使用 d3 v6 开发可视化,它基本上使用一组条目来显示水平层。 可视化如下所示:
需要注意的是,随着层数的增加,一些层变得不可能看到适当的规模减少。所以我想做一个缩放(和平移)功能,但它只能在 Y 轴上工作。我进行了很多搜索,发现了本教程 (https://observablehq.com/@d3/x-y-zoom),从中我做了一些更改以适应我的可视化:
const svgHeight: any = d3.select(svgContainer.current).attr('height');
const yScaleGlobal = d3
.scaleLinear()
.domain([0, maxYValues])
.range([0, svgHeight - MARGINS.TOP - MARGINS.BOTTOM]);
const yAxis = d3.axisLeft(yScaleGlobal).tickFormat((d: any) => `${d} m`);
const gY = layerGroup.append('g').attr('class', 'y-axis');
// z holds a copy of the previous transform, so we can track its changes
let z = d3.zoomIdentity;
// set up the ancillary zooms and an accessor for their transforms
const zoomY = d3.zoom().scaleExtent([0.2, 5]);
const ty = () => d3.zoomTransform(gY.node());
gY.call(zoomY).attr('pointer-events', 'none');
drawViz();
const zoom = d3.zoom().on('zoom', function (e) {
const t = e.transform;
const k = t.k / z.k;
const point = center(e, this);
if (k === 1) {
// pure translation?
gY.call(zoomY.translateBy, 0, (t.y - z.y) / ty().k);
} else {
// if not, we're zooming on a fixed point
gY.call(zoomY.scaleBy, k, point);
}
z = t;
drawViz();
});
svg.call(zoom).call(zoom.transform, d3.zoomIdentity.scale(0.8)).node();
function drawViz() {
const yr = ty().rescaleY(yScaleGlobal);
yAxis.scale(yr);
gY.call(yAxis, yr);
if (data) updateLayers(data, yr);
}
function center(event, target) {
if (event.sourceEvent) {
const p = d3.pointers(event, target);
return [d3.mean(p, (d) => d[0]), d3.mean(p, (d) => d[1])];
}
return [svgWidth / 2, svgHeight / 2];
}
updateLayers 函数是这样的:
const updateLayers = (data: LAYER_COMPONENT_TYPE[], yScale) => {
const layerFill = getLayerFill(data);
const rects = layerGroup.selectAll('rect').data(data);
rects.exit().remove();
const newLayers = rects
.enter()
.append('rect')
.attr('x', 10)
.style('opacity', 0.5)
.attr('width', 300)
.style('stroke', '#101010')
.style('stroke-width', '1px');
newLayers
.merge(rects)
.style('fill', (d: LAYER_COMPONENT_TYPE) => {
if (!layerFill[`${d.fgdc_texture}.${d.from}`].url) {
return layerFill[`${d.fgdc_texture}.${d.from}`];
}
svg.call(layerFill[`${d.fgdc_texture}.${d.from}`]);
return layerFill[`${d.fgdc_texture}.${d.from}`].url();
})
.attr('y', (d: LAYER_COMPONENT_TYPE, i) => {
if (i === 0) return yScale(d.from);
return yScale(data[i - 1].to);
})
.attr('height', (d: LAYER_COMPONENT_TYPE, i) => {
return yScale(d.to - d.from);
});
};
缩放和平移效果很好,整个可视化效果也很好,但是 yScale 有一个奇怪的行为。矩形的高度在缩放或平移时超出比例(我已经意识到高度的异常等于 yScale 处“0 m”点的距离) here you can view the problem
无论如何,我可以弄清楚代码有什么问题或导致异常的原因。所以我需要一些帮助来解决这个问题
编辑 1: 我正在使用反应顺便说一句
【问题讨论】:
标签: javascript typescript svg d3.js data-visualization