[英]How to programmatically trigger drag events with d3.js?
I wrote some code that uses a drag event for svg elements.我编写了一些代码,为 svg 元素使用拖动事件。 The code works fine and I would like to write some tests for it.代码运行良好,我想为它编写一些测试。 Instead of manually moving my mouse by hand I would like to programmatically trigger the dragstart
and drag
events with selection.dispatch :而不是手动手动移动我的鼠标,我想通过selection.dispatch以编程方式触发dragstart
和drag
事件:
svgSelection.dispatch('dragstart',{bubbles:true});
svgSelection.dispatch('drag',{bubbles:true});
However, the events do not seem to be fired.但是,这些事件似乎没有被触发。 Maybe I use the wrong event keys or need to include some additional option?也许我使用了错误的事件键或需要包含一些额外的选项?
I also tried to use following variants that did not help:我还尝试使用以下没有帮助的变体:
svgElement.dispatchEvent(new Event('drag', {bubbles:true}));
svgSelection.dispatch('mousedown.drag',{bubbles:true});
If I try如果我尝试
svgElement.on('mousedown.drag')()
I get an error我收到一个错误
Uncaught TypeError: Cannot read property 'ctrlKey' of null
at defaultFilter (drag.js?009f:10)
at mousedowned (drag.js?009f:51)
What is the right way to trigger the events 'start' and 'drag' used in following code?触发以下代码中使用的事件“开始”和“拖动”的正确方法是什么?
let offset = [0,0];
let drag = d3.drag()
.on('start', () => this.__dragStarted(d3, svgSelection, offset))
.on('drag', ()=> this.__dragged(d3, svgSelection, offset));
svgSelection.call(drag);
My test example:我的测试示例:
it('enableDragAndDrop', ()=>{
let element = document.createElement('svg');
let svgSelection = d3.select(element);
spyOn(sut, '__dragStarted');
spyOn(sut, '__dragged');
sut.enableDragAndDrop(svgSelection);
svgSelection.dispatch('dragstart',{bubbles:true});
svgSelection.dispatch('drag',{bubbles:true});
expect(sut.__dragStarted).toHaveBeenCalled();
expect(sut.__dragged).toHaveBeenCalled();
});
My code example:我的代码示例:
enableDragAndDrop(svgSelection){
let offset = [0,0];
let drag = d3.drag()
.on('start', () => this.__dragStarted(d3, svgSelection, offset))
.on('drag', ()=> this.__dragged(d3, svgSelection, offset));
svgSelection.call(drag);
}
__dragStarted(d3, svgSelection, offset){
if(!svgSelection.attr('transform')){
svgSelection.attr('transform','translate(0,0)');
}
let transform = svgSelection.attr('transform');
let translate = this.__extractTranslate(transform);
offset[0] = translate[0] - d3.event.x;
offset[1] = translate[1] - d3.event.y;
}
__dragged(d3, svgSelection, offset){
let x = d3.event.x + offset[0];
let y = d3.event.y + offset[1];
svgSelection
.attr('transform', 'translate(' + x + ', ' + y + ')');
}
__extractTranslate(transformString){
let stripped = transformString;
stripped = stripped.replace('translate(','');
stripped = stripped.replace(')','');
let numberStrings = stripped.split(',');
return numberStrings.map(numberString=>parseFloat(numberString));
}
Related questions:相关问题:
How to externally trigger d3 events 如何从外部触发 d3 事件
How to trigger event in JavaScript? 如何在 JavaScript 中触发事件?
dataTransfer is null when creating drag event programmatically 以编程方式创建拖动事件时,dataTransfer 为 null
Here is a work around that partially mocks d3 with jest:这是一个用玩笑部分模拟 d3 的解决方法:
import * as d3 from 'd3';
jest.mock('d3', ()=>{
let wrappedD3 = jest.requireActual('d3');
var d3Mock = {
drag: undefined,
event: wrappedD3.event,
select: wrappedD3.select,
__passedEventHandlers: []
};
d3Mock.drag = ()=>{
let dragMock = {
apply: ()=>{}
};
dragMock.on = (event, eventHandler)=>{
d3Mock.__passedEventHandlers.push(eventHandler);
return dragMock;
}
return dragMock;
};
return d3Mock;
});
Example usage in test:测试中的示例用法:
it('enableDragAndDrop', ()=>{
let element = document.createElement('svg');
document.body.appendChild(element);
let svgSelection = d3.select(element);
sut.enableDragAndDrop(svgSelection);
spyOn(sut, '__dragStarted');
let dragStartedHandler = d3.__passedEventHandlers[0];
dragStartedHandler();
expect(sut.__dragStarted).toHaveBeenCalled();
spyOn(sut, '__dragged');
let draggedHandler = d3.__passedEventHandlers[1];
draggedHandler();
expect(sut.__dragged).toHaveBeenCalled();
});
I will share a circle drag example on SVG, I hope it works for you我将分享一个关于 SVG 的圆形拖动示例,希望对你有用
svg.selectAll("circle")
.data(yourdata)
.enter()
.append("circle")
.attr("class", "nodes")
.attr("cx", function(d) { return d.x; }) // your data have x and y position
.attr("cy", function(d) { return d.y; })
.attr("r", "5px")
.call(d3.drag().on("drag", dragged)) // you're calling drag function from here
.attr("fill", "black");
function dragged(d) {
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = d3.event.y)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.