在D3中,如何在转换运行时接收元素的当前X,Y坐标?

时间:2016-09-17 17:13:01

标签: d3.js svg

根据此answer,如何获得圆圈X&过渡发生时Y坐标?

2 个答案:

答案 0 :(得分:3)

您可以使用标准MutationObserver界面来侦听DOM的更改。 MutationObserver构造函数提供了一个回调,它将使用MutationRecord数组调用,其中包含有关发生的更改的详细信息。创建观察者实例后,您可以将其注册到特定节点的更改,例如您的圈子,并过滤您感兴趣的属性更改,例如cxcy,方法是将此配置提供给将启动侦听器的.observe()调用。

// Create a new MutationObserver.
// This one just logs changes to attributes.
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(m) {
    console.log(
      m.attributeName + 
      " -- old:" + m.oldValue +
      ", new: " + m.target.getAttribute(m.attributeName));
  });
});

// Start observing the circle node and listen for changes to attributes cx and cy
// while recording old values.
var config = {
  attributes: true,
  attributeOldValue: true,
  attributeFilter: ["cx","cy"]
};

observer.observe(circle.node(), config);

鉴于您链接的JSFiddle,一个工作示例可能如下所示:

var svg = d3.select("body")
    .append("svg")
    .attr("width", 200)
    .attr("height", 200);

var circle = svg.append("circle")
	.attr("id", "circ")
    .attr("cx", Math.random() * 200)
    .attr("cy", Math.random() * 200)
    .attr("r", 10 + "px")
    .transition().each("end", function () {
    		myTransf();
		});

var d = d3.select("div");
function myTransf() {
    d3.select("#circ").transition().duration(500)
        .attr("cx", Math.random() * 200) // change this to random 2px 
    	.attr("cy", Math.random() * 200) // change this to random 2px
        .each("end", function () {
        myTransf();
    });
}

// Create a new MutationObserver.
// This one just logs changes to attributes.
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(m) {
    console.log(
      m.attributeName + 
      " -- old:" + m.oldValue +
      ", new: " + m.target.getAttribute(m.attributeName));
  });
});

// Start observing the circle node and listen for changes to attributes cx and cy
// while recording old values.
var config = {
  attributes: true,
  attributeOldValue: true,
  attributeFilter: ["cx","cy"]
};

observer.observe(circle.node(), config);

// Stop observing once you are done
setTimeout(function() {
  observer.disconnect();
}, 5000);
<script src="http://d3js.org/d3.v3.js"></script>

如果您需要support IE <11,那么您运气不好,需要采用其他解决方案,例如the one提出的Mark

答案 1 :(得分:2)

您必须控制转换并编写自定义tween功能。这样您就可以控制每个动画步骤。这里有一些可运行的代码用自定义补间替换示例中的attrTween魔术。

&#13;
&#13;
var svg = d3.select("body")
    .append("svg")
    .attr("width", 200)
    .attr("height", 200);

var circle = svg.append("circle")
		.attr("id", "circ")
    .attr("cx", Math.random() * 200)
    .attr("cy", Math.random() * 200)
    .attr("r", 10 + "px");
    
myTransf();

function myTransf() {
    circle.transition()
    	.duration(500)
      .each("end", function () {
          myTransf();
      })
      .tween("move", function() {
        var self = d3.select(this),
            x = d3.interpolate(+self.attr('cx'), Math.random() * 200),
            y = d3.interpolate(+self.attr('cy'), Math.random() * 200);
        return function(t) {
          var cx = x(t),
              cy = y(t);
          self.attr("cx", cx);
          self.attr("cy", cy);
        };
      });
}
&#13;
svg {
    border:1px solid #ccc;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;