我使用具有缩放和画笔功能的 d3.js 创建了一个多线图。所有功能都运行良好,除了当我刷新我的浏览器选项卡时,我在图表中完成的缩放/画笔被重置并且图表以其初始状态显示。 有什么方法可以使用任何 d3.js 函数记录缩放/画笔位置,并且每当我刷新浏览器页面时,我都可以看到上次缩放/画笔状态的图形。 附上我用于缩放和画笔的代码片段。
const brush = d3.brushX()
.extent([[0, 0], [this.width, this.height2]])
.on("brush end", () => {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") {
return;
} // ignore brush-by-zoom
const s = d3.event.selection || this.x2.range();
this.x.domain(s.map(this.x2.invert, this.x2));
legendDataLine.selectAll(".line").attr("d", (d: any) => line(d.values));
focus.select(".axis--x").call(d3.axisBottom(this.x));
this.svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(this.width / (s[1] - s[0]))
.translate(-s[0], 0));
});
const zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [this.width, this.height]])
.extent([[0, 0], [this.width, this.height]])
.on("zoom", () => {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") {
return;
} // ignore zoom-by-brush
const t = d3.event.transform;
this.x.domain(t.rescaleX(this.x2).domain());
legendDataLine.selectAll(".line").attr("d", (d: any) => line(d.values));
focus.select(".axis--x").call(d3.axisBottom(this.x));
context.select(".brush").call(brush.move, this.x.range().map(t.invertX, t));
});
最佳答案
想到了一种方法,使用 URL 查询字符串。在您的示例代码或规范的画笔和缩放示例中 here , 只有缩放变换的两个部分很重要:比例 (k
) 和 x
值。
我们可以记录每个缩放事件的x
和k
,并在URL查询字符串中添加或修改它们。我们不需要担心在画笔事件中执行此操作,因为画笔事件会触发缩放(并且每次缩放都会触发画笔)。为了避免无限循环,画笔引起的缩放事件被忽略:
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
因此,我们可以在此之前设置 URL 参数:
function zoomed() {
var t = d3.event.transform;
// Update url:
window.history.replaceState( {} , '', '?k='+t.k+"&x="+t.x )
// ... rest of zoom functionality
}
这会更新查询字符串和 URL,并且不会重新加载页面,还有其他选项可能会提供更好的兼容性但不那么简洁(如果我没记错的话这不适用于 IE) . 由于有许多更好的资源可用于设置查询字符串参数的方法,因此我不会在这里详细介绍。
现在我们应该在更新的 URL 中存储了 x
和 k
值。
使用更新后的 URL,重新加载页面将加载地址中包含缩放状态参数的页面。剩下的就是在页面加载时应用它们,当然,如果它们已设置的话。
加载数据并创建所有内容后,我们可以检查 URL 中是否提供了缩放参数并应用适当的缩放转换:
var url = (new URL(document.location)).searchParams;
if(url.has("k") && url.has("x")) {
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity.translate(+url.get("x"),0).scale(+url.get("k")));
}
我对 URL 的检索是基本的,我不会再详细说明如何提取参数(有关此方法的更多信息,请参阅 MDN)。如果存在 x
和 k
参数,它们将被强制转换为数字并用于创建 d3 缩放转换(使用 d3.zoomIdentity 作为基础),这是用于通过适当的变换触发缩放事件。通过这样做,存储在 URL 中的缩放参数用于在重新加载、后退、前进或使用更新的 URL 打开链接等时将图形更新到其最后状态。
因为这在 Stack Overflow 片段中可能不起作用,所以我创建了一个示例 here .
关于javascript - 有什么方法可以捕获缩放/刷过的 d3.js 多线图位置吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56983969/