我正在玩d3.js,我注意到拖动时出现了怪异的行为。 如果我使用data和scaleX / scaleY添加一个圆,则将其拖动时,d3.event.y值相对于“数据”数组中的xy坐标,而不是左上角...
这是代码和jsFiddle:如果打开控制台,则如果拖动第一个圆圈,则参考是左上角,如果拖动第二个圆圈,则参考是与{x: 3,y:2}
var circle2 = svgGraph
.selectAll('.circle2')
.data([{ x: 3, y: 2 }])
.enter()
.append('circle') // Uses the enter().append() method
.attr('cx', scaleX(100))
.attr('cy', scaleY(100))
.attr('r', 15)
.call(d3.drag()
.on('start', (d) => { })
.on('drag', onHandlerDrag())
.on('end', (d) => { }));
function onHandlerDrag() {
return (d) => {
console.log(d3.event.y);
}
}
这是故意的行为吗?您对此有什么参考吗?
谢谢
答案 0 :(得分:1)
是的,这是预期的行为。实际上,我们通常在拖动事件中使用这些x
和y
属性,以避免容器周围元素 jumping (当人们足够懒惰以指定正确的主题时)
自从您寻求参考以来,请查看drag.subject
:
拖动手势的主题表示被拖动的物体。在拖动手势开始前立即收到启动输入事件(例如,鼠标按下或触摸启动)时进行计算。
然后,在下一段中,对您来说最重要的信息:
默认主题是接收到初始输入事件的原始选择中元素的数据(请参见拖动);如果未定义此基准,则创建一个表示指针坐标的对象。在SVG中拖动圆元素时,默认主题就是要拖动的圆的原点。 (强调我的)
最后:
返回的主题应该是暴露
x
和y
属性的对象,以便在拖动手势期间可以保留主题和指针的相对位置。
因此,如果您不希望x
使用基准中的y
和drag
,只需在主题中设置另一个对象:
.subject(function() {
return {
foo: d3.event.x,
bar: d3.event.y
};
})
这是您所做的更改的代码:
function onHandlerDrag() {
return (d) => {
console.log(d3.event.y);
}
}
var scaleX = d3
.scaleLinear()
.domain([0, 500])
.range([0, 500]);
var scaleY = d3
.scaleLinear()
.domain([0, 500])
.range([0, 500]);
var svgGraph = d3
.select('.area')
.attr('width', 500)
.attr('height', 500);
var circle1 = svgGraph
.append('circle')
.attr('cx', scaleX(20))
.attr('cy', scaleY(20))
.attr('r', 15)
.call(d3.drag()
.on('start', (d) => {})
.on('drag', onHandlerDrag())
.on('end', (d) => {}));
var circle2 = svgGraph
.selectAll('.circle2')
.data([{
x: 3,
y: 2
}])
.enter()
.append('circle') // Uses the enter().append() method
.attr('cx', scaleX(100))
.attr('cy', scaleY(100))
.attr('r', 15)
.call(d3.drag()
.subject(function() {
return {
foo: d3.event.x,
bar: d3.event.y
};
})
.on('start', (d) => {})
.on('drag', onHandlerDrag())
.on('end', (d) => {}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg class='area'></svg>