简体   繁体   中英

tooltips on grouped bar charts in vega (using group marks)

I'm using vega to create a grouped bar chart and I would want to make some numbers (in my label data field) appear when I hover my mouse over one bar or a subgroup of bars. The json object below seems to work, but it shows all the number of all the bars when I move over a part of the graph.

{
  "scales": [
    {
      "padding": 0.2, 
      "range": "height", 
      "type": "ordinal", 
      "domain": {
        "field": "category", 
        "data": "table"
      }, 
      "name": "cat"
    }, 
    {
      "domain": {
        "field": "value", 
        "data": "table"
      }, 
      "name": "val", 
      "range": "width", 
      "type": "linear", 
      "round": "true", 
      "nice": "true"
    }, 
    {
      "range": "category20", 
      "type": "ordinal", 
      "domain": {
        "field": "position", 
        "data": "table"
      }, 
      "name": "color"
    }
  ], 
  "axes": [
    {
      "tickSize": 0, 
      "scale": "cat", 
      "type": "y", 
      "tickPadding": 8
    }, 
    {
      "scale": "val", 
      "type": "x"
    }
  ], 
  "signals": [
    {
      "name": "tooltip",
      "init": {},
      "streams": [
        {"type": "rect:mouseover", "expr": "datum"},
        {"type": "rect:mouseout", "expr": "{}"}
      ]
    }
  ],
  "predicates": [
    {
      "name": "tooltip", "type": "==", 
      "operands": [{"signal": "tooltip._id"}, {"arg": "id"}]
    }
  ],  
  "height": 800, 
  "width": 600, 
  "marks": [
    {
      "from": {
        "data": "table", 
        "transform": [
          {
            "type": "facet", 
            "groupby": [
              "category"
            ]
          }
        ]
      }, 
      "marks": [
        {
          "type": "rect", 
          "name": "bars", 
          "properties": {
            "enter": {
              "y": {
                "field": "position", 
                "scale": "pos"
              }, 
              "x": {
                "field": "value", 
                "scale": "val"
              }, 
              "x2": {
                "scale": "val", 
                "value": 0
              }, 
              "fill": {
                "field": "position", 
                "scale": "color"
              }, 
              "height": {
                "band": "true", 
                "scale": "pos"
              }
            }
          }
        }, 
        {
          "from": {
            "mark": "bars"
          }, 
          "type": "text", 
          "properties": {
            "enter": {
              "align": {"value": "center"},
              "fill": {"value": "#333"}
            },
            "update": {
              "x": { "field": "x2"},
              "dy": {"field":"height", "mult": 0.5},
              "y": {"field":"y"},
              "text": {"field": "datum.label"},
              "align": {"value":"center"},
              "baseline":{"value":"middle"},
              "fillOpacity": {
                "rule": [
                  {
                    "predicate": {"name": "tooltip", "id": {"value": null}},
                    "value": 0
                  },
                  {"value": 1}
                ]
              }
            }
          }
        }
      ], 
      "type": "group", 
      "properties": {
        "enter": {
          "y": {
            "field": "key", 
            "scale": "cat"
          }, 
          "height": {
            "band": "true", 
            "scale": "cat"
          }
        }
      }, 
      "scales": [
        {
          "range": "height", 
          "type": "ordinal", 
          "name": "pos", 
          "domain": {
            "field": "position"
          }
        }
      ]
    }
  ], 
  "data": [
    {
      "values": [
        {
          "category": "A", 
          "position": 1, 
          "value": 1661.0, 
          "label": 40.0
        }, 
        {
          "category": "A", 
          "position": 2, 
          "value": 2928.0, 
          "label": 35.0
        }, 
        {
          "category": "A", 
          "position": 3, 
          "value": 9010.0, 
          "label": 69.0
        }, 
        {
          "category": "A", 
          "position": 4, 
          "value": 6459.0, 
          "label": 97.0
        }, 
        {
          "category": "B", 
          "position": 1, 
          "value": 1022.0, 
          "label": 39.0
        }, 
        {
          "category": "B", 
          "position": 2, 
          "value": 1185.0, 
          "label": 33.0
        }, 
        {
          "category": "B", 
          "position": 3, 
          "value": 567.0, 
          "label": 60.0
        }, 
        {
          "category": "B", 
          "position": 4, 
          "value": 759.0, 
          "label": 84.0
        }
      ], 
      "name": "table"
    }
  ]
} 

I also tried to use signals in the mark block as shown below, but this doens't give me the desired result (all numbers are shown stacked on top of each other, unreadable).

  {
      "from": {
        "mark": "bars"
      }, 
      "type": "text", 
      "properties": {
        "enter": {
          "align": {"value": "center"},
          "fill": {"value": "#333"}
        },
        "update": {
          "x": { "signal": "tooltip.x2"},
          "dy": {"field":"height", "mult": 0.5},
          "y": {"signal":"tooltip.y"},
          "text": {"field": "datum.label"},
          "align": {"value":"center"},
          "baseline":{"value":"middle"},
          "fillOpacity": {
            "rule": [
              {
                "predicate": {"name": "tooltip", "id": {"value": null}},
                "value": 0
              },
              {"value": 1}
            ]
          }
        }
      }
    }

Can anyone help out how to get the desired result and to understand how the data is passed of a (sub)mark to that signal?

I solved the issue by specifying three predicates, one that checks if datum.position equals the position given by the tooltip's signal datum. Another predicate for checking the category and a last predicate that checks both these conditions. When you hoover your mouse over a bar in the chart and the position and category datum of that bar are the same as in the tooltip's signal, the text is made opaque, otherwise it remains transparent.

{
  "scales": [
    {
      "padding": 0.2, 
      "range": "height", 
      "type": "ordinal", 
      "domain": {
        "field": "category", 
        "data": "table"
      }, 
      "name": "cat"
    }, 
    {
      "domain": {
        "field": "value", 
        "data": "table"
      }, 
      "name": "val", 
      "range": "width", 
      "type": "linear", 
      "round": "true", 
      "nice": "true"
    }, 
    {
      "range": "category20", 
      "type": "ordinal", 
      "domain": {
        "field": "position", 
        "data": "table"
      }, 
      "name": "color"
    }
  ], 
  "axes": [
    {
      "tickSize": 0, 
      "scale": "cat", 
      "type": "y", 
      "tickPadding": 8
    }, 
    {
      "scale": "val", 
      "type": "x"
    }
  ], 
  "signals": [
    {
      "name": "tooltip",
      "init": {},
      "streams": [
        {"type": "rect:mouseover", "expr": "datum"},
        {"type": "rect:mouseout", "expr": "{}"}
      ]
    }
  ],
  "predicates": [
    {
      "name": "isPosition", "type": "==", 
      "operands": [{"signal": "tooltip.position"}, {"arg": "position"}]
    },
    {
      "name": "isCategory", "type": "==", 
      "operands": [{"signal": "tooltip.category"}, {"arg": "category"}]
    },
    {
      "name": "iftooltip", "type": "and", 
      "operands": [{"predicate": "isPosition"}, {"predicate": "isCategory"}]
    }
  ],  
  "height": 800, 
  "width": 600, 
  "marks": [
    {
      "from": {
        "data": "table", 
        "transform": [
          {
            "type": "facet", 
            "groupby": [
              "category"
            ]
          }
        ]
      }, 
      "marks": [
        {
          "type": "rect", 
          "name": "bars", 
          "properties": {
            "enter": {
              "y": {
                "field": "position", 
                "scale": "pos"
              }, 
              "x": {
                "field": "value", 
                "scale": "val"
              }, 
              "x2": {
                "scale": "val", 
                "value": 0
              }, 
              "fill": {
                "field": "position", 
                "scale": "color"
              }, 
              "height": {
                "band": "true", 
                "scale": "pos"
              }
            }
          }
        }, 
        {
          "from": {
            "mark": "bars"
          }, 
          "type": "text", 
          "properties": {
            "enter": {
              "align": {"value": "center"},
              "fill": {"value": "#333"}
            },
            "update": {
              "x": { "field": "x2","offset":-10},
              "y": {"field":"y"},
              "dy": {"field": "height", "mult": 0.5},
              "text": {"signal": "tooltip.label"},
              "align": {"value":"center"},
              "baseline":{"value":"middle"},
              "fillOpacity": {
                "rule": [
                {
                  "predicate": {"name": "iftooltip", "position": {"field": "datum.position"},"category":{"field":"datum.category"}},
                  "value": 1
                },
                {"value": 0}
            ]}
            }
          }
        }
      ], 
      "type": "group", 
      "properties": {
        "enter": {
          "y": {
            "field": "key", 
            "scale": "cat"
          }, 
          "height": {
            "band": "true", 
            "scale": "cat"
          }
        }
      }, 
      "scales": [
        {
          "range": "height", 
          "type": "ordinal", 
          "name": "pos", 
          "domain": {
            "field": "position"
          }
        }
      ]
    }
  ], 
  "data": [
    {
      "values": [
        {
          "category": "A", 
          "position": 1, 
          "value": 1661.0, 
          "label": 40.0
        }, 
        {
          "category": "A", 
          "position": 2, 
          "value": 2928.0, 
          "label": 35.0
        }, 
        {
          "category": "A", 
          "position": 3, 
          "value": 9010.0, 
          "label": 69.0
        }, 
        {
          "category": "A", 
          "position": 4, 
          "value": 6459.0, 
          "label": 97.0
        }, 
        {
          "category": "B", 
          "position": 1, 
          "value": 1022.0, 
          "label": 39.0
        }, 
        {
          "category": "B", 
          "position": 2, 
          "value": 1185.0, 
          "label": 33.0
        }, 
        {
          "category": "B", 
          "position": 3, 
          "value": 567.0, 
          "label": 60.0
        }, 
        {
          "category": "B", 
          "position": 4, 
          "value": 759.0, 
          "label": 84.0
        }
      ], 
      "name": "table"
    }
  ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM