【问题标题】:Interrupt scrolling transitions in D3.js中断 D3.js 中的滚动转换
【发布时间】:2019-04-09 19:50:14
【问题描述】:

我正在使用 scrollama javascript 库来编写一篇“滚动讲述”文章,其中涉及在用户滚动时将 D3 图形移入和移出视图。它大部分都在工作,但如果我滚动得太快,这些图表就会堆积在一起。

Here is a jsfiddle 基于此example by the scrollama author。在我的示例中,彩色圆点应该一次淡入一个。如果您要快速滚动到最后,则不应出现间歇性点。以下 sn-ps 显示了我是如何设置转换的:

我定义了一些创建“图表”的函数,然后调用它们。

var makeCircle0 = function(){

  g.append("circle")
    .attr("cx", 50)
    .attr("cy", 100)
    .attr("r", 20)
    .attr("fill", "red")
    .attr("class", "redcircle")

  g.selectAll(".redcircle")
    .attr("opacity", 0)
}

makeCircle0();

// Do this for makeCircle1, 2, and 3, also. 

然后,我创建函数来处理转换。这个说让红色圆圈淡入并将其他圆圈设置为 0 不透明度。我对所有圈子/阶段都这样做。

var showCircle0 = function(){

  g.selectAll(".redcircle")
  .transition()
  .duration(1000)
  .attr("opacity", 1)

  g.selectAll(".yellowcircle").attr("opacity", 0)
  g.selectAll(".greencircle").attr("opacity", 0)
  g.selectAll(".bluecircle").attr("opacity", 0)

}

本部分创建了一个我的转换函数数组,以便我可以在您滚动时在页面中的特定步骤调用它们。这类似于Jim Vallandingham handled his scroller

var activateFunctions = [];
activateFunctions[0] = showCircle0;
activateFunctions[1] = showCircle1;
activateFunctions[2] = showCircle2;
activateFunctions[3] = showCircle3;

最后,这会在页面的正确步骤调用所需的函数。它确实......但并非没有停止在上一步中触发的其他转换,导致多个点出现在各个阶段。

function handleStepEnter(response) {
  step.classed('is-active', function (d, i) {
    return i === response.index;
  })

  figure.call(activateFunctions[response.index])
}

如何防止这种情况发生?

【问题讨论】:

  • 我认为this 是您正在寻找的东西(过渡与左侧的段并不完全一致,但圆圈与数字匹配)。这是正确的吗?
  • @AndrewReid 这太棒了!所以你所做的只是在开始任何新的转换之前先“interrupt()”?
  • 差不多 - interrupt() 将取消选择的任何转换。
  • 好吧,有趣。如果我有几个可能正在转换的课程(如 redcircle、yellowcircle 等),我将不得不中断所有课程?
  • 如果存在他们仍在过渡的风险 - 这就是为什么我使用 class 来选择它们并使用 id 来单独选择一个。

标签: d3.js scroll


【解决方案1】:

如果您需要中断转换,d3-transition 有一个方法:

selection.interrupt();

这将取消选择的过渡。 如果使用命名转换,您可以通过为中断提供一个参数来指定名称,该参数指示要取消的转换的名称。


如果这是显示元素的函数的通用版本:

function show() {
  selectionToHide.attr("opacity",0);

  selectionToShow.transition()
     .attr("opacity",1);
}

不使用 selection.interrupt 将不透明度设置为零,然后任何正在进行的转换的下一个刻度继续更新不透明度并完成转换。通过添加中断,我们避免了这种情况。这是更新后的fiddle

但是,还有另一种解决方案 - 我们可以对不想显示的元素应用另一种过渡。为此,我们只需将转换替换为新的:

function show() {
  selectionToHide.transition()
     .attr("opacity",0);

  selectionToShow.transition()
     .attr("opacity",1);
}

这将替换现有的未命名过渡(因为您的未命名)并淡出元素,而不是一次简单地隐藏它们。这是其中的fiddle当然,如果您有很多元素,则可以将其细化为仅对任何正在转换的元素(不是那些已经隐藏的元素)应用转换,以减少活动转换的数量。

我没有接触滚动,显示的圆圈应该有它的索引与显示的数字匹配,但似乎数字并不总是与滚动位置匹配,但这是一个单独的问题 em>

【讨论】:

  • 这太棒了!如果作为过渡的一部分有延迟(),这会起作用吗?
  • 应该 - 延迟是转换的一部分,如果替换或中断转换,您将删除整个先前的转换,包括延迟。
  • 我可以证明延迟不会影响任何事情 - here's 一个小提琴显示了中断和用新的转换替换。初始过渡会在延迟后修改半径,但它永远不会因为它被取消/替换而开始。
  • @GerardoFurtado,谢谢!唯一合适的是你的第 1000 个 - 如果我没记错的话,我相信我在 2 年前给了你你的,当时我还很新鲜。期待能够以骗子的身份关闭 - 通常在 d3 中只有不到 5 个常客,通常会等你上线并看到它。
  • @GerardoFurtado,我的意思只是普通的 d3 人金徽章或其他,很难在没有金币的情况下对一个骗子(或任何其他接近的理由)获得五票接近的门槛支持,因为常客很少。但是现在 Alto 也随时可以拿到金牌,希望家务管理会容易一些。
猜你喜欢
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 2016-12-10
  • 1970-01-01
相关资源
最近更新 更多