Javascript 使用d3.dispatch在d3组件之间广播事件
我目前正在创建一个可重用的d3组件库,并希望创建一个“交互层”组件,该组件基本上在我的可视化上创建一个svg矩形,然后将与它的交互广播给其他监听这些交互的组件,如mouseover、mousemove、click等 我一直遵循Mike Bostock的可重用d3图表模式(),虽然我可以在每个组件内部创建一个调度器来在内部分派事件,但我无法成功地让单独的组件侦听另一个组件的分派事件。所以基本上我希望我的库有一个调度器,所有组件在使用时都可以监听Javascript 使用d3.dispatch在d3组件之间广播事件,javascript,svg,d3.js,Javascript,Svg,D3.js,我目前正在创建一个可重用的d3组件库,并希望创建一个“交互层”组件,该组件基本上在我的可视化上创建一个svg矩形,然后将与它的交互广播给其他监听这些交互的组件,如mouseover、mousemove、click等 我一直遵循Mike Bostock的可重用d3图表模式(),虽然我可以在每个组件内部创建一个调度器来在内部分派事件,但我无法成功地让单独的组件侦听另一个组件的分派事件。所以基本上我希望我的库有一个调度器,所有组件在使用时都可以监听 我已经做了很多搜索,但还没有找到答案,甚至没有找到如
我已经做了很多搜索,但还没有找到答案,甚至没有找到如何做的提示,如果有人有任何想法,我将不胜感激。因此我意识到,我可以通过在我的库名称空间下保存对d3.dispatch的引用,并在我的组件内部使用它来关联彼此的事件来实现这一点 像这样
namespace = {}
namespace.dispatch = d3.dispatch('mousemove');
//Interactive layer component
namespace.dispatch.mousemove(args)
//Other components listening for events
namespace.dispatch.on('mousemove', function(args){
//do something here
})
然后在我的交互层组件中,我分派事件,在另一个组件中,我监听它。这里有一种方法,可以将事件直接与d3组件关联,而不是强制您在全局命名空间中注册每个事件 广播事件的组件可能如下所示:
namespace.interactiveLayer = function() {
dispatch = d3.dispatch('myEvent');
me = function() {
// ...
svg.on('click', function() {
pos = d3.mouse(this);
dispatch.myEvent(pos);
});
};
me = d3.rebind(me, dispatch, 'on')
return me;
};
namespace.listenerLayer = function() {
me = function() {
interactive = namespace.interactiveLayer();
d3.select("body").call(interactive);
interactive.on('myEvent', function(d) {
alert('You clicked on ' + d);
});
};
return me;
};
侦听事件的组件可能如下所示:
namespace.interactiveLayer = function() {
dispatch = d3.dispatch('myEvent');
me = function() {
// ...
svg.on('click', function() {
pos = d3.mouse(this);
dispatch.myEvent(pos);
});
};
me = d3.rebind(me, dispatch, 'on')
return me;
};
namespace.listenerLayer = function() {
me = function() {
interactive = namespace.interactiveLayer();
d3.select("body").call(interactive);
interactive.on('myEvent', function(d) {
alert('You clicked on ' + d);
});
};
return me;
};
我提出了一个充实的解决方案。我遇到了一个类似的问题,并使用以下设计原则解决了它:
调用的契约
//这是我的可重用组件
var myown={};
myown.brush=函数(){
//设置私有变量
var高度,调度员;
职能(我的小组){
每组(功能(d,i){
//下面是创建笔刷的代码
//注“this”也可用于(除d和i之外),例如。
var b=d3。选择(本);
控制台日志(“我的每个内部”+高度);
if(调度员){
调度程序调用(“test1”);
}
});
}
my.move=功能(组、位置){
console.log(“在移动功能中”);
每组(功能(d,i){
//下面是移动笔刷的代码
//注“this”也可用于(除d和i之外),例如。
VarB=d3。选择(这个),那个=这个;
控制台日志(“每个内部移动”);
console.log(typeof(position));//注意它是函数
//现在调用这个函数
//使用“应用”和“参数”
设pos=position.apply(即参数);
控制台日志(pos);
if(调度员){
调度程序调用(“test2”);
}
})
归还我的;
}
my.height=函数(值){
if(!arguments.length)返回值;
高度=+值;
归还我的;
}
my.dispatcher=函数(值){
如果(!arguments.length)返回分派?true:false;
调度器=值;
归还我的;
}
归还我的;
};
//编排器创建分派,调用者
var myDispatch=d3.dispatch(“test1”、“test2”);
on(“test1”,function()){
log(“test1已被调用!!!”;
//在此处调用其他组件的公共函数(例如类似于brush.move)
});
on(“test2”,function()){
log(“现在,test2也被称为!!!”;
//在此处调用其他组件的公共函数(例如类似于brush.move)
});
//好的,现在使用所有这些好代码
风险值数据=[
{id:1,mv:[100500]},
{id:2,mv:[300600]},
{id:3,mv:[8001000]}
];
//orchestrator设置实例化期间创建的分派
var brush=myown.brush().height(90).dispatcher(myDispatch);
var svg=d3.选择(“svg”);
var g=svg.selectAll(“g”).data(data).enter()
.附加(“g”)
.attr(“转换”(transform),(d,i)=>“转换(0,+i*100+)”;
g、 呼叫(刷子)。呼叫(刷子移动,(d,i)=>d.mv)代码>
链接组件以及测试分派事件的样板
使用这种方法,您需要在单个位置注册整个命名空间中每个组件的每个事件,这对于复杂的应用程序来说无法很好地扩展。如果不同的组件公开相同类型的事件,您还将遇到名称冲突。