【问题标题】:how do you interpret the d3 event.x and event.y coordinates?你如何解释 d3 event.x 和 event.y 坐标?
【发布时间】:2020-10-31 12:45:28
【问题描述】:

我正在尝试在 d3 (v6.2) 中实现拖动事件,但在解释 d3 x 和 y 坐标时遇到了一些问题。考虑以下代码。当我检查控制台输出时,在我看来,在拖动处理程序中:

  • event.xevent.y 是用户(图形)坐标对象位置和 SVG 坐标中的总移动/距离的总和?

  • event.dxevent.dy 是指示自上次更新以来,您是否向左/向上移动 (-1)、未移动 (0) 或向右/向下 (1)?

  • event.subject.xevent.subject.y 给出被拖动对象的位置?

  • 如果我想要拖动的当前坐标(在用户/图形坐标或 SVG 坐标中),我需要自己计算它们(参见代码中的示例,这似乎有效)?

我找不到具体的文档记录在哪里。我的问题是:

  1. 上述印象是否正确?
  2. 如果不正确,获取当前拖动坐标的最佳方法是什么?
  3. 如果正确,为什么要对来自两个不同坐标系的值求和?这对我来说没有意义。
<html>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<svg width="500" height="300"></svg>

<style>
circle.circ {
  fill: red;
  stroke: black;
  stroke-width: 1px;
}
</style>

<script>

function dragHandler(e, d){
    
    const objx = scaleX.invert(e.x - d.x + scaleX(d.x))
    const objy = scaleY.invert(e.y - d.y + scaleY(d.y))

    console.log(`x: ${e.x}, dx: ${e.dx} sx: ${e.subject.x} objx: ${objx}\ny: ${e.y} dy: ${e.dy} sy: ${e.subject.y} objy: ${objy}`)
}

var drag = d3
 .drag()
 .on('drag', dragHandler)

var x = [{x: 150, y: 150}]

var svg = d3.select("svg")

var margin = {
  top: 20,
  right: 80,
  bottom: 30,
  left: 50
}
var width = svg.attr("width") - margin.left - margin.right
var height = svg.attr("height") - margin.top - margin.bottom

g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")")

var scaleX = d3.scaleLinear().range([0, width]).domain([140, 160])
var scaleY = d3.scaleLinear().range([height, 0]).domain([140, 160])

g.append("g")
  .attr("class", "axis axis--x")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(scaleX));

g.append("g")
  .attr("class", "axis axis--y")
  .call(d3.axisLeft(scaleY))

var circ = g.selectAll(".circ")
  .data(x)
  .enter()
  .append("circle")
  .attr("r", 5)
  .attr("cx", function(d) { return scaleX(d.x) })
  .attr("cy", function(d) { return scaleY(d.y) })
  .attr("class", "circ")
  .call(drag);

</script>

</body>
<html>

【问题讨论】:

  • 文档有点晦涩,但你可以找到它here
  • 我已经看到了,但是表格只是说“请参阅 drag.container”,然后在该部分中,它说“[t]拖动手势的容器决定了后续拖动事件的坐标系,影响 event.x 和 event.y”,我不清楚 - 它没有说明它是如何影响它的。我错过了什么吗?

标签: javascript svg d3.js


【解决方案1】:

你的印象是对的。你可以

  • 计算局部坐标中的距离作为event.x/yevent.subject.x/y之间的差

这两个工作在不同的坐标系中。

  • 客户端坐标系是浏览器视口的坐标系。它们只是从原生 DOM mousemove 事件中读取的。
  • 用户坐标系是被拖动的对象之一,使用的坐标与编写 SVG 标记时使用的坐标相同。它们是使用 SVG API 提供的 transform matrix 从客户端坐标计算得出的。源代码是here

您所做的是通常不需要的中间方式:通过应用scaleX/Y 变换,您计算了 SVG 视图框 系统中的坐标,即。 e.当viewBox 应用于最外层&lt;svg&gt; 元素时找到的坐标系。这可以是客户端坐标系,但前提是未设置属性,或者元素的widthheight 值与viewBox 的内容匹配。

在几乎所有实际用例中,两者都会有所不同。 SVG is just about that distinction 中的“可扩展”。像您一样省略viewBox 会剥夺您轻松扩展整个图形的可能性。

【讨论】:

  • 谢谢。我想我仍然不清楚为什么要添加来自两个系统的坐标?我这样做的原因之一是我想根据图形坐标限制拖动(例如,不能拖动 x=145 以下的形状)。有没有更好的方法来做到这一点?
【解决方案2】:

添加到上面@ccprog 的答案(这对我有用)。将.container(selection.node) 添加到您的drag 对象中也很有用。这使得坐标工作得很好。注意不要将selection 传递给selection.node(),而是传递给.container(...)

【讨论】:

    猜你喜欢
    • 2014-02-26
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 2019-05-15
    • 2016-04-21
    • 1970-01-01
    • 2017-01-22
    • 2010-09-09
    相关资源
    最近更新 更多