首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与d3可重用模式的交互性

与d3可重用模式的交互性
EN

Stack Overflow用户
提问于 2015-02-16 23:22:35
回答 2查看 584关注 0票数 1

在D3中:

我试图使用可重用图表模式实现一个图表,它允许我添加在实际图表之外处理的事件。例如,我有一个简单的条形图,在那里我可以点击每个单独的条形图。现在,我希望能够从创建图表实例的地方处理它,而不是仅仅处理图表组件中的单击事件。例如,我希望编辑与单击的bar元素相对应的数据,或者根据我单击的条形图的位置更新其他元素的位置。为了尽可能保持图表组件的模块化和独立性,我不希望在其中完成某些任务。

我想出了一个非常直截了当的解决方案,但我觉得必须有一个更好的解决方案。通过这种方式,我必须解释外部世界可能感兴趣的每一个可能的事件。JSFiddle

代码语言:javascript
复制
function clickHandler(d, i) {
  // do something with the element/event/data
}

var svg = d3.select('#container')
  .append('svg');

var myChart = chart()
    .onClick(clickHandler);

svg.append('g')
  .datum(data)
  .call(chart);

function chart() {
  var onClick = function() {};

  function _chart(selection) {
    selection.each(function(d, i) {

      selection.selectAll('rect')
        .data(d)
        .enter()
        .append('rect')
        .attr('x', 0)
        .attr('y', function(d, i) {return i * 11;})
        .attr('width', function(d, i) {return d;})
        .attr('height', 10);
        .on('click', _onClick);

    });
  }

  function _onClick(d, i) {
    d3.select(this)
      .attr('fill', 'red');

    onClick(d, i);
  }

  _chart.onClick = function(_) {
    if(!arguments.length) return onClick;
    onClick = _;
    return _chart;
  }

  return _chart;
}

是否有任何标准的方法/最佳实践来处理这种情况?还是说这不是一种普遍的情况?

任何帮助都很感激!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-17 07:30:47

您要寻找的是在核心应用程序代码和可以重用的代码之间创建一个分离。这是一个好主意,因为它使应用程序的代码保持较小,使您更容易更改它并将其向前移动。在可重用的图表中,您希望发送一个非常通用的事件,例如clicked,而在应用程序中,您需要这些事件非常特定于您的域,例如addSugar

你需要两种原料:d3.dispatchd3.rebind。前者帮助您创建一个清晰的内部API,而后者帮助您将分派的事件公开给外部世界。

到这里来找这个的示例。你想要寻找的是三件事:

  1. 在可重用的图表中,您创建一个调度器,其中包含要发布到外部世界的事件:var myDispatch = d3.dispatch('myclick', 'mydrag')
  2. 然后在可重用图表的事件处理程序中发布如下所示的事件:myDispatch.myclick(argumentsyouwanttopass)
  3. 作为最后一步,您使这些事件对外部可用:return d3.rebind(_chart, myDispatch, "on");
  4. 然后可以绑定到外部的这些事件:myChart.on('myclick', function(){})

因此,重写的示例如下所示:

代码语言:javascript
复制
function chart() {
  var dispatch = d3.dispatch('click');

  function _chart(selection) {
    selection.each(function(d, i) {

      selection.selectAll('rect')
        .data(d)
        .enter()
        .append('rect')
        .attr('x', 0)
        .attr('y', function(d, i) {return i * 11;})
        .attr('width', function(d, i) {return d;})
        .attr('height', 10);
        .on('click', dispatch.click);

    });
  }

  return d3.rebind(_chart, dispatch, 'on');
}

附加注意:要注册多个事件处理程序,您需要命名它们(就像常规d3事件一样),例如chart.on('click.foo', handlerFoo)chart.on('click.bar', handlerBar)等。

票数 6
EN

Stack Overflow用户

发布于 2015-02-16 23:47:58

让它更可重用和适用于任何可能的事件的一个想法是定义一个handler数组。这类似于d3本身。这是一个更新小提琴

代码语言:javascript
复制
function chart() {
  var event_handlers = {}; //key value pairs

  function _chart(selection) {
    selection.each(function(d, i) {

      var rects = selection.selectAll('rect')
        .data(d)
        .enter()
        .append('rect')
        .attr('x', 0)
        .attr('y', function(d, i) {return i * 11;})
        .attr('width', function(d, i) {return d;})
        .attr('height', 10);

        for(var event in event_handlers){
          rects.on(event, event_handlers[event])
        }

    });
  }

  _chart.on = function(event, fun) {
    if(arguments.length==1) return event_handlers[event];
    event_handlers[event] = fun;
    return _chart;
  }

  return _chart;
}

您可以使用chart的方式与使用HTML元素的方式相同。

代码语言:javascript
复制
chart.on("click", clickHandler);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28552087

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档