在 D3 中查找拖动距离



我有一组 D3 元素(它们恰好是文本节点,但我认为哪种元素无关紧要(,我已经将拖动行为附加到

paragraphs.enter().append("text")
.text(function (d, i) { return d })
.attr("x", function (d, i) { return (i + 1) * 32 })
.attr("y", function (d, i) { return (i + 1) * 16 })
.attr("fill", color)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))

我希望拖动行为知道用户自拖动启动以来拖动了多远。 目前,我在dragstarted中添加了一个标记初始位置的attr,然后在dragged期间检查当前位置并以这种方式计算。

有没有办法在不计算阻力事件的情况下找到自拖动start以来拖动的距离,只需直接从拖动事件中即可?我看过dx/dy,但它们似乎只从上次拖动事件开始计算,因此该值始终处于低个位数。

根据 API,这些是事件对象在拖动事件期间公开的字段:

  • 目标 - 关联的拖动行为。
  • type - 字符串 "start"、"drag" 或 "end";请参阅 drag.on。
  • 主题 - 拖动主题,由 drag.Subject 定义。
  • x
  • - 主题的新 x 坐标;请参阅 drag.container。
  • y
  • - 主题的新 y 坐标;请参见 drag.container。
  • DX - 自上一次拖动事件以来 X 坐标的变化。
  • dy - 自上一次拖动事件以来 y 坐标的变化。
  • 标识符 - 字符串"鼠标"或数字触摸标识符。
  • 活动 - 当前活动的拖动手势的数量(在开始和结束时,不包括此手势(。
  • 源事件 - 基础输入事件,例如鼠标移动或触摸移动。

如您所见,它们都不具有您正在寻找的价值。

但是,有一个简单的解决方案,可能不适合您,因为您清楚地说明了"不计算它"。

解决方案涉及获取"开始"侦听器的位置,并将其与"结束"侦听器的位置进行比较:

d3.drag().on("start", function(d) {
d.startX = d.x;
d.startY = d.y;
}).on("drag", function(d) {
d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}).on("end", function(d) {
console.log("x distance: " + (d.x - d.startX))
console.log("y distance: " + (d.y - d.startY))
})

这是一个简单的演示,拖着圆圈四处走动:

var svg = d3.select("svg");
var circle = svg.append("circle")
.datum({
x: 150,
y: 75
})
.attr("cx", function(d) {
return d.x
})
.attr("cy", function(d) {
return d.y
})
.attr("r", 10)
.attr("fill", "teal");
circle.call(d3.drag().on("start", function(d) {
d.startX = d.x;
d.startY = d.y;
}).on("drag", function(d) {
d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}).on("end", function(d) {
console.log("x distance: " + (d.x - d.startX))
console.log("y distance: " + (d.y - d.startY))
}))
svg {
border: 1px solid black;
}
.as-console-wrapper { max-height: 25% !important;}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

再次:我知道你说"没有计算",但由于你想要的东西没有原生属性,我认为值得展示它进行计算是多么简单。