在D3中:
我试图使用可重用图表模式实现一个图表,它允许我添加在实际图表之外处理的事件。例如,我有一个简单的条形图,在那里我可以点击每个单独的条形图。现在,我希望能够从创建图表实例的地方处理它,而不是仅仅处理图表组件中的单击事件。例如,我希望编辑与单击的bar元素相对应的数据,或者根据我单击的条形图的位置更新其他元素的位置。为了尽可能保持图表组件的模块化和独立性,我不希望在其中完成某些任务。
我想出了一个非常直截了当的解决方案,但我觉得必须有一个更好的解决方案。通过这种方式,我必须解释外部世界可能感兴趣的每一个可能的事件。JSFiddle
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;
}是否有任何标准的方法/最佳实践来处理这种情况?还是说这不是一种普遍的情况?
任何帮助都很感激!
发布于 2015-02-17 07:30:47
您要寻找的是在核心应用程序代码和可以重用的代码之间创建一个分离。这是一个好主意,因为它使应用程序的代码保持较小,使您更容易更改它并将其向前移动。在可重用的图表中,您希望发送一个非常通用的事件,例如clicked,而在应用程序中,您需要这些事件非常特定于您的域,例如addSugar。
你需要两种原料:d3.dispatch和d3.rebind。前者帮助您创建一个清晰的内部API,而后者帮助您将分派的事件公开给外部世界。
到这里来找这个的示例。你想要寻找的是三件事:
var myDispatch = d3.dispatch('myclick', 'mydrag')myDispatch.myclick(argumentsyouwanttopass)return d3.rebind(_chart, myDispatch, "on");myChart.on('myclick', function(){})因此,重写的示例如下所示:
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)等。
发布于 2015-02-16 23:47:58
让它更可重用和适用于任何可能的事件的一个想法是定义一个handler数组。这类似于d3本身。这是一个更新小提琴
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元素的方式相同。
chart.on("click", clickHandler);https://stackoverflow.com/questions/28552087
复制相似问题