D3.js 如何创建自定义转换?

D3.js 如何创建自定义转换?,d3.js,D3.js,问这个问题的一种方式可能是:我如何重构,使其符合d3约定?(代码也包括在下面) 也就是说,不是像我这样写: rotateTransition(line1, 90) 我更喜欢这样写: line1.transition().attr("rotation-around-origin", 90) 所以问题是:用我例子中的自定义转换扩展d3转换的正确方法是什么?或者:我将如何进行猴子修补“线”选择对象 附加问题:在第6-16行中,我创建了两个完全相同初始化的“行”选择。是否有d3方法根据另一个选择复制

问这个问题的一种方式可能是:我如何重构,使其符合d3约定?(代码也包括在下面)

也就是说,不是像我这样写:

rotateTransition(line1, 90)
我更喜欢这样写:

line1.transition().attr("rotation-around-origin", 90)
所以问题是:用我例子中的自定义转换扩展d3转换的正确方法是什么?或者:我将如何进行猴子修补“线”选择对象

附加问题:在第6-16行中,我创建了两个完全相同初始化的“行”选择。是否有d3方法根据另一个选择复制一个选择?类似于:
line2=line1.dup()

链接到上面的示例的源代码:

var centerX = centerY = 50
var radius = 200

var svg = d3.select("svg").attr("width", 600).attr("height",600)

var line1 = svg.append("line")
  .attr("x1", centerX)
  .attr("y1", centerY)
  .attr("x2", centerX + radius)
  .attr("y2", centerY);

var line2 = svg.append("line")
  .attr("x1", centerX)
  .attr("y1", centerY)
  .attr("x2", centerX + radius)
  .attr("y2", centerY);

line1.attr("transform", "translate(100,100) rotate(45 50 50)");

function rotateTransition(line, degrees) {

  var rotationString = function(angle, x1, x2) { return "rotate("+angle+" "+x1+" "+x2+")" };
  var retInterpolator, startAngle = 0, endAngle = degrees;
  var transformStart = line.attr("transform") ? line.attr("transform") : "";
  var curRotation = transformStart.match(/rotate\((\d+) /)

  if (curRotation)
    endAngle = parseInt(curRotation.pop()) + degrees;
  else
    transformStart += rotationString(0,line.attr("x1"),line.attr("y1"));

  var transformEnd = transformStart.replace(/(.*rotate\()(\d+)( .*)/,"$1"+endAngle+"$3")
      console.log(transformStart);
  console.log(transformEnd);
  line.transition()
  .duration(2000)
  .attrTween("transform", function() {
    return d3.interpolateString(transformStart, transformEnd);
  })
}

rotateTransition(line1, 90)
rotateTransition(line2, 45)

对于这两个问题,请在d3的
selection.call()
方法

在行旋转的情况下,您甚至不必更改
rotateTransition
的主体。您可以这样使用它:

line1.call(rotateTransition, 90)
实际上,唯一的区别是这种方法允许链接函数调用


如果您想更深入地了解一般教育,请查看d3源代码,了解如何实现
d3.svg.axis()
,因为在将轴应用于d3选择时,此
call()
方法是结合使用的。

谢谢,非常有用。我确实想挖得更深一些。接下来的问题是:使用selection.call()技术创建副本不是一个好方法,因为您必须为每个svg elm创建单独的帮助器方法(因为它们具有不同的属性),然后执行类似于
s.call(dup\u line)
s.call(dup\u循环)
的操作。我真正想要的是扩展选择的行为,这样我就可以对任何选择执行
s.dup
,并根据类型执行正确的操作。这需要改变d3的核心,还是有更好的方法来实现它?@Jonah我对你的第二个问题的想法不是完全重复,而是将设置属性的代码放入一个函数中。所以它是这样的:
var line1=svg.append(“line”).call(prepareLine)@Jonah Dup'ing像你描述的那样,有一个挑战,我不知道如何应对(除了你提到的,关于需要知道元素类型的挑战)。事实上,如果要克隆dom元素,则克隆的元素不会附加到dom。在jQuery中,这并不重要;元素可以不作为DOM的一部分而存在。在d3中,我不知道这是否可能,或者需要做些什么。我所见过的在d3中创建元素的唯一方法是通过
append
方法,根据定义,该方法需要一个父级。Re:您的第一条评论,我建议
s.dup
将是
.append(“”.call()
的缩写。我还可以看到提供其他可选参数,但我认为这个案例应该涵盖90%的用例。