Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用d3.dispatch在d3组件之间广播事件_Javascript_Svg_D3.js - Fatal编程技术网

Javascript 使用d3.dispatch在d3组件之间广播事件

Javascript 使用d3.dispatch在d3组件之间广播事件,javascript,svg,d3.js,Javascript,Svg,D3.js,我目前正在创建一个可重用的d3组件库,并希望创建一个“交互层”组件,该组件基本上在我的可视化上创建一个svg矩形,然后将与它的交互广播给其他监听这些交互的组件,如mouseover、mousemove、click等 我一直遵循Mike Bostock的可重用d3图表模式(),虽然我可以在每个组件内部创建一个调度器来在内部分派事件,但我无法成功地让单独的组件侦听另一个组件的分派事件。所以基本上我希望我的库有一个调度器,所有组件在使用时都可以监听 我已经做了很多搜索,但还没有找到答案,甚至没有找到如

我目前正在创建一个可重用的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)
    
    
    链接组件以及测试分派事件的样板
    
    使用这种方法,您需要在单个位置注册整个命名空间中每个组件的每个事件,这对于复杂的应用程序来说无法很好地扩展。如果不同的组件公开相同类型的事件,您还将遇到名称冲突。