FormidableLabs / victory

A collection of composable React components for building interactive data visualizations
http://commerce.nearform.com/open-source/victory/
Other
10.96k stars 526 forks source link

Events across components #267

Closed boygirl closed 8 years ago

boygirl commented 8 years ago

Figure out how to coordinate events and side-effects between components. i.e. clicking on an axis tick and highlighting all data components at that x-value.

joshburgess commented 8 years ago

This one is super important to me and seems a bit difficult so far. Currently using Recharts because they've finished the Tooltip already, but they also haven't done anything yet for coordination across charts. I'm having a tough time trying to use brushing and showing Tooltips across all components simultaneously on hover.

Here's a good example of how the synced hover event across components can be really useful:

http://projects.fivethirtyeight.com/election-2016/delegate-targets/

Would also be great to have a single brush/viewfinder control to be able to zoom in/out of all charts at the same time.

EDIT: Maybe crossfilter could be useful?

boygirl commented 8 years ago

@joshburgess what great timing! I'm polishing up shared events for release as we speak. Here's a sneak peak at how the API will work. https://gist.github.com/boygirl/367b76ab7d6144f43ce3e6a5228fde40

I haven't built anything like tooltip on top of it yet, but the flexibility should be there to get something started. If you have a wish list of requirements, or suggestions about how a tooltip across components should be defined in terms of an api, I would love to hear more ideas here https://github.com/FormidableLabs/victory/issues/83

joshburgess commented 8 years ago

@boygirl Nice. Just to be clear, these shared events can be across charts, not just across components within a single chart?

For example, you could click a coordinate on the chart (or hover over it producing a tooltip later) and have it simultaneously fire the same event in the same position on the other charts on the page if desired? The main thing for me is being able to highlight that point across charts for comparison purposes as it accomplishes the same thing as a chart with multiple y-axes without the confusion/incorrect correlations that can be drawn from looking at different data metrics on a single chart with multiple y-axes (data series lines intersecting only because of scale, etc.). Besides highlighting the point, we would want to show the corresponding data to that point somewhere, whether in individual Tooltips on each chart, aggregated into a single Tooltip on the clicked/hovered over chart, or just dynamically updating the data in a fixed location somewhere else above/below the chart.

I'll try to think of any comments to leave on the Tooltips issue.

boygirl commented 8 years ago

That's right. The VictorySharedEvents wrapper will coordinate events between victory components regardless of where they are nested (but deep nesting gets expensive). VictoryChart will use VictorySharedEvents with its events prop automatically, so this will be opaque in the simple case

stuthib commented 6 years ago

This is very useful. But I am not able to get this to work. I have two scatter charts. Hover on one should mutate that scatter point along all the scatter charts. I used the VictorySharedEvents, but the events don't seem to get triggered. Trying to de it in the below way, am I missing anything?


<VictorySharedEvents
events={[
{
      childName: ["scatter_wp","scatter_cc"], 
      target: "data", 
      eventKey: 1,
      eventHandlers: {
      onMouseOver: (evt,data) => {
console.log('mouse over');
          const clickIndex = data.index;
          return [
            {
              childName: "wp_scatter"
              mutation: (props) => {
                return (props.index === clickIndex) && (props.data[clickIndex].y !== null) ?
                                                                  {style: {fill: "#000",
                                                                   strokeWidth: 1.5,
                                                                   stroke: wp_trend_color,
                                                                   width: 0.5,
                                                                   fillOpacity: 0.8}} : null;
              }
            },
            {
              childName: "cc_scatter"
              mutation: (props) => {
                return (props.index === clickIndex) && (props.data[clickIndex].y !== null) ?
                                                                  {style: {fill: "#000",
                                                                   strokeWidth: 1.5,
                                                                   stroke: cc_trend_color,
                                                                   width: 0.5,
                                                                   fillOpacity: 0.8}} : null;
              }
            }];
        },
      } }
  ]}>
  <VictoryScatter
    name="scatter_wp"
    style={{ data: { fill: "transparent"} }}
    size={4}
    data={data1}
  />
  <VictoryScatter
    name="scatter_cc"
    style={{ data: { fill: "transparent"} }}
    size={4}
    data={data2}/></VictorySharedEvents>```
boygirl commented 6 years ago

@stuthib I think something might be going wrong with the conditional logic you are using for your mutation. The props argument in the mutation function refers the the props that are passed to a single Point rendered by VictoryScatter, so rather than data they will have datum. The other issue I see is that you've set eventKey: 1. if you do that, the events you've defined will only be attached to a single point in each chart. I'm not sure whether you intended that.

stuthib commented 6 years ago

I don't see the log in onMouseOver, and that seems like the event-handler is not triggered. I am using VictorySharedEvents inside VictoryChart. Is that allowed?