如何在 D3 中重用两个(或更多)链式转换序列

2024-03-12

我必须应用两个非常长的链式转换序列,它们主要在转换顺序上有所不同,并且我正在寻找一种紧凑的编码方式。

作为一个玩具示例,考虑序列顺序应该是的情况a,b,c,d,e,f,g,h and e,f,g,h,a,b,c,d。我已经尝试使用下面的代码,但它不起作用。请注意,转换可能具有不同的属性(delay, duration, ease等)并且它们可以应用于不同的属性(x, y, width, height or cx, cy, r等)和样式。例如,过渡a可以参考width, 过渡b to height, 过渡c to x, 过渡d to y, 过渡e to transform属性、转换f to color风格等等。

P.S.:这个问题与我的目标相同previous https://stackoverflow.com/questions/52459212/a-compact-way-to-code-chained-transitions-in-d3一个,但我使用了太多简单的编码案例,误导了答案。

有没有办法以紧凑的方式编码?

var t1 = d3
.transition() // transition "a" specifications 
...
.transition() // transition "b" specifications 
...
.transition() // transition "c" specifications 
...
.transition() // transition "d" specifications 
...
;
var t2 = d3
.transition() // transition "e" specifications 
...
.transition() // transition "f" specifications 
...
.transition() // transition "g" specifications 
...
.transition() // transition "h" specifications 
...
;
someelement1
.transition(t1).transition(t2); 
someelement2
.transition(t2).transition(t1); 

正如评论中所指出的,回答这个问题的原则与你之前的问题相同。在这种情况下,您有一组不同的转换,可以按不同键引用的任何顺序应用这些转换。让我们将它们存储在一个对象中:

var transitions = {
  a: function(sel){ return sel.transition().duration(1000).delay(1000).attr('cy', 200) },
  b: function(sel){ return sel.transition().duration(2000).delay(0).attr('r', 40) },
  c: function(sel){ return sel.transition().duration(500).delay(1500).attr('fill', 'red') },
  d: function(sel){ return sel.transition().duration(1500).delay(500).attr('opacity', 0.5) },
  e: function(sel){ return sel.transition().duration(1000).delay(3000).attr('cy', 300) },
  f: function(sel){ return sel.transition().duration(2000).delay(0).attr('r', 60) },
  g: function(sel){ return sel.transition().duration(500).delay(1500).attr('fill', 'magenta') },
  h: function(sel){ return sel.transition().duration(1500).delay(500).attr('opacity', 0.25) }
};

每个函数需要一个d3.selection对象并向其应用特定的转换参数和转换集。这些函数可以任意长、任意复杂。我很懒,想象力很少,所以他们在这个版本中只做了一次转换。

这里已经有一些代码重复了,所以我们把选择到转换的转换拿出来,并使用this而不是传递参数:

var transitions = {
  a: function(){ return this.duration(1000).delay(1000).attr('cy', 200) },
  b: function(){ return this.duration(2000).delay(0).attr('r', 40) },
  c: function(){ return this.duration(500).delay(1500).attr('fill', 'red') },
  d: function(){ return this.duration(1500).delay(500).attr('opacity', 0.5) },
  e: function(){ return this.duration(1000).delay(3000).attr('cy', 300) },
  f: function(){ return this.duration(2000).delay(0).attr('r', 60) },
  g: function(){ return this.duration(500).delay(1500).attr('fill', 'magenta') },
  h: function(){ return this.duration(1500).delay(500).attr('opacity', 0.25) }
};

现在我们可以通过调用类似的代码来执行这些转换

transitions['a'].call( selection.transition() )
transitions.f.call( d3.select('circle').transition() )

您想要指定要应用于选择的过渡数组,如下所示:

apply_transitions( group.select(":nth-child(1)"), ['a','b','c','d'] );
apply_transitions( group.select(":nth-child(2)"), ['e','f','g','h'] );

这可以按如下方式实施:

/**
* apply a series of transitions to a selection
*
* @param selection - d3 selection
* @param tr_arr - array of transition identifiers, referring to functions in the `transitions` object
*/
function apply_transitions( selection, tr_arr ) {

  // turn the current selection into a d3.transition
  // call the transition function referred to by the first ID in the array
  // with the d3.transition as the `this` context
  // note that the function returns a transition object, so it can be chained
  transitions[ tr_arr[0] ].call( selection.transition() )
  // add a handler to be applied at the end of the transition
    .on('end', function(){
      // if there are more transitions to be applied, call
      // apply_transitions again with tr_arr minus the first element
      // note that the `this` context in the `on` function is a DOM element,
      // so use `d3.select(this)` to turn it into a d3 selection
      if ( tr_arr.length > 1 ) {
        apply_transitions( d3.select(this), tr_arr.slice(1) );
      }
    })
}

真人动作示例:

    var svg = d3.select('svg').attr('width', 500).attr('height', 500);

    var dataSet = [20, 20];

    var group=svg.append("g");
    var circles = group.selectAll('circle')
    .data(dataSet)
    .enter()
    .append('circle')
    .attr("r",function(d){ return d })
    .attr("cx",function(d, i){ return i * 100 + 50 })
    .attr("cy",50)
    .attr("fill",'black');

    apply_transitions( group.select(":nth-child(1)"), ['a','b','c','d'] );

    apply_transitions( group.select(":nth-child(2)"), ['e','f','g','h'] );

  function apply_transitions( selection, tr_arr ) {

    var transitions = {
      a: function(){ return this.duration(1000).delay(1000).attr('cy', 200) },
      b: function(){ return this.duration(2000).delay(0).attr('r', 40) },
      c: function(){ return this.duration(500).delay(1500).attr('fill', 'red') },
      d: function(){ return this.duration(1500).delay(500).attr('opacity', 0.5) },
      e: function(){ return this.duration(1000).delay(3000).attr('cy', 300) },
      f: function(){ return this.duration(2000).delay(0).attr('r', 60) },
      g: function(){ return this.duration(500).delay(1500).attr('fill', 'magenta') },
      h: function(){ return this.duration(1500).delay(500).attr('opacity', 0.25) }
    };

      transitions[ tr_arr[0] ].call( selection.transition() )
        .on('end', function(){
          if ( tr_arr.length > 1 ) {
            apply_transitions( d3.select(this), tr_arr.slice(1) );
          }
        })
  }
<script src="http://d3js.org/d3.v5.js"></script>
<svg></svg>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 D3 中重用两个(或更多)链式转换序列 的相关文章

随机推荐

  • R - 如何将数据转换为块形式以进行弗里德曼测试?

    在此输入图像描述 https i stack imgur com N0cvs png我有一些与治疗前后血液中化学物质水平有关的数据 有 4 个治疗组 ABCD 有人告诉我可以运行弗里德曼测试来立即比较所有这些变量 我尝试过的代码是 atta
  • 如何限制极坐标的显示宽度,以便以清晰的方式打印宽数据帧?

    考虑下面的例子 pd set option display width 50 pl DataFrame data np random randint 0 20 size 10 42 columns list abcdefghijklmnop
  • EF 中的 CurrentDateTime()

    我使用这段代码来获取服务器日期 但我真的不明白 CreateDateTime 不是一个 sql 函数 那么它是什么 DateTime ServerDate Entities CreateQuery
  • Python matplotlib 减小颜色条标签的大小

    我需要你的帮助 我有一个绘图代码如下 fig plt figure ax1 fig add subplot 111 imax1 ax1 imshow data interpolation nearest origin lower cmap
  • Log4J - 类似 SiftingAppender 的功能

    我在一个使用的项目中工作Log4J http logging apache org log4j 1 2 index html 要求之一是为每个线程创建一个单独的日志文件 这本身就是一个奇怪的问题 通过动态创建一个新的 FileAppende
  • 在 Matlab 图中重叠两个轴

    我正在寻找一种方法来覆盖 x y 时间序列 比如用 plot 创建的 在 contourf 生成的显示之上 在 y 轴上具有不同的缩放比例 似乎在两个 x y 图的情况下执行此操作的典型方法是使用内置函数 plotyy 它甚至可以由 plo
  • 实体框架代码优先一对一必需-必需关系

    使用 Entity Framework Code First 4 3 1 时 可以创建具有多重性的 1 对 1 关系 也就是说 关系的每一端都有一个实体 可以将一对一关系配置为需要 需要 or 必需 可选 然而 当我在两者之间切换时 我没有
  • Spark - 它如何在节点周围分发数据?

    Spark如何将数据分发给worker 工作人员是从数据源读取数据 还是驱动程序读取数据并将其发送给工作人员 当一个工作人员需要另一个工作人员中的数据时 他们是否直接进行通信 Thanks 如果您使用分布式输入法 例如SparkContex
  • 如果对于屏幕来说太长,则使水平单选按钮换行

    所以我有以下单选按钮 我想让它们像这样显示 然而 出现这种情况 我怎样才能让它像上面那样显示 我可以在 Eclipse 中的 GUI 编辑器中移动它 但它会从 RadioGroup 中删除 RadioButton 在组内 它忽略所有其他布局
  • 对象初始值设定项和构造函数有什么区别?

    两者之间有什么区别 何时使用 对象初始值设定项 而不是 构造函数 反之亦然 我正在使用 C 如果这很重要的话 另外 对象初始值设定项方法是否特定于 C 或 NET 对象初始值设定项是 C 3 中添加的内容 目的是在使用对象时简化对象的构造
  • 强制抽象类属性由具体类实现

    考虑这个抽象类和实现它的类 from abc import ABC class FooBase ABC foo str bar str baz int def init self self bar bar self baz baz clas
  • 无论如何,在一个 neo4j 实例上有多个数据库?

    从关系数据库的思维方式来看 每个 Neo4j 实例只有一个图形数据库似乎很奇怪 我们的想法是从根开始创建多个子图吗 Thanks 根 节点的概念正在消失 这存在很多问题 其中大部分与节点密度有关 我相信您问题的核心在于数据库设计 以及拥有多
  • Eclipse 类似于:“无法确定 [项目名称]/[文件路径]/[文件名称] 的 URI”

    主要问题 我在 Eclipse Luna 上遇到以下错误 有一天 您上班并尝试启动 Eclipse 并提高工作效率 但是工作台一打开 您就会看到所有文件选项卡都出现错误 如下所示 无法确定 my project path to file f
  • 与 object.prop 相比,使用 `in` 有什么好处?

    我们都看到该功能检测到执行以下操作 var touch function return ontouchstart in window 但我想知道使用它是否还有其他好处in类似这样的操作符 这可以节省一些字节 var touch functi
  • 获取 JavaScript 对象的第一个键名称[重复]

    这个问题在这里已经有答案了 假设我们有以下 JavaScript 对象 ahash one 1 2 3 two 4 5 6 是否有一个函数可以返回给定对象的第一个键名称 从上面的例子我想得到one作为该功能的结果 在 JavaScript
  • netty ChannelInboundHandlerAdapter 将帧裁剪为 ~1500 字节

    我已经实现了一个服务器应用程序 它使用 netty 框架通过 ChannelInblundHandlerAdapter 读取传入的字节 如标题所示 我的问题是 我不定期地从客户端获取内容 我认为这些内容在 1 500 字节后被剪切 例如 在
  • OSGi 声明性服务的绑定顺序

    假设我使用 OSGi 声明性服务 并且我有一个服务 该服务具有多个带有策略 动态的引用 A 强制一元 B 强制一元 C 强制倍数 D 可选一元 E 可选的多个 当我的服务开始时 所有参考资料都可用 有没有办法控制bind的调用顺序 我想让
  • 即使在 webpack 配置中拆分后,供应商代码仍然位于 bundle.js 文件中

    使用下面的 webpack 配置 我仍然在 bundle js 文件中获取供应商代码 即使在代码分割之后 bundle js 的大小也保持不变 我希望供应商代码不应出现在bundle js 中 遵循某些链接 但没有帮助 https gith
  • 使用 array_map() 访问第一级键,而不调用 `array_keys()`

    有没有办法做这样的事情 test array array first key gt first value second key gt second value var dump array map function a b return
  • 如何在 D3 中重用两个(或更多)链式转换序列

    我必须应用两个非常长的链式转换序列 它们主要在转换顺序上有所不同 并且我正在寻找一种紧凑的编码方式 作为一个玩具示例 考虑序列顺序应该是的情况a b c d e f g h and e f g h a b c d 我已经尝试使用下面的代码